IDShort LinkTitleDescriptionCoverCategoryTagsAuthor IDStatusOG ImageLinkHtml
65dae1e6159e9a0197193db3project-astro-blogAstro BlogAstro blog with Starlight template
project
opensource
65c9f17ccc3a7831bb5612caPUBLISHED00
https://astro.vio.vin/2024年02月25日2024年02月25日Null
65da05d4c582f1a749dc390fscreen-cmd-noteScreen Command Notenull
short
codesnap
65c9f17ccc3a7831bb5612caPUBLISHED00
2024年02月24日2024年02月27日Null
65d46c4fcf67d3feaff09135bos-plugin-listBos Plugin Listnull
short
bos
65c9f17ccc3a7831bb5612caPUBLISHED130
2024年02月20日2024年03月01日Generated
65d36fcd17b26f57b627c473blog-theme介绍一些博客主题some astro, nuxt blog template
article
article
65c9f17ccc3a7831bb5612caPUBLISHED830
2024年02月19日2024年03月01日Generated
65d07718f25ee75012854bf9nuxt-fullstack我的第一个Nuxt全栈项目关于此网站的介绍
article
65c9f17ccc3a7831bb5612caPUBLISHED1450
2024年02月17日2024年03月01日Generated
65cefa7ee723b4f68e09c78etest-publish-4testdesc
article
test
65c9f17ccc3a7831bb5612caDELETED00
2024年02月16日2024年02月16日Null
65cefa34e723b4f68e09c787test-publish-3testdesc
article
testarticle
65c9f17ccc3a7831bb5612caDELETED00
2024年02月16日2024年02月16日Null
65cef7e9e723b4f68e09c711test-publish-2testdesc
article
testtech
65c9f17ccc3a7831bb5612caDELETED10
2024年02月16日2024年02月16日Null
65ce48965b1085b10ed01fecuse-nuxt-scheduler在Nuxtjs中执行定时任务Create scheduled jobs with human readable time settings.
article
Nuxt.js
65c9f17ccc3a7831bb5612caPUBLISHED210
2024年02月15日2024年02月29日Generated
65cdaf6a8b310acb69c5970atest-publish-1Test Publish Updateddesc Updated
article
testcodesnapNuxt.jstech
65c9f17ccc3a7831bb5612caDELETED10
2024年02月15日2024年02月15日Null
65ca3152912f6564d5af08a0use-data-fetchData Fetch in Nuxt.jsNuxt中如何进行数据请求,useFetch、$fetch、useAsyncData如何使用。
article
Nuxt.js
65c9f17ccc3a7831bb5612caPUBLISHED640
2024年02月10日2024年03月01日Generated
65ca3152912f6564d5af089fuse-graphqlHow to build a GraphQL API applicationAn example,Show how to build an API using Spring Boot and Graph QL.
article
SpringBootGraphQL
65c9f17ccc3a7831bb5612caPUBLISHED1160
2024年02月07日2024年02月29日Generated
65ca3152912f6564d5af089euse-puppeteer使用无界面浏览器生成网页截图_使用Docker部署一个无界面浏览器,用于生成网页截图,并使用API远程调用
article
tech
65c9f17ccc3a7831bb5612caPUBLISHED1810
2024年02月06日2024年02月29日Generated
65ca3152912f6564d5af089d2023-summary2023 Year-end summary2023 Year-end summary,2023年终总结
article
article
65c9f17ccc3a7831bb5612caPUBLISHED920
2023年12月12日2024年02月28日Generated
65ca3152912f6564d5af089cmy-ipMyIPA IP Toolbox. Easy to check what's your IPs, IP informations, check for DNS leaks, examine WebRTC connections, and test website.
project
opensource
65c9f17ccc3a7831bb5612caPUBLISHED20
https://myip.lnbiuc.com/2023年12月06日2024年02月17日Null
65ca3152912f6564d5af089baoplogAopLog
short
codesnapaop
65c9f17ccc3a7831bb5612caPUBLISHED210
2023年12月04日2024年03月01日Generated
65ca3152912f6564d5af089abos-plugin-templateBos Plugin TemplateBos Plugin Template
short
bos
65c9f17ccc3a7831bb5612caPUBLISHED200
2023年12月04日2024年02月28日Generated
65ca3152912f6564d5af0899blog-bug-trackBlog BUG Track记录目前Blog存在的bug和修复计划
short
bug
65c9f17ccc3a7831bb5612caPUBLISHED200
2023年12月02日2024年02月28日Generated
65ca3152912f6564d5af0898singleton-patternSingleton PatternSingleton Pattern Template
short
codesnap
65c9f17ccc3a7831bb5612caPUBLISHED170
2023年12月01日2024年02月27日Generated
65ca3152912f6564d5af0897bos-plugin-lifecyleBos Plugin lifecycle金蝶Bos中各类插件执行顺序
short
bos
65c9f17ccc3a7831bb5612caPUBLISHED170
2023年11月28日2024年02月27日Generated
65ca3152912f6564d5af0896proxy-settingsProxy Settings
short
npm
65c9f17ccc3a7831bb5612caPUBLISHED310
2023年11月27日2024年03月01日Generated
65ca3152912f6564d5af0895project-umamiUmami AnalyticsUmami Analytics for this site.
project
umami
65c9f17ccc3a7831bb5612caPUBLISHED20
https://umami.vio.vin/share/ZxMIwBCbR54s3qvu/vio.vin2023年11月27日2024年02月28日Null
65ca3152912f6564d5af0894project-musicYesPlayMusicA visually stunning third-party Netease Cloud Music player.
project
opensource
65c9f17ccc3a7831bb5612caDELETED20
2023年11月27日2024年02月15日Null
65ca3152912f6564d5af0893project-live-roomLive Stream RoomMy live streaming platform - a cutting-edge project that enables seamless live broadcasting for up to 5 simultaneous streamers.
project
Nuxt.jsTencentCloud
65c9f17ccc3a7831bb5612caPUBLISHED20
https://live.vio.vin/2023年11月27日2024年02月17日Null
65ca3152912f6564d5af0892project-my-blogNuxt Fullstock BlogMy latest blog. Build with Nuxt.js
project
Nuxt.jsSpringBoot
65c9f17ccc3a7831bb5612caPUBLISHED20
https://vio.vin/2023年11月27日2024年02月25日Null
65ca3152912f6564d5af0891mysql-commonMySQLMySQL数据库基础、MySQL架构、存储引擎、事务、锁、索引、日志等
article
mysql
65c9f17ccc3a7831bb5612caPUBLISHED640
2023年11月26日2024年03月01日Generated
65ca3152912f6564d5af0890redis-commonRedisRedis中数据类型、数据结构。
article
redis
65c9f17ccc3a7831bb5612caPUBLISHED630
2023年11月26日2024年02月27日Generated
65ca3152912f6564d5af088fdruid-configDruidDataSource ConfigDruidDataSource Config
short
druidspringboot
65c9f17ccc3a7831bb5612caPUBLISHED60
2023年11月26日2024年02月27日Generated
65ca3152912f6564d5af088eredis-cache-configRedis Cache ConfigRedis Cache Config
short
redisspringboot
65c9f17ccc3a7831bb5612caPUBLISHED60
2023年11月26日2024年02月27日Generated
65ca3152912f6564d5af088dsensitive-data-annoJava SensitiveData Annotation基于注解实现Java接口返回数据数据自动脱敏
short
java
65c9f17ccc3a7831bb5612caPUBLISHED100
2023年11月26日2024年02月27日Generated
65ca3152912f6564d5af088ctencent-sdk-useTencent SDK腾讯云文件上传至COS,短信发送
short
tencent-cloud
65c9f17ccc3a7831bb5612caPUBLISHED50
2023年11月26日2024年02月27日Generated
65ca3152912f6564d5af088bmy-springboot-confMy SpringBoot ConfigMy SpringBoot Config
short
springboot
65c9f17ccc3a7831bb5612caPUBLISHED80
2023年11月26日2024年03月01日Generated
65ca3152912f6564d5af088amy-nginx-confMy nginx.confMy nginx.conf
short
nginx
65c9f17ccc3a7831bb5612caPUBLISHED140
2023年11月26日2024年02月28日Generated
65ca3152912f6564d5af0889docker-run-scriptMy Docker run ScriptMy Docker run Script
short
docker
65c9f17ccc3a7831bb5612caPUBLISHED70
2023年11月26日2024年02月27日Generated
65ca3152912f6564d5af0888ubt-i-dockerInstall Docker on Ubuntunull
short
dockerubuntu
65c9f17ccc3a7831bb5612caPUBLISHED40
2023年11月26日2024年02月27日Generated
65ca3152912f6564d5af0887test-2test2desc asdasdasd
short
test
65c9f17ccc3a7831bb5612caDELETED30
2023年11月25日2024年02月16日Null
65ca3152912f6564d5af0886md-testMarkdown Feature TestTest new feature of Markdown
short
65c9f17ccc3a7831bb5612caPUBLISHED840
2023年11月25日2024年03月01日Generated
65ca3152912f6564d5af0885jvm-commonJVMJVM内存结构等
article
javajvm
65c9f17ccc3a7831bb5612caPUBLISHED620
2023年11月20日2024年02月27日Generated
65ca3152912f6564d5af0884java-collectionJava集合基础Java集合详解、数据结构、代码分析
article
java
65c9f17ccc3a7831bb5612caPUBLISHED160
2023年11月20日2024年02月27日Generated
65ca3152912f6564d5af0883java-commonJava基础知识面向对象,Java语言特点等
article
java
65c9f17ccc3a7831bb5612caPUBLISHED140
2023年11月20日2024年03月01日Generated
65ca3152912f6564d5af0882java-concurrentJava并发编程Java中进程、线程、线程生命周期、创建、同步、调度等问题
article
java
65c9f17ccc3a7831bb5612caPUBLISHED140
2023年11月20日2024年02月27日Generated
65ca3152912f6564d5af0881project-1Building a Scalable E-commerce PlatformExploring the architecture and technologies behind a scalable e-commerce platform.
project
65c9f17ccc3a7831bb5612caDELETED30
2023年11月15日2023年11月27日Null
65ca3152912f6564d5af0880use-frps基于frp实现windows远程桌面连接基于frp内网穿透和服务器的windows远程桌面连接最佳实践\n
article
frps
65c9f17ccc3a7831bb5612caPUBLISHED170
2023年11月10日2024年02月28日Generated
[{"_id":"65dae1e6159e9a0197193db3","shortLink":"project-astro-blog","title":"Astro Blog","description":"Astro blog with Starlight template","cover":"https://static.vio.vin/blog/2024/02/eac36c56d841ccf8f7b855c83c85d4ec0eb7d3cad8a4edcaebbf13aefcbfbdc5.png","category":"project","tags":["opensource"],"authorId":"65c9f17ccc3a7831bb5612ca","status":"PUBLISHED","views":0,"likes":0,"ogImage":"https://static.vio.vin/screenshot/2024/02/5553b803ac7d9a2195a6c6341ee081d6da66f89cd34320e8769fc3ad5f83f7a7.png","link":"https://astro.vio.vin/","createdAt":"2024-02-25T06:44:54.055Z","updatedAt":"2024-02-25T06:50:56.457Z","__v":0},{"_id":"65da05d4c582f1a749dc390f","shortLink":"screen-cmd-note","title":"Screen Command Note","description":"null","cover":"","category":"short","tags":["codesnap"],"authorId":"65c9f17ccc3a7831bb5612ca","status":"PUBLISHED","views":0,"likes":0,"ogImage":"","link":"","createdAt":"2024-02-24T15:05:56.041Z","updatedAt":"2024-02-27T03:14:46.737Z","__v":0},{"_id":"65d46c4fcf67d3feaff09135","shortLink":"bos-plugin-list","title":"Bos Plugin List","description":"null","cover":"","category":"short","tags":["bos"],"authorId":"65c9f17ccc3a7831bb5612ca","status":"PUBLISHED","views":13,"likes":0,"ogImage":"https://static.vio.vin/screenshot/2024/02/dedf9eb2f7e25a31c25fa7d9c0f1cccb9b91b164329ecef63ff49645f06df1b7.png","link":"","createdAt":"2024-02-20T09:09:35.017Z","updatedAt":"2024-03-01T16:56:28.182Z","__v":0,"html":"<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">插件类型</th>\n<th style=\"text-align:left\">基类</th>\n<th style=\"text-align:left\">插件用途</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\">动态表单插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/form/plugin/AbstractFormPlugin.html\">AbstractFormPlugin</a></td>\n<td style=\"text-align:left\">对动态表单界面进行控制</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">动态表单插件(移动端)</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/form/plugin/AbstractMobFormPlugin.html\">AbstractMobFormPlugin</a></td>\n<td style=\"text-align:left\">对移动端动态表单界面进行控制</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">单据界面插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/bill/AbstractBillPlugIn.html\">AbstractBillPlugIn</a></td>\n<td style=\"text-align:left\">对单据界面进行控制</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">单据界面插件(移动端)</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/bill/AbstractMobBillPlugIn.html\">AbstractMobBillPlugIn</a></td>\n<td style=\"text-align:left\">对移动端单据界面进行控制</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">基础资料界面插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/base/AbstractBasePlugIn.html\">AbstractBasePlugIn</a></td>\n<td style=\"text-align:left\">对基础资料界面进行控制</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">标准单据列表插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/list/plugin/AbstractListPlugin.html\">AbstractListPlugin</a></td>\n<td style=\"text-align:left\">对标准列表界面及取数进行控制</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">左树右表单据列表插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/list/plugin/AbstractTreeListPlugin.html\">AbstractTreeListPlugin</a></td>\n<td style=\"text-align:left\">左树右表单据列表,左边显示分组树、右边显示数据列表: 1. 默认会自动加载分组基础资料数据,填充在分组树; 2. 用户点击分组树节点,自动对数据列表进行过滤; 3. 选择数据比较方便,通常用于显示基础资料。 左树右表继承了标准列表的功能,增加了对分组树的管理,插件事件也做了相应的补充</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">树形基础资料列表插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/list/plugin/StandardTreeListPlugin.html\">StandardTreeListPlugin</a></td>\n<td style=\"text-align:left\">系统预置树形基础资料模板,派生自这种模板的基础资料,数据之间具有从属关系,如部门,上级部门和下级部门之间有从属关系。 列表采用左树右表。</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">单据列表插件(移动端)</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/list/plugin/AbstractMobListPlugin.html\">AbstractMobListPlugin</a></td>\n<td style=\"text-align:left\">对移动端列表界面进行控制</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">单据操作插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/entity/plugin/AbstractOperationServicePlugIn.html\">AbstractOperationServicePlugIn</a></td>\n<td style=\"text-align:left\">对单据保存、提交、审核、删除等更新数据库的过程进行控制。 退出、刷新、新建、修改、复制等大部分操作不会实时更新数据库,不支持单据操作插件。</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">单据转换插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/entity/botp/plugin/AbstractConvertPlugIn.html\">AbstractConvertPlugIn</a></td>\n<td style=\"text-align:left\">对上游单据向下游单据转换携带数据过程进行控制</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">单据反写插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/entity/botp/plugin/AbstractWriteBackPlugIn.html\">AbstractWriteBackPlugIn</a></td>\n<td style=\"text-align:left\">对下游单据向上游单据反写数据过程进行控制</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">打印插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/entity/plugin/AbstractPrintServicePlugin.html\">AbstractPrintServicePlugin</a></td>\n<td style=\"text-align:left\">打印功能进行了升级换代,推荐使用打印4.0设计器重新设计打印模板,开发打印4.0插件</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">打印4.0插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/print/core/plugin/AbstractPrintPlugin.html\">AbstractPrintPlugin</a></td>\n<td style=\"text-align:left\">对打印取数和格式化过程进行控制</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">报表取数插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/entity/report/AbstractReportListDataPlugin.html\">AbstractReportListDataPlugin</a></td>\n<td style=\"text-align:left\">实现报表取数</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">报表树构造插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/entity/report/AbstractReportTreeDataPlugin.html\">AbstractReportTreeDataPlugin</a></td>\n<td style=\"text-align:left\">实现报表树节点的构造</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">报表界面插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/report/plugin/AbstractReportFormPlugin.html\">AbstractReportFormPlugin</a></td>\n<td style=\"text-align:left\">报表界面进行控制,格式化报表数据</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">引入插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/form/plugin/impt/BatchImportPlugin.html\">BatchImportPlugin</a></td>\n<td style=\"text-align:left\">对单据引入Excel解析等过程进行控制</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">引出插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/list/plugin/AbstractListPlugin.html\">AbstractListPlugin</a></td>\n<td style=\"text-align:left\">列表引出数据时触发引出事件</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">开放API插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/bill/AbstractBillWebApiPlugin.html\">AbstractBillWebApiPlugin</a></td>\n<td style=\"text-align:left\">自定义WebApi服务对外发布,供第三方调用</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">后台任务插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/schedule/executor/AbstractTask.html\">AbstractTask</a></td>\n<td style=\"text-align:left\">由调度服务定时启动,执行定期任务</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">工作流插件</td>\n<td style=\"text-align:left\"><a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/javadoc/kd/bos/workflow/engine/extitf/IWorkflowPlugin.html\">IWorkflowPlugin</a></td>\n<td style=\"text-align:left\">对工作流执行过程进行控制</td>\n</tr>\n</tbody>\n</table>\n"},{"_id":"65d36fcd17b26f57b627c473","shortLink":"blog-theme","title":"介绍一些博客主题","description":"some astro, nuxt blog template","cover":"https://static.vio.vin/blog/2024/02/2f3c4ee1e39767ab27d4d2e7d837e9ee50ad93706412254ddc4317fcd232aeb9.png","category":"article","tags":["article"],"authorId":"65c9f17ccc3a7831bb5612ca","status":"PUBLISHED","views":83,"likes":0,"ogImage":"https://static.vio.vin/screenshot/2024/02/5bb0620b8f4ebdc3d6946add875c29d65fdb8c58f2e8253e582d637c843aab37.png","link":"","createdAt":"2024-02-19T15:12:13.858Z","updatedAt":"2024-03-01T12:17:15.972Z","__v":0,"html":"<blockquote>\n<p>如果你对本站的主题很感兴趣,在你打算使用本站主题之前,我想想你推荐一些更优秀的作品,本站是基于Nuxt + MongoDB构建,只做为博客来说有点太重型了,下面我推荐一些轻量级的SSG(服务端生成),纯静态博客方案。</p>\n</blockquote>\n<h2 id=\"astro\" tabindex=\"-1\">Astro</h2>\n<p>如果你不想看我的推荐,这里有全部的主题<a href=\"https://astro.build/themes/\">https://astro.build/themes/</a></p>\n<p>Astro powers the world's fastest websites, client-side web apps, dynamic API endpoints, and everything in-between.</p>\n<p><a href=\"https://astro.build/themes/details/ev0/\">https://astro.build/themes/details/ev0/</a></p>\n<figure><img src=\"https://static.vio.vin/blog/2024/02/8224716eef2743b6de8142446c5a2cacc343b7819a09bcb954fd264916b096cb.png\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<p><a href=\"https://astro.build/themes/details/astropod/\">https://astro.build/themes/details/astropod/</a></p>\n<figure><img src=\"https://static.vio.vin/blog/2024/02/f83984c4753e08c8fd9261063d629736e361a6c6f572e3f9a859416070bb4abc.png\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<p><a href=\"https://astro.build/themes/details/grid-portfolio/\">https://astro.build/themes/details/grid-portfolio/</a></p>\n<figure><img src=\"https://static.vio.vin/blog/2024/02/f6e38e334eed7afd72c834aa3277bb6b6b3e5841b5181e4b3270b72492126f47.png\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<p><a href=\"https://astro.build/themes/details/littlesticks-simple-blog/\">https://astro.build/themes/details/littlesticks-simple-blog/</a></p>\n<figure><img src=\"https://static.vio.vin/blog/2024/02/ebf4695958ea874ebf4a1224c2756eac69310681573617ba8b78488be19d8d3b.png\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<p><a href=\"https://astro.build/themes/details/astrofy/\">https://astro.build/themes/details/astrofy/</a></p>\n<figure><img src=\"https://static.vio.vin/blog/2024/02/e1707d87746a4f6228cbe2cd30733ffbeb5c2063994f0560049b2172bb612df9.png\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<h2 id=\"nuxt-content\" tabindex=\"-1\">Nuxt Content</h2>\n<p>这里有全部的:<a href=\"https://nuxt.com/templates\">https://nuxt.com/templates</a></p>\n<p><a href=\"https://zooper.pages.dev/\">https://zooper.pages.dev/</a></p>\n<figure><img src=\"https://static.vio.vin/blog/2024/02/cffa25fb3c1bea3b036ac5dd68f1a5a0dff01273fa191687ea836380c1a9611d.png\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n"},{"_id":"65d07718f25ee75012854bf9","shortLink":"nuxt-fullstack","title":"我的第一个Nuxt全栈项目","description":"关于此网站的介绍","cover":"https://static.vio.vin/blog/2024/02/148c65fd853188007ccc3c338c7ac8c1dfe2ae1d5111b4f661af404d6a9bf3ec.jpg","category":"article","tags":[],"authorId":"65c9f17ccc3a7831bb5612ca","status":"PUBLISHED","views":145,"likes":0,"ogImage":"https://static.vio.vin/screenshot/2024/02/e077516903fea5e4cc945afd539bd9f090d0db3a12c1d5bf34c1f3067ad4f7e9.png","link":"","createdAt":"2024-02-17T09:06:32.257Z","updatedAt":"2024-03-01T17:41:29.021Z","__v":0,"html":"<h2 id=\"%E5%89%8D%E8%A8%80\" tabindex=\"-1\">前言</h2>\n<p><div class=\"embed-responsive embed-responsive-16by9\"><iframe class=\"embed-responsive-item bilibili-player\" type=\"text/html\" width=\"100%\" height=\"490\" src=\"//player.bilibili.com/player.html?bvid=BV1PB42167ce\" frameborder=\"0\" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div></p>\n<blockquote>\n<p>我的上个网站使用的技术栈是Vue + SpringBoot,使用了一年多的时间,后来由于SPA前端对于SEO的效果不是很好,于是我决定开发第二代。</p>\n</blockquote>\n<blockquote>\n<p>相比于最初的版本,数据库使用了MySQL,新项目,我想尝试不同的技术栈,于是便使用了MongoDB,但是就开发上来说,两者并没有什么差别。前端则是在很早之前就决定使用Nuxtjs。</p>\n</blockquote>\n<blockquote>\n<p><strong>为什么后期又改称了Nuxt全栈项目?</strong></p>\n<p>主要是服务器成本问题,此次项目的部署方式是Paas,所有服务均以容器化的形式部署在Zeabur,一个按量计费的Paas平台,如果使用前后端分离的模式,需要部署5个容器,分别是:MongoDB,SpringBoot,Nuxt,ScreenShot(一个给网页截图的工具,具体可以看<a href=\"https://vio.vin/article/use-puppeteer\">这篇介绍</a>),Redis(用了一段时间之后去掉了,Redis主要用来做接口限流和数据缓存,由于数据缓存这块内容,没有使用任何框架,纯手动操作Redis,导致有很多缓存和实际数据不同步的情况,又需要通过定时任务来同步数据,最主要的是,网站数据量不大,加不加缓存接口响应时间相差不大,所以后期去掉了Redis)。按照每GB内存没分钟0.00023刀来计算,每个月超不多会产生10刀的服务器成本,于是便有了精简结构,改成Nuxt全栈项目的想法。</p>\n</blockquote>\n<blockquote>\n<p>从开始改造到结束总共花了5-6天时间,其中接口方面几乎没遇到什么困难,唯一遇到的问题出在文件上传上,我对于Node环境下的文件操作不熟悉,起初文件以二进制的格式传到后端,之后需要调用Cloudflare Works上传到Clouflare R2存储桶,我一直不不知道为啥,上传之后的文件格式仍然是二进制,请求返回的内容是一堆数字。折麽了一天之后,改成使用Amazon S3的上传API上传,问题得以解决。</p>\n</blockquote>\n<h2 id=\"%E6%8A%80%E6%9C%AF%E6%A0%88\" tabindex=\"-1\">技术栈</h2>\n<p>主要:</p>\n<ul>\n<li>Nuxt:主框架</li>\n<li>MongoDB:数据存储</li>\n<li>Cloudflare R2:图片存储</li>\n<li>Giscus:评论系统</li>\n<li>NuxtUI:UI框架</li>\n</ul>\n<p>其他</p>\n<ul>\n<li>vditor:Makrdown编辑器</li>\n<li>Markdown-It:Markdown文本转HTML</li>\n<li>Tocbot:文章目录生成</li>\n<li>vue-use-fixed-header:网站Header</li>\n<li>pinia/nuxt:前端数据缓存</li>\n<li>unocss:CSS 框架</li>\n<li>async-validator:数据校验</li>\n<li>nuxt-mongoose:数据库连接</li>\n<li>nuxt-scheduler:定时任务</li>\n<li>shikiji:代码高亮</li>\n<li>@nuxtseo/module:SEO优化</li>\n<li>@nuxtjs/color-mode:主题切换</li>\n</ul>\n<h2 id=\"%E5%8A%9F%E8%83%BD\" tabindex=\"-1\">功能</h2>\n<p>除了你所能看到的页面之外,还有以下小功能:</p>\n<ul>\n<li>全文搜索</li>\n</ul>\n<figure><a href=\"https://static.vio.vin/blog/2024/02/2183ab9bfce23f50dd39994b521a44f5ea408fcab6d5fe525b2124527a7ea58e.gif\"><img src=\"https://static.vio.vin/blog/2024/02/2183ab9bfce23f50dd39994b521a44f5ea408fcab6d5fe525b2124527a7ea58e.gif\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></a></figure>\n<ul>\n<li>复制选中的文字</li>\n</ul>\n<figure><a href=\"https://static.vio.vin/blog/2024/02/ac7f1ae9cb91cbc854b3fd1f546a77a6aab9b81125b052129314a7d95075d97e.gif\"><img src=\"https://static.vio.vin/blog/2024/02/ac7f1ae9cb91cbc854b3fd1f546a77a6aab9b81125b052129314a7d95075d97e.gif\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></a></figure>\n<ul>\n<li>集成管理功能</li>\n</ul>\n<figure><a href=\"https://static.vio.vin/blog/2024/02/778bcda66ce1cd8fc5353f664ad7db688fa5ccaaeea0e8f83480531ca26e4133.gif\"><img src=\"https://static.vio.vin/blog/2024/02/778bcda66ce1cd8fc5353f664ad7db688fa5ccaaeea0e8f83480531ca26e4133.gif\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></a></figure>\n<ul>\n<li>生成友链网站截图</li>\n</ul>\n<figure><a href=\"https://static.vio.vin/blog/2024/02/795217bb78e0e06735174c020e0ad71c84c57184980c963c1de4ae0690fdc633.gif\"><img src=\"https://static.vio.vin/blog/2024/02/795217bb78e0e06735174c020e0ad71c84c57184980c963c1de4ae0690fdc633.gif\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></a></figure>\n<ul>\n<li>所见即所得的在线编辑器</li>\n</ul>\n<figure><a href=\"https://static.vio.vin/blog/2024/02/d413820eee0bb39b9df6732629ce9e757e84097658d6d8ad67a8ac8ffb2896c0.png\"><img src=\"https://static.vio.vin/blog/2024/02/d413820eee0bb39b9df6732629ce9e757e84097658d6d8ad67a8ac8ffb2896c0.png\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></a></figure>\n<h2 id=\"%E6%9C%AC%E5%9C%B0%E8%BF%90%E8%A1%8C\" tabindex=\"-1\">本地运行</h2>\n<ul>\n<li>你需要Fork这个仓库的<strong>zeabur-mongo</strong>分支</li>\n</ul>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-\"><span class=\"line\"><span>https://github.com/lnbiuc/blog-next-view</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"https://github.com/lnbiuc/blog-next-view\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<ul>\n<li>clone你Fork的仓库</li>\n<li>添加环境变量</li>\n</ul>\n<p>复制一份<code>.env</code>文件,重命名为<code>.env.local</code></p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-\"><span class=\"line\"><span># 数据库连接URI</span></span>\n<span class=\"line\"><span>MONGODB_URI=${MY_MONGODB_URI}</span></span>\n<span class=\"line\"><span># 图片浏览地址,最后不要加/</span></span>\n<span class=\"line\"><span>IMAGE_PREVIEW_URI=${IMAGE_PREVIEW_URI}</span></span>\n<span class=\"line\"><span># 网页截图地址,最后不要加/</span></span>\n<span class=\"line\"><span>SCREEN_URL=${SCREEN_URL}</span></span>\n<span class=\"line\"><span></span></span>\n<span class=\"line\"><span># Cloudflare文件上传地址</span></span>\n<span class=\"line\"><span>R2_UPLOAD_ENDPOINT=${R2_UPLOAD_ENDPOINT}</span></span>\n<span class=\"line\"><span># ACCESS_ID</span></span>\n<span class=\"line\"><span>AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}</span></span>\n<span class=\"line\"><span># SECRET_KEY</span></span>\n<span class=\"line\"><span>AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}</span></span>\n<span class=\"line\"><span># 存储桶名称</span></span>\n<span class=\"line\"><span>R2_BUCKET_NAME=${R2_BUCKET_NAME}</span></span>\n<span class=\"line\"><span></span></span>\n<span class=\"line\"><span># JWT Key,使用随机字符串即可</span></span>\n<span class=\"line\"><span>JWT_SECRET_KEY=${JWT_SECRET_KEY}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"# 数据库连接URI\nMONGODB_URI=${MY_MONGODB_URI}\n# 图片浏览地址,最后不要加/\nIMAGE_PREVIEW_URI=${IMAGE_PREVIEW_URI}\n# 网页截图地址,最后不要加/\nSCREEN_URL=${SCREEN_URL}\n\n# Cloudflare文件上传地址\nR2_UPLOAD_ENDPOINT=${R2_UPLOAD_ENDPOINT}\n# ACCESS_ID\nAWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}\n# SECRET_KEY\nAWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}\n# 存储桶名称\nR2_BUCKET_NAME=${R2_BUCKET_NAME}\n\n# JWT Key,使用随机字符串即可\nJWT_SECRET_KEY=${JWT_SECRET_KEY}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<ul>\n<li>安装依赖运行</li>\n</ul>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-shell\"><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">pnpm</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> i</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">pnpm</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> dev</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"pnpm i\npnpm dev\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E5%A6%82%E4%BD%95%E9%83%A8%E7%BD%B2\" tabindex=\"-1\">如何部署</h2>\n<blockquote>\n<p>我使用了Zeabur进行部署\n<a href=\"https://zeabur.com?referralCode=lnbiuc&amp;utm_source=lnbiuc\"><img src=\"https://zeabur.com/deployed-on-zeabur-dark.svg\" alt=\"Deployed on Zeabur\" /></a></p>\n</blockquote>\n<ul>\n<li>在Zeabur创建Project</li>\n<li>创建数据库实例</li>\n</ul>\n<figure><a href=\"https://static.vio.vin/blog/2024/02/0b25696f98d61cefa0788a772080235ae1d37fb284ac667562501176e93f18eb.png\"><img src=\"https://static.vio.vin/blog/2024/02/0b25696f98d61cefa0788a772080235ae1d37fb284ac667562501176e93f18eb.png\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></a></figure>\n<figure><a href=\"https://static.vio.vin/blog/2024/02/4cdf4cbefbf6a99ebdeb580379384da535c3e5e2e9ed97720cbd9a644909b841.png\"><img src=\"https://static.vio.vin/blog/2024/02/4cdf4cbefbf6a99ebdeb580379384da535c3e5e2e9ed97720cbd9a644909b841.png\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></a></figure>\n<ul>\n<li>新建服务,使用Git仓库,选择刚才Fork的仓库</li>\n<li>设置环境变量</li>\n</ul>\n<figure><a href=\"https://static.vio.vin/blog/2024/02/5fe2a384723b41a53a165f836cf986df877758ed0e1f277321ffff0ba3ce2abf.png\"><img src=\"https://static.vio.vin/blog/2024/02/5fe2a384723b41a53a165f836cf986df877758ed0e1f277321ffff0ba3ce2abf.png\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></a></figure>\n<ul>\n<li>设置域名</li>\n</ul>\n<figure><a href=\"https://static.vio.vin/blog/2024/02/4406c7cd4c0afaab718ce5fae741ca06d7cbf1f04616679b17fdd668ee6e67a1.png\"><img src=\"https://static.vio.vin/blog/2024/02/4406c7cd4c0afaab718ce5fae741ca06d7cbf1f04616679b17fdd668ee6e67a1.png\" alt=\"image\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></a></figure>\n<ul>\n<li>CDN</li>\n</ul>\n<p>设置回源地址到你上一步设置的域名即可,推荐设置缓存时间为2小时</p>\n<h2 id=\"%E8%AF%84%E8%AE%BA%E7%B3%BB%E7%BB%9F\" tabindex=\"-1\">评论系统</h2>\n<p>评论系统基于<a href=\"https://docs.github.com/en/discussions\">GitHub Discussions</a>,fork之后需要将<code>components/Comment.vue</code>中的<code>category-id</code>,<code>repo-id</code>换成自己的,具体参看文档<a href=\"https://giscus.app/zh-CN\">https://giscus.app/zh-CN</a></p>\n<h2 id=\"changlog\" tabindex=\"-1\">Changlog</h2>\n<ul>\n<li>\n<p>2024-02-18:</p>\n<ul>\n<li>登陆生成token,数据库更新校验token</li>\n<li>更新依赖</li>\n</ul>\n</li>\n<li>\n<p>2024-02-19</p>\n<ul>\n<li>将jwt Secret Key添加到环境变量中,防止公开仓库泄漏, issue <a href=\"https://github.com/lnbiuc/blog-next-view/issues/25\">#25</a></li>\n</ul>\n</li>\n<li>\n<p>2024-02-23</p>\n<ul>\n<li>添加mdc支持</li>\n<li>优化编辑器</li>\n</ul>\n</li>\n<li>\n<p>2024-02-24</p>\n<ul>\n<li>添加更多markdown样式<a href=\"https://vio.vin/article/md-test\">article/md-test</a></li>\n<li>修改图片渲染方式</li>\n</ul>\n</li>\n<li>\n<p>2024-02-27</p>\n<ul>\n<li>提前完成markdown渲染,避免在客户端进行渲染,提升进入速度</li>\n</ul>\n</li>\n<li>\n<p>2024-03-01</p>\n<ul>\n<li>修复logout不能正确退出问题</li>\n<li>修复tag不能创建问题</li>\n<li>管理界面增加权限控制</li>\n<li>修复编辑文章不进行不自动进行预渲染问题</li>\n<li>图片增加a标签渲染</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"%E5%85%B6%E4%BB%96%E9%97%AE%E9%A2%98%E8%AF%B7%E8%AF%84%E8%AE%BA\" tabindex=\"-1\">其他问题请评论</h2>\n"},{"_id":"65cefa7ee723b4f68e09c78e","shortLink":"test-publish-4","title":"test","description":"desc","cover":"https://static.vio.vin/blog/2024/02/148c65fd853188007ccc3c338c7ac8c1dfe2ae1d5111b4f661af404d6a9bf3ec.jpg","category":"article","tags":["test"],"authorId":"65c9f17ccc3a7831bb5612ca","status":"DELETED","views":0,"likes":0,"ogImage":"","link":"","createdAt":"2024-02-16T06:02:38.881Z","updatedAt":"2024-02-16T06:05:02.495Z","__v":0},{"_id":"65cefa34e723b4f68e09c787","shortLink":"test-publish-3","title":"test","description":"desc","cover":"https://static.vio.vin/blog/2024/02/148c65fd853188007ccc3c338c7ac8c1dfe2ae1d5111b4f661af404d6a9bf3ec.jpg","category":"article","tags":["test","article"],"authorId":"65c9f17ccc3a7831bb5612ca","status":"DELETED","views":0,"likes":0,"ogImage":"","link":"","createdAt":"2024-02-16T06:01:24.556Z","updatedAt":"2024-02-16T06:05:13.062Z","__v":0},{"_id":"65cef7e9e723b4f68e09c711","shortLink":"test-publish-2","title":"test","description":"desc","cover":"https://static.vio.vin/blog/2024/02/b2de7a2e5028bbb07fe6bd187b302294d4db9e9f3066121dca38797464e5252a.jpg","category":"article","tags":["test","tech"],"authorId":"65c9f17ccc3a7831bb5612ca","status":"DELETED","views":1,"likes":0,"ogImage":"","link":"","createdAt":"2024-02-16T05:51:37.126Z","updatedAt":"2024-02-16T06:05:42.951Z","__v":0},{"_id":"65ce48965b1085b10ed01fec","shortLink":"use-nuxt-scheduler","title":"在Nuxtjs中执行定时任务","description":"Create scheduled jobs with human readable time settings.","cover":"https://static.vio.vin/blog/2024/02/0f27d9215d90ab8aacef4073c2b0b53be4cd25587663f476c1b613f670f5f22a.jpg","category":"article","tags":["Nuxt.js"],"authorId":"65c9f17ccc3a7831bb5612ca","status":"PUBLISHED","views":21,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/782288c7d68a2bba0be2e225fe1fefc06442b223e31df3edd83abc631026ea56.png","link":"","createdAt":"2024-02-15T17:23:34.070Z","updatedAt":"2024-02-29T17:52:37.894Z","__v":0,"html":"<blockquote>\n<p>后端执行定时任务非常容易,只需要在方法上加上<code>@Scheduled</code>就行了,那么Nuxt全栈项目有没有办法执行定时任务呢?答案是有的</p>\n</blockquote>\n<p><a href=\"https://github.com/jurassicjs/nuxt-scheduler\">nuxt-scheduler</a>是Nuxt生态中的一个模块,用于创建定义任务。</p>\n<h2 id=\"%E5%AE%89%E8%A3%85\" tabindex=\"-1\">安装</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-shell\"><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">pnpm</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> add</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> -D</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> nuxt-scheduler</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"pnpm add -D nuxt-scheduler\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E4%BD%BF%E7%94%A8\" tabindex=\"-1\">使用</h2>\n<p>在<code>nuxt.config.ts</code>中使用</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-ts\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> default</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> defineNuxtConfig</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">({</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\tmodules: [</span></span>\n<span class=\"line\"><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\t\t'nuxt-scheduler'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\t],</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">})</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"export default defineNuxtConfig({\n\tmodules: [\n\t\t&apos;nuxt-scheduler&apos;,\n\t],\n})\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>创建<code>~/server/plugins/SchedulerTask.ts</code></p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-ts\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">import</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { useScheduler } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">from</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> '#scheduler'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">import</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { updateFriendScreenShotTask, updateArticleObImageTask } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">from</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> '~/server/task'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> default</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> defineNitroPlugin</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">\tstartScheduler</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">});</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">function</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> startScheduler</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">\tconst</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> scheduler</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useScheduler</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\tscheduler</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\t\t.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">run</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">\t\t\tupdateFriendScreenShotTask</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\t\t})</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\t\t.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">dailyAt</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">0</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">22</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\tscheduler</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\t\t.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">run</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">\t\t\tupdateArticleObImageTask</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\t\t})</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\t\t.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">dailyAt</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">1</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">3</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\tscheduler</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\t\t.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">run</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\t\t\tconsole.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">warn</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'cool beans! I run once a minutes! 😀'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\t\t})</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">\t\t.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">everyMinutes</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">1</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"import { useScheduler } from &apos;#scheduler&apos;;\nimport { updateFriendScreenShotTask, updateArticleObImageTask } from &apos;~/server/task&apos;;\n\nexport default defineNitroPlugin(() => {\n\tstartScheduler();\n});\n\nfunction startScheduler() {\n\tconst scheduler = useScheduler();\n\n\tscheduler\n\t\t.run(() => {\n\t\t\tupdateFriendScreenShotTask();\n\t\t})\n\t\t.dailyAt(0, 22);\n\n\tscheduler\n\t\t.run(() => {\n\t\t\tupdateArticleObImageTask();\n\t\t})\n\t\t.dailyAt(1, 3);\n\n\tscheduler\n\t\t.run(() => {\n\t\t\tconsole.warn(&apos;cool beans! I run once a minutes! 😀&apos;);\n\t\t})\n\t\t.everyMinutes(1);\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>使用<code>useScheduler()</code>来创建定时任务,每个<code>scheduler</code>都是一个单独执行的任务。</p>\n"},{"_id":"65cdaf6a8b310acb69c5970a","shortLink":"test-publish-1","title":"Test Publish Updated","description":"desc Updated","cover":"https://static.vio.vin/blog/2024/02/759a30bdf85dc122731b3b347845ce47dfaf601d584680c8539ed1660b2cae0d.png","category":"article","tags":["test","codesnap","Nuxt.js","tech"],"authorId":"65c9f17ccc3a7831bb5612ca","status":"DELETED","views":1,"likes":0,"ogImage":"","link":"","createdAt":"2024-02-15T06:30:02.427Z","updatedAt":"2024-02-15T07:34:15.168Z","__v":0},{"_id":"65ca3152912f6564d5af08a0","shortLink":"use-data-fetch","title":"Data Fetch in Nuxt.js","description":"Nuxt中如何进行数据请求,useFetch、$fetch、useAsyncData如何使用。","cover":"https://static.vio.vin/blog/2024/02/1730deb124e1f8aff900a711e5171868.jpg","category":"article","tags":["Nuxt.js"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2024-02-10T13:02:48.319Z","updatedAt":"2024-03-01T05:56:55.748Z","status":"PUBLISHED","views":64,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/3c893c7da837fad65ecaecdc4fd6f5c1f0569da1f60d7da9be37ca86538c36c0.png","html":"<blockquote>\n<p>Nuxt中提供了3种方式进行数据请求,分别是<code>useFetch</code>、<code>$fetch</code>、<code>useAsyncData</code>。这三种在用法,配置上有一些不同。</p>\n</blockquote>\n<p>根据<a href=\"https://nuxt.com/docs/getting-started/data-fetching\">Nuxt</a>官网的描述,Nuxt可以通过以下3种方式进行数据请求</p>\n<ul>\n<li><strong>useFetch</strong>: 适合在组件中使用,例如在组件setup中用于页面初始的数据加载。</li>\n<li><strong>$fetch</strong>: 适合在用户交互时发出请求。可以通过<code>this</code>访问,全局使用</li>\n<li><strong>useAsyncData</strong>: 配合<code>$fetch</code>使用</li>\n</ul>\n<h2 id=\"usefetch\" tabindex=\"-1\">useFetch</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-vue\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> setup</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> lang</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"ts\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">data</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> await</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useFetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">any</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'https://v1.hitokoto.cn/'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">template</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">div</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {{ data}}</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">p</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">nuxt-link</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> class</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"text-2xl text-violet\"</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> to</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"/about\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> to about</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">nuxt-link</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">p</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">div</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">template</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"<script setup lang=&quot;ts&quot;>\nconst { data } = await useFetch<any>(&apos;https://v1.hitokoto.cn/&apos;)\n</script>\n\n<template>\n <div>\n {{ data}}\n <p>\n <nuxt-link class=&quot;text-2xl text-violet&quot; to=&quot;/about&quot;>\n to about\n </nuxt-link>\n </p>\n </div>\n</template>\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p><code>useFetch</code>用于在页面组件中异步获取数据。useFetch会在组件实例化之前被调用。可以通过以下方式设置返回值的类型.</p>\n<p><code>useFetch</code>的第二个参数可以添加一些自定义配置,<a href=\"https://nuxt.com/docs/api/composables/use-fetch#params\">可用的配置列表</a>,例如自定义header等。这里主要使用的是<code>getCachedData</code>。</p>\n<p>以上代码会在路由切换是重新进行数据请求,然而在有些时候这是没有必要的,因为两次请求的数据相同的,基于此,可以考虑在客户端缓存请求到的数据。</p>\n<p>在以前,缓存数据可以通过<code>pinia</code>、<code>localstorage</code>等方式进行缓存,但是这些方式都需要单独进行配置,Nuxt3.8中提供了客户端请求数据缓存的功能,可以在配置中使用该功能,具体代码如下。</p>\n<p>注意需要使用此功能需要开启<code>payloadExtraction</code></p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-ts\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> default</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> defineNuxtConfig</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">({</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // ...</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> experimental: {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> payloadExtraction: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // ...</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">})</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"export default defineNuxtConfig({\n // ...\n experimental: {\n payloadExtraction: true,\n },\n // ...\n})\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-vue\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> setup</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> lang</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"ts\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> nuxtApp</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useNuxtApp</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">data</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> await</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useFetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">any</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'https://blog-api.vio.vin/api/v1/tags/all'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> method: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'GET'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> timeout: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">3000</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> headers: {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Accept: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'application/json'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> getCachedData</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">key</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> nuxtApp.payload.data[key] </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">||</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> nuxtApp.static.data[key]</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">})</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"<script setup lang=&quot;ts&quot;>\nconst nuxtApp = useNuxtApp()\nconst { data } = await useFetch<any>(&apos;https://blog-api.vio.vin/api/v1/tags/all&apos;, {\n method: &apos;GET&apos;,\n timeout: 3000,\n headers: {\n Accept: &apos;application/json&apos;,\n },\n getCachedData(key) {\n return nuxtApp.payload.data[key] || nuxtApp.static.data[key]\n },\n})\n</script>\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>由于Nuxt会讲数据缓存到<code>nuxtApp.payload</code>中,所以可以直接从缓存中读取数据。</p>\n<p>除此之外,还可以进行更精细化的控制,例如设置缓存过期时间,Nuxt并没有提供这一功能,可以通过<code>transform</code>配置,在响应的数据中添加响应时间来判断缓存的数据是否过期。如果过期,直接return,<code>useFetch</code>会重新请求数据,否则返回缓存中的数据,具体代码如下:</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-vue\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> setup</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> lang</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"ts\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> nuxtApp</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useNuxtApp</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">data</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> await</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useFetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">any</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'https://blog-api.vio.vin/api/v1/tags/all'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> method: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'GET'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> timeout: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">3000</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> headers: {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Accept: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'application/json'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> transform</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">input</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> ...</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">input,</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> fetchedAt: </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> Date</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(),</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> getCachedData</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">key</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> const</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> data</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> nuxtApp.payload.data[key] </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">||</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> nuxtApp.static.data[key]</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">!</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">data)</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> const</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> expirationDate</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> Date</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(data.fetchedAt)</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 缓存10s</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> expirationDate.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setTime</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(expirationDate.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getTime</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">+</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 10</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> *</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 1000</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> const</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> isExpired</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> expirationDate.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getTime</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Date.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">now</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (isExpired)</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> data</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">})</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"<script setup lang=&quot;ts&quot;>\nconst nuxtApp = useNuxtApp()\nconst { data } = await useFetch<any>(&apos;https://blog-api.vio.vin/api/v1/tags/all&apos;, {\n method: &apos;GET&apos;,\n timeout: 3000,\n headers: {\n Accept: &apos;application/json&apos;,\n },\n transform(input) {\n return {\n ...input,\n fetchedAt: new Date(),\n }\n },\n getCachedData(key) {\n const data = nuxtApp.payload.data[key] || nuxtApp.static.data[key]\n if (!data)\n return null\n\n const expirationDate = new Date(data.fetchedAt)\n // 缓存10s\n expirationDate.setTime(expirationDate.getTime() + 10 * 1000)\n const isExpired = expirationDate.getTime() < Date.now()\n if (isExpired)\n return null\n return data\n },\n})\n</script>\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%24fetch\" tabindex=\"-1\">$fetch</h2>\n<p>用于在用户交互时发送请求,<code>$fetch</code>不支持缓存配置。</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-vue\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> setup</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> lang</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"ts\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">async</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> function</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> fetchData</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> const</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">data</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> await</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> $fetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'https://blog-api.vio.vin/api/v1/tags/all'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> console.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">log</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(data)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">template</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">div</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">a</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">click</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">fetchData</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>fetch data&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">a</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">div</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">template</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"<script setup lang=&quot;ts&quot;>\nasync function fetchData() {\n const { data } = await $fetch(&apos;https://blog-api.vio.vin/api/v1/tags/all&apos;)\n console.log(data)\n}\n</script>\n\n<template>\n <div>\n <a @click=&quot;fetchData&quot;>fetch data</a>\n </div>\n</template>\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"useasyncdata\" tabindex=\"-1\">useAsyncData</h2>\n<p>用于处理多个请求,可配置相当于同时发起多个<code>useFetch</code>。<code>useAsyncData</code>最常用的方式是配合<code>$fetch</code>发起多个请求,例如:</p>\n<p><code>useAsyncData</code>的第一个参数是用于缓存数据的key</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-vue\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> setup</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">data</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">discounts</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">pending</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> await</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useAsyncData</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'cart-discount'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">async</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> () </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> const</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> [</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">coupons</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">offers</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">] </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> await</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> Promise</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">all</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">([</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> $fetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'/cart/coupons'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">),</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> $fetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'/cart/offers'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ])</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { coupons, offers }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">})</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\">// discounts.value.coupons</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\">// discounts.value.offers</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"<script setup>\nconst { data: discounts, pending } = await useAsyncData(&apos;cart-discount&apos;, async () => {\n const [coupons, offers] = await Promise.all([\n $fetch(&apos;/cart/coupons&apos;),\n $fetch(&apos;/cart/offers&apos;)\n ])\n\n return { coupons, offers }\n})\n// discounts.value.coupons\n// discounts.value.offers\n</script>\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E5%85%B6%E4%BB%96%E5%8F%AF%E9%85%8D%E7%BD%AE%E9%A1%B9\" tabindex=\"-1\">其他可配置项</h2>\n<p>这里列举一下我会用到的配置项,并不是全部</p>\n<ul>\n<li><code>server</code>: <code>false</code>只在客户端执行该请求</li>\n</ul>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-vue\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> setup</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\">/* This call is performed before hydration */</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">article</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> await</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useFetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'api/article'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\">/* This call will only be performed on the client */</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">pending</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">data</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">posts</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useFetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'/api/comments'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> lazy: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> server: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">false</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">})</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"<script setup>\n/* This call is performed before hydration */\nconst { article } = await useFetch(&apos;api/article&apos;)\n\n/* This call will only be performed on the client */\nconst { pending, data: posts } = useFetch(&apos;/api/comments&apos;, {\n lazy: true,\n server: false\n})\n</script>\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<ul>\n<li><code>refresh</code>: 重新获取数据</li>\n</ul>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-vue\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> setup</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> lang</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"ts\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">data</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">error</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">execute</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">refresh</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> await</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useFetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'/api/users'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">template</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">div</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">p</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>{{ data }}&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">p</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">button</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">click</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">refresh</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>Refresh data&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">button</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">div</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">template</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"<script setup lang=&quot;ts&quot;>\nconst { data, error, execute, refresh } = await useFetch(&apos;/api/users&apos;)\n</script>\n\n<template>\n <div>\n <p>{{ data }}</p>\n <button @click=&quot;refresh&quot;>Refresh data</button>\n </div>\n</template>\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<ul>\n<li><code>watch</code>: 值更新时重新获取数据,可用于搜索框</li>\n</ul>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-vue\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> setup</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> lang</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"ts\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> id</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> ref</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">1</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">data</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">error</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">refresh</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> await</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useFetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'/api/users'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, {</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> /* Changing the id will trigger a refetch */</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> watch: [id]</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">})</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"<script setup lang=&quot;ts&quot;>\nconst id = ref(1)\n\nconst { data, error, refresh } = await useFetch(&apos;/api/users&apos;, {\n /* Changing the id will trigger a refetch */\n watch: [id]\n})\n</script>\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"proxy\" tabindex=\"-1\">proxy</h2>\n<p>一般来说,请求的domain可能是不固定的,此时需要使用到代理转发功能,nuxt继承了网络框架nitor,可以通过配置来实现转发功能。</p>\n<p>同时也能解决跨域问题。具体配置如下:</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-ts\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> default</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> defineNuxtConfig</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">({</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // ...</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> routeRules: {</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 匹配所有api开头的请求,将/api/后的参数代理到http://blog-next-api/api/**</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 例如请求: '/api/v1/tags/all' === 'http://blog-next-api/api/v1/tags/all'</span></span>\n<span class=\"line\"><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> '/api/**'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: { proxy: { to: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'http://blog-next-api/api/**'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } },</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // ...</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">})</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"export default defineNuxtConfig({\n // ...\n routeRules: {\n // 匹配所有api开头的请求,将/api/后的参数代理到http://blog-next-api/api/**\n // 例如请求: &apos;/api/v1/tags/all&apos; === &apos;http://blog-next-api/api/v1/tags/all&apos;\n &apos;/api/**&apos;: { proxy: { to: &apos;http://blog-next-api/api/**&apos; } },\n // ...\n})\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E8%AF%B7%E6%B1%82%E5%B0%81%E8%A3%85\" tabindex=\"-1\">请求封装</h2>\n<p>有时候需要对请求进行全局拦截,加入请求前预处理和请求后检查请求状态,这里提供两种配置方式:</p>\n<h3 id=\"%E6%95%B4%E4%BD%93%E9%85%8D%E7%BD%AE\" tabindex=\"-1\">整体配置</h3>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-ts\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">import</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> type</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { FetchResponse } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">from</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> 'ofetch'</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">import</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> type</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { UseFetchOptions } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">from</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> '#app'</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\">// 自定义的响应数据结构</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> interface</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> ResOptions</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> {</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> data</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">?:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> T</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> code</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">?:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> number</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> timestamp</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">?:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> number</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">type</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> UrlType</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> string</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> type</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> HttpOption</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> UseFetchOptions</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">ResOptions</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>></span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">function</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> handleError</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">response</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> FetchResponse</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">ResOptions</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>> </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x26;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> FetchResponse</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">ResponseType</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> const</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> err</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">text</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> string</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> console.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">error</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(text)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">!</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">response._data) {</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> err</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'请求超时,服务器无响应!'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> const</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> handleMap</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { [</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">key</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> number</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">]</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> () </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> void</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 404</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: () </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> err</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'服务器资源不存在'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">),</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 500</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: () </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> err</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'服务器内部错误'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">),</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 403</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: () </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> err</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'没有权限访问该资源'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">),</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> handleMap[response.status] </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">?</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> handleMap[response.status]() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> err</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'未知错误!'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">function</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> fetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">url</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> UrlType</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">option</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> UseFetchOptions</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">ResOptions</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>>) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useFetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">ResOptions</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>>(url, {</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 请求拦截器</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> onRequest</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">({ </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">options</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }) {</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 在这里判断错误</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> options</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 响应拦截</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> onResponse</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">({ </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">response</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (response.headers.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'content-disposition'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x26;&#x26;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> response.status </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">===</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 200</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> response</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 在这里判断错误</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (response._data.code </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">!==</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 200</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> handleError</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(response)</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> Promise</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">reject</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(response._data)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 成功返回</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> response._data</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 错误处理</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> onResponseError</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">({ </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">response</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }) {</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> handleError</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(response)</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> Promise</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">reject</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(response?._data </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">??</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 合并参数</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> ...</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">option,</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> })</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\">// 自动导出</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> const</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> useHttp</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: &#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">url</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> UrlType</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">params</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">?:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> any</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">option</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">?:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> HttpOption</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> fetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(url, { method: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'get'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, params, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">...</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">option })</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> post</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: &#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">url</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> UrlType</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">body</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">?:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> any</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">option</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">?:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> HttpOption</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> fetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(url, { method: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'post'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, body, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">...</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">option })</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: &#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">url</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> UrlType</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">body</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">?:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> any</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">option</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">?:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> HttpOption</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> fetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(url, { method: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'put'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, body, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">...</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">option })</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> delete</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: &#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">url</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> UrlType</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">body</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">?:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> any</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">option</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">?:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> HttpOption</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> fetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(url, { method: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'delete'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, body, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">...</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">option })</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"import type { FetchResponse } from &apos;ofetch&apos;\nimport type { UseFetchOptions } from &apos;#app&apos;\n\n// 自定义的响应数据结构\nexport interface ResOptions<T> {\n data?: T\n code?: number\n timestamp?: number\n}\n\ntype UrlType = string\n\nexport type HttpOption<T> = UseFetchOptions<ResOptions<T>>\n\nfunction handleError<T>(response: FetchResponse<ResOptions<T>> & FetchResponse<ResponseType>) {\n const err = (text: string) => {\n console.error(text)\n }\n if (!response._data) {\n err(&apos;请求超时,服务器无响应!&apos;)\n return\n }\n const handleMap: { [key: number]: () => void } = {\n 404: () => err(&apos;服务器资源不存在&apos;),\n 500: () => err(&apos;服务器内部错误&apos;),\n 403: () => err(&apos;没有权限访问该资源&apos;),\n }\n handleMap[response.status] ? handleMap[response.status]() : err(&apos;未知错误!&apos;)\n}\n\nfunction fetch<T>(url: UrlType, option: UseFetchOptions<ResOptions<T>>) {\n return useFetch<ResOptions<T>>(url, {\n // 请求拦截器\n onRequest({ options }) {\n // 在这里判断错误\n return options\n },\n // 响应拦截\n onResponse({ response }) {\n if (response.headers.get(&apos;content-disposition&apos;) && response.status === 200)\n return response\n // 在这里判断错误\n if (response._data.code !== 200) {\n handleError<T>(response)\n return Promise.reject(response._data)\n }\n // 成功返回\n return response._data\n },\n // 错误处理\n onResponseError({ response }) {\n handleError<T>(response)\n return Promise.reject(response?._data ?? null)\n },\n // 合并参数\n ...option,\n })\n}\n\n// 自动导出\nexport const useHttp = {\n get: <T>(url: UrlType, params?: any, option?: HttpOption<T>) => {\n return fetch<T>(url, { method: &apos;get&apos;, params, ...option })\n },\n\n post: <T>(url: UrlType, body?: any, option?: HttpOption<T>) => {\n return fetch<T>(url, { method: &apos;post&apos;, body, ...option })\n },\n\n put: <T>(url: UrlType, body?: any, option?: HttpOption<T>) => {\n return fetch<T>(url, { method: &apos;put&apos;, body, ...option })\n },\n\n delete: <T>(url: UrlType, body?: any, option?: HttpOption<T>) => {\n return fetch<T>(url, { method: &apos;delete&apos;, body, ...option })\n },\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-ts\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">import</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { useHttp } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">from</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> '~/composables/useHttp'</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> async</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> function</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> getAllArticle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">pageNumber</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> number</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">pageSize</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> number</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> await</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> useHttp.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">post</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'/api/v1/articles/page'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, { pageNumber, pageSize })</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"import { useHttp } from &apos;~/composables/useHttp&apos;\n\nexport async function getAllArticle(pageNumber: number, pageSize: number) {\n return await useHttp.post(&apos;/api/v1/articles/page&apos;, { pageNumber, pageSize })\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h3 id=\"%E7%B2%BE%E7%BB%86%E5%8C%96%E9%85%8D%E7%BD%AE\" tabindex=\"-1\">精细化配置</h3>\n<p>单个请求配置</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-ts\"><span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\">// repository.ts</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">import</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> type</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { NitroFetchRequest, $Fetch } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">from</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> 'nitropack'</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\">// 定义返回类型</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">type</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> User</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> id</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> number</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> name</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> string</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> username</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> string</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> email</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> string</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> address</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> street</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> string</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> suite</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> string</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> city</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> string</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> zipcode</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> string</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> geo</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> lat</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> string</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> lng</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> string</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> };</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> };</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">};</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> const</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> userRepository</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>(</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">fetch</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> $Fetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">T</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">NitroFetchRequest</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ({</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> async</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> Promise</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">User</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">[]> {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> fetch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">User</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">[]>(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'/users'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">})</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"// repository.ts\nimport type { NitroFetchRequest, $Fetch } from &apos;nitropack&apos;\n\n// 定义返回类型\ntype User = {\n id: number;\n name: string;\n username: string;\n email: string;\n address: {\n street: string;\n suite: string;\n city: string;\n zipcode: string;\n geo: {\n lat: string;\n lng: string;\n };\n };\n};\n\nexport const userRepository = <T>(fetch: $Fetch<T, NitroFetchRequest>) => ({\n async get(): Promise<User[]> {\n return fetch<User[]>(&apos;/users&apos;)\n }\n})\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>basepath或proxy</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-ts\"><span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\">// plugins/api.ts</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> default</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> defineNuxtPlugin</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">({</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> setup</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> const</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> api</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> $fetch.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">create</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">({</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> baseURL: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">'http://blog-next-api/'</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#6A737D;--shiki-dark:#6A737D\">// useRuntimeConfig().public.apiBaseUrl</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> })</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> provide: {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> api</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">})</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"// plugins/api.ts\nexport default defineNuxtPlugin({\n setup() {\n const api = $fetch.create({\n baseURL: &apos;http://blog-next-api/&apos;, // useRuntimeConfig().public.apiBaseUrl\n })\n\n return {\n provide: {\n api\n }\n }\n }\n})\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>使用</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-vue\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> setup</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> lang</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"ts\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">$api</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useNuxtApp</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> userRepo</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> =</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> userRepository</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">($api)</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">const</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> { </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">data</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> await</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> useAsyncData</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> userRepo.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">())</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">script</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">template</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">div</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">h1</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>Users&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">h1</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {{ data }}</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">div</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">template</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"<script setup lang=&quot;ts&quot;>\nconst { $api } = useNuxtApp()\nconst userRepo = userRepository($api)\nconst { data } = await useAsyncData(() => userRepo.get())\n\n</script>\n<template>\n <div>\n <h1>Users</h1>\n {{ data }}\n </div>\n</template>\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n"},{"_id":"65ca3152912f6564d5af089f","shortLink":"use-graphql","title":"How to build a GraphQL API application","description":"An example,Show how to build an API using Spring Boot and Graph QL.","cover":"https://static.vio.vin/blog/2024/02/e63568891e8a2962e9fa7666d02cfd8a.jpeg","category":"article","tags":["SpringBoot","GraphQL"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2024-02-07T08:23:48.356Z","updatedAt":"2024-02-29T17:53:03.945Z","status":"PUBLISHED","views":116,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/317502c30cb7d73f6bfe94f8f6e41b1ac38d3a3558480a1ab4e550c82351873d.png","html":"<blockquote>\n<p>GraphQL API和Restful API类似,是一种查询数据的语言,相比于Restful API,GraphQL API在查询方面更加灵活,前后端代码编写也更加方便。本文将介绍如何构建GraphQL API应用程序,基于SpringBoot3.0。如何测试GraphQL API接口是否可用,以及前端如何调用GraphQL API接口(以Nuxt项目为例)。</p>\n</blockquote>\n<h2 id=\"what-is-graphql\" tabindex=\"-1\">What is GraphQL</h2>\n<p>以下内容摘自<a href=\"https://zh.wikipedia.org/zh-cn/GraphQL\">GraphQL Wiki</a>。</p>\n<p>GraphQL是一个开源的,面向API而创造出来的数据查询操作语言以及相应的运行环境。于2012年仍处于Facebook内部开发阶段,直到2015年才公开发布。 2018年11月7日,Facebook将GraphQL项目转移到新成立的GraphQL基金会(隶属于非营利性的Linux基金会)。</p>\n<p>GraphQL相较于REST以及其他web service架构提供了一种更加高效、强大和灵活的开发web APIs的方式。它通过由客户端根据所需定义数据结构,同时由服务端负责返回相同数据结构的对应数据的方式避免了服务端大量冗余数据的返回,但与此同时也意味着这种方式不能有效利用起查询结果的web缓存。GraphQL这种查询语言所带来的灵活性和丰富性的同时也增加了复杂性,导致简单的APIs有可能并不适合这种方式。</p>\n<h2 id=\"why-use-graphql\" tabindex=\"-1\">Why use GraphQL</h2>\n<ul>\n<li>由前端决定返回哪些数据。这对于后端需要复杂格式的JSON特别有用,前端可以自行决定需要哪些数据,不需要哪些数据,减少冗余数据同时也减少后端压力。</li>\n<li>不仅可以查询,还可以用于更新。虽然名称为Graph Query Language,但是GraphQL同样可以用于创建、更新、删除操作。</li>\n</ul>\n<h2 id=\"how-to-use\" tabindex=\"-1\">How to use</h2>\n<p>通过调用GraphQL接口,向后端发送这样的数据,注意这并不是JSON</p>\n<p>这里传入参数为article id,用于查询一篇文章</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-\"><span class=\"line\"><span>query Article {</span></span>\n<span class=\"line\"><span> article(id: \"2\") {</span></span>\n<span class=\"line\"><span> id</span></span>\n<span class=\"line\"><span> title</span></span>\n<span class=\"line\"><span> content</span></span>\n<span class=\"line\"><span> author {</span></span>\n<span class=\"line\"><span> id</span></span>\n<span class=\"line\"><span> firstName</span></span>\n<span class=\"line\"><span> lastName</span></span>\n<span class=\"line\"><span> }</span></span>\n<span class=\"line\"><span> tags {</span></span>\n<span class=\"line\"><span> id</span></span>\n<span class=\"line\"><span> name</span></span>\n<span class=\"line\"><span> description</span></span>\n<span class=\"line\"><span> }</span></span>\n<span class=\"line\"><span> }</span></span>\n<span class=\"line\"><span>}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"query Article {\n article(id: &quot;2&quot;) {\n id\n title\n content\n author {\n id\n firstName\n lastName\n }\n tags {\n id\n name\n description\n }\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>后端将根据请求中的数据结构返回对于应数据</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-json\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"data\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"article\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"2\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"title\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"title2\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"content\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"content2\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"author\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"author-2\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"firstName\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Douglas\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"lastName\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Adams\"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"tags\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: [</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"2\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"name\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Python\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"description\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Python related articles\"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"3\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"name\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"JavaScript\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"description\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"JavaScript related articles\"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ]</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"{\n &quot;data&quot;: {\n &quot;article&quot;: {\n &quot;id&quot;: &quot;2&quot;,\n &quot;title&quot;: &quot;title2&quot;,\n &quot;content&quot;: &quot;content2&quot;,\n &quot;author&quot;: {\n &quot;id&quot;: &quot;author-2&quot;,\n &quot;firstName&quot;: &quot;Douglas&quot;,\n &quot;lastName&quot;: &quot;Adams&quot;\n },\n &quot;tags&quot;: [\n {\n &quot;id&quot;: &quot;2&quot;,\n &quot;name&quot;: &quot;Python&quot;,\n &quot;description&quot;: &quot;Python related articles&quot;\n },\n {\n &quot;id&quot;: &quot;3&quot;,\n &quot;name&quot;: &quot;JavaScript&quot;,\n &quot;description&quot;: &quot;JavaScript related articles&quot;\n }\n ]\n }\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>也可以一次查询多条数据</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-\"><span class=\"line\"><span>query Article {</span></span>\n<span class=\"line\"><span> articles {</span></span>\n<span class=\"line\"><span> id</span></span>\n<span class=\"line\"><span> title</span></span>\n<span class=\"line\"><span> content</span></span>\n<span class=\"line\"><span> author {</span></span>\n<span class=\"line\"><span> id</span></span>\n<span class=\"line\"><span> firstName</span></span>\n<span class=\"line\"><span> lastName</span></span>\n<span class=\"line\"><span> }</span></span>\n<span class=\"line\"><span> tags {</span></span>\n<span class=\"line\"><span> id</span></span>\n<span class=\"line\"><span> name</span></span>\n<span class=\"line\"><span> description</span></span>\n<span class=\"line\"><span> }</span></span>\n<span class=\"line\"><span> }</span></span>\n<span class=\"line\"><span>}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"query Article {\n articles {\n id\n title\n content\n author {\n id\n firstName\n lastName\n }\n tags {\n id\n name\n description\n }\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>Reponse</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-json\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"data\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"articles\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: [</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"1\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"title\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"title1\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"content\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"content1\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"author\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"author-1\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"firstName\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Joshua\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"lastName\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Bloch\"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"tags\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: [</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"1\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"name\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Java\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"description\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Java related articles\"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"2\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"name\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Python\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"description\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Python related articles\"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"1\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"name\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Java\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"description\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Java related articles\"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ]</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"2\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"title\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"title2\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"content\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"content2\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"author\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"author-2\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"firstName\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Douglas\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"lastName\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Adams\"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"tags\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: [</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"2\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"name\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Python\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"description\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Python related articles\"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> },</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"3\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"name\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"JavaScript\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> \"description\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"JavaScript related articles\"</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ]</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ]</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"{\n &quot;data&quot;: {\n &quot;articles&quot;: [\n {\n &quot;id&quot;: &quot;1&quot;,\n &quot;title&quot;: &quot;title1&quot;,\n &quot;content&quot;: &quot;content1&quot;,\n &quot;author&quot;: {\n &quot;id&quot;: &quot;author-1&quot;,\n &quot;firstName&quot;: &quot;Joshua&quot;,\n &quot;lastName&quot;: &quot;Bloch&quot;\n },\n &quot;tags&quot;: [\n {\n &quot;id&quot;: &quot;1&quot;,\n &quot;name&quot;: &quot;Java&quot;,\n &quot;description&quot;: &quot;Java related articles&quot;\n },\n {\n &quot;id&quot;: &quot;2&quot;,\n &quot;name&quot;: &quot;Python&quot;,\n &quot;description&quot;: &quot;Python related articles&quot;\n },\n {\n &quot;id&quot;: &quot;1&quot;,\n &quot;name&quot;: &quot;Java&quot;,\n &quot;description&quot;: &quot;Java related articles&quot;\n }\n ]\n },\n {\n &quot;id&quot;: &quot;2&quot;,\n &quot;title&quot;: &quot;title2&quot;,\n &quot;content&quot;: &quot;content2&quot;,\n &quot;author&quot;: {\n &quot;id&quot;: &quot;author-2&quot;,\n &quot;firstName&quot;: &quot;Douglas&quot;,\n &quot;lastName&quot;: &quot;Adams&quot;\n },\n &quot;tags&quot;: [\n {\n &quot;id&quot;: &quot;2&quot;,\n &quot;name&quot;: &quot;Python&quot;,\n &quot;description&quot;: &quot;Python related articles&quot;\n },\n {\n &quot;id&quot;: &quot;3&quot;,\n &quot;name&quot;: &quot;JavaScript&quot;,\n &quot;description&quot;: &quot;JavaScript related articles&quot;\n }\n ]\n }\n ]\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"build-springboot-application\" tabindex=\"-1\">Build SpringBoot Application</h2>\n<p>推荐IDEA先安装GraphQL的相关插件,<a href=\"https://plugins.jetbrains.com/plugin/8097-graphql\">GraphQL</a>,该插件提供了对<code>schema.graphqls</code>文件的语法高亮支持。</p>\n<h3 id=\"%E5%88%9B%E5%BB%BA%E9%A1%B9%E7%9B%AE\" tabindex=\"-1\">创建项目</h3>\n<p>pom.xml中需要加入以下依赖项</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-xml\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">dependency</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">groupId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>org.springframework.boot&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">groupId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">artifactId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>spring-boot-starter-graphql&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">artifactId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">dependency</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">dependency</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">groupId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>org.springframework.boot&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">groupId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> &#x3C;</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">artifactId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>spring-boot-starter-web&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">artifactId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">&#x3C;/</span><span style=\"color:#22863A;--shiki-dark:#85E89D\">dependency</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">></span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"<dependency>\n <groupId>org.springframework.boot</groupId>\n <artifactId>spring-boot-starter-graphql</artifactId>\n</dependency>\n<dependency>\n <groupId>org.springframework.boot</groupId>\n <artifactId>spring-boot-starter-web</artifactId>\n</dependency>\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h3 id=\"%E5%AE%9A%E4%B9%89%E5%AE%9E%E4%BD%93%E7%B1%BB\" tabindex=\"-1\">定义实体类</h3>\n<p>实体类既可以和数据库字段对应,可以是自定义的VO。这里使用了record,也可以选择使用传统class</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> record</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> Article</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(String id, String title, String content, String authorId, String tagId) {}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> record Author (String id, String firstName, String lastName) {}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> record</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> Tag</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(String id, String name, String description) {}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"public record Article(String id, String title, String content, String authorId, String tagId) {}\n\npublic record Author (String id, String firstName, String lastName) {}\n\npublic record Tag(String id, String name, String description) {}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h3 id=\"%E6%9F%A5%E8%AF%A2%E6%95%B0%E6%8D%AE\" tabindex=\"-1\">查询数据</h3>\n<h3 id=\"%E5%AE%9A%E4%B9%89schema.graphqls\" tabindex=\"-1\">定义<code>schema.graphqls</code></h3>\n<p><code>schema.graphqls</code>文件将用于定义GraphQL模式、描述数据结构和数据之间的关系、以及客户端可以进行的操作。\n文件将定义以下内容</p>\n<ul>\n<li>类型</li>\n<li>查询</li>\n<li>关系</li>\n</ul>\n<p>以下是一个具体的<code>schema.graphqls</code>文件</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-\"><span class=\"line\"><span># 查询的接口,客户端可以访问的内容</span></span>\n<span class=\"line\"><span>type Query {</span></span>\n<span class=\"line\"><span> # id表示查询的参数,Article为下面type中定义的返回的数据结构</span></span>\n<span class=\"line\"><span> article(id: String): Article</span></span>\n<span class=\"line\"><span> # 使用[Article]表示返回的是多条数据,以数组形式返回</span></span>\n<span class=\"line\"><span> articles: [Article]</span></span>\n<span class=\"line\"><span> tag(id: String): Tag</span></span>\n<span class=\"line\"><span> tags: [Tag]</span></span>\n<span class=\"line\"><span> author(id: String): Author</span></span>\n<span class=\"line\"><span>}</span></span>\n<span class=\"line\"><span></span></span>\n<span class=\"line\"><span># 定义数据结构</span></span>\n<span class=\"line\"><span>type Author {</span></span>\n<span class=\"line\"><span> id: String</span></span>\n<span class=\"line\"><span> firstName: String</span></span>\n<span class=\"line\"><span> lastName: String</span></span>\n<span class=\"line\"><span>}</span></span>\n<span class=\"line\"><span></span></span>\n<span class=\"line\"><span># tags是多条,用[Tag]表示</span></span>\n<span class=\"line\"><span>type Article {</span></span>\n<span class=\"line\"><span> id: String</span></span>\n<span class=\"line\"><span> title: String</span></span>\n<span class=\"line\"><span> content: String</span></span>\n<span class=\"line\"><span> author: Author</span></span>\n<span class=\"line\"><span> tags: [Tag]</span></span>\n<span class=\"line\"><span>}</span></span>\n<span class=\"line\"><span></span></span>\n<span class=\"line\"><span>type Tag {</span></span>\n<span class=\"line\"><span> id: String</span></span>\n<span class=\"line\"><span> name: String</span></span>\n<span class=\"line\"><span> description: String</span></span>\n<span class=\"line\"><span>}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"# 查询的接口,客户端可以访问的内容\ntype Query {\n # id表示查询的参数,Article为下面type中定义的返回的数据结构\n article(id: String): Article\n # 使用[Article]表示返回的是多条数据,以数组形式返回\n articles: [Article]\n tag(id: String): Tag\n tags: [Tag]\n author(id: String): Author\n}\n\n# 定义数据结构\ntype Author {\n id: String\n firstName: String\n lastName: String\n}\n\n# tags是多条,用[Tag]表示\ntype Article {\n id: String\n title: String\n content: String\n author: Author\n tags: [Tag]\n}\n\ntype Tag {\n id: String\n name: String\n description: String\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h3 id=\"%E7%BC%96%E5%86%99controller\" tabindex=\"-1\">编写Controller</h3>\n<p>GraphQL同样需要通过Controller来访问。相比与MVC中使用<code>@RequsetMapping</code>,在GraphQL中应该使用<code>@QueryMapping</code>。并且该<code>@QueryMapping</code>不需要定义请求路径,以下是一个具体示例</p>\n<h4 id=\"%40querymapping\" tabindex=\"-1\">@QueryMapping</h4>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">QueryMapping</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Collection</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">Article</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">></span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> articles</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> queryService.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">listArticles</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"@QueryMapping\npublic Collection<Article> articles()\n{\n return queryService.listArticles();\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>此处方法名为<code>articles()</code>,需要和<code>schema.graphqls</code>文件中<code>type Query</code>中定义的名称相同。</p>\n<p>这样当前端发送\n<code>query Article { articles { id } }</code>时,会匹配到这一个接口。该方法返回<code>type Article</code>中所包含的所有属性,之后<code>GraphQL</code>会更具前端传入的参数,自动保留需要的数据。</p>\n<p>例如在这个示例中,前端只请求了id和title,所以只有id和title会被返回,其他的数据会被隐藏/删除。</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-\"><span class=\"line\"><span>query Article {</span></span>\n<span class=\"line\"><span> articles {</span></span>\n<span class=\"line\"><span> id</span></span>\n<span class=\"line\"><span> title</span></span>\n<span class=\"line\"><span> }</span></span>\n<span class=\"line\"><span>}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"query Article {\n articles {\n id\n title\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>查询的参数需要添加<code>@Argument</code>注解,否则会报错</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">QueryMapping</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Article </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">article</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Argument</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String id) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> queryService.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getArticleById</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(id);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"@QueryMapping\npublic Article article(@Argument String id) {\n return queryService.getArticleById(id);\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h4 id=\"%40schemamapping\" tabindex=\"-1\">@SchemaMapping</h4>\n<p><code>@QueryMapping</code>和<code>@SchemaMapping</code>是GraphQL最核心的两个注解。<code>@QueryMapping</code>用于匹配请求地址,而<code>@SchemaMapping</code>将用于构建数据关系。</p>\n<p>以一个具体的例子来说</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">QueryMapping</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Article </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">article</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Argument</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String id) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> queryService.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getArticleById</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(id);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">SchemaMapping</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Collection</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">Tag</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">></span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> tags</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Article article)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> queryService.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getTagsByArticleId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(article.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">id</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">SchemaMapping</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Author </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">author</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Article article)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> queryService.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getAuthorByAuthorId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(article.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">authorId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"@QueryMapping\npublic Article article(@Argument String id) {\n return queryService.getArticleById(id);\n}\n\n@SchemaMapping\npublic Collection<Tag> tags(Article article)\n{\n return queryService.getTagsByArticleId(article.id());\n}\n\n@SchemaMapping\npublic Author author(Article article)\n{\n return queryService.getAuthorByAuthorId(article.authorId());\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p><code>tags()</code>方法将用于查询Article关联的Tag,所以该方法的参数为<code>Article article</code>,返回数据为多条Tag。同理,author用于查询Article关联的Author,所以返回数据为Author类型。</p>\n<h3 id=\"%E4%BF%9D%E5%AD%98%E6%95%B0%E6%8D%AE\" tabindex=\"-1\">保存数据</h3>\n<h4 id=\"%E5%AE%9A%E4%B9%89schema.graphqls-1\" tabindex=\"-1\">定义<code>schema.graphqls</code></h4>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-\"><span class=\"line\"><span>type Mutation {</span></span>\n<span class=\"line\"><span> # !表示该参数为必须,:Article表示插入之后返回的数据类型</span></span>\n<span class=\"line\"><span> createArticle(article: ArticleInput!): Article</span></span>\n<span class=\"line\"><span>}</span></span>\n<span class=\"line\"><span></span></span>\n<span class=\"line\"><span>input ArticleInput {</span></span>\n<span class=\"line\"><span> title: String</span></span>\n<span class=\"line\"><span> content: String</span></span>\n<span class=\"line\"><span> authorId: String</span></span>\n<span class=\"line\"><span> tagId: String</span></span>\n<span class=\"line\"><span>}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"type Mutation {\n # !表示该参数为必须,:Article表示插入之后返回的数据类型\n createArticle(article: ArticleInput!): Article\n}\n\ninput ArticleInput {\n title: String\n content: String\n authorId: String\n tagId: String\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h4 id=\"controller\" tabindex=\"-1\">Controller</h4>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">MutationMapping</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Article </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">createArticle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Argument</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"article\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) ArticleInput article) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> createService.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">createArticle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(article);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"@MutationMapping\npublic Article createArticle(@Argument(&quot;article&quot;) ArticleInput article) {\n return createService.createArticle(article);\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h4 id=\"%E8%B0%83%E7%94%A8%E8%AF%A5%E6%8E%A5%E5%8F%A3\" tabindex=\"-1\">调用该接口</h4>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-\"><span class=\"line\"><span>mutation {</span></span>\n<span class=\"line\"><span> createArticle(</span></span>\n<span class=\"line\"><span> article: {title: \"Sample Title\", content: \"Sample Content\", authorId: \"author-3\", tagId: \"2\"}</span></span>\n<span class=\"line\"><span> ) {</span></span>\n<span class=\"line\"><span> id</span></span>\n<span class=\"line\"><span> title</span></span>\n<span class=\"line\"><span> content</span></span>\n<span class=\"line\"><span> author {</span></span>\n<span class=\"line\"><span> id</span></span>\n<span class=\"line\"><span> firstName</span></span>\n<span class=\"line\"><span> lastName</span></span>\n<span class=\"line\"><span> }</span></span>\n<span class=\"line\"><span> tags {</span></span>\n<span class=\"line\"><span> id</span></span>\n<span class=\"line\"><span> name</span></span>\n<span class=\"line\"><span> description</span></span>\n<span class=\"line\"><span> }</span></span>\n<span class=\"line\"><span> }</span></span>\n<span class=\"line\"><span>}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"mutation {\n createArticle(\n article: {title: &quot;Sample Title&quot;, content: &quot;Sample Content&quot;, authorId: &quot;author-3&quot;, tagId: &quot;2&quot;}\n ) {\n id\n title\n content\n author {\n id\n firstName\n lastName\n }\n tags {\n id\n name\n description\n }\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h3 id=\"%E5%88%A0%E9%99%A4%2F%E6%9B%B4%E6%96%B0%E6%95%B0%E6%8D%AE\" tabindex=\"-1\">删除/更新数据</h3>\n<p>删除数据同样需要在<code>Mutation</code>中定义操作,:后面为操作完成之后返回的类型,这里不再详细描述</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-\"><span class=\"line\"><span>type Mutation {</span></span>\n<span class=\"line\"><span> deleteArticle(id: String!): Boolean</span></span>\n<span class=\"line\"><span> updateArticle(id: String!, article: ArticleInput!): Article</span></span>\n<span class=\"line\"><span>}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"type Mutation {\n deleteArticle(id: String!): Boolean\n updateArticle(id: String!, article: ArticleInput!): Article\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>后端项目地址<a href=\"https://github.com/lnbiuc/graphql-start\">https://github.com/lnbiuc/graphql-start</a></p>\n"},{"_id":"65ca3152912f6564d5af089e","shortLink":"use-puppeteer","title":"使用无界面浏览器生成网页截图_","description":"使用Docker部署一个无界面浏览器,用于生成网页截图,并使用API远程调用","cover":"https://static.vio.vin/blog/2024/02/4691d594daf3f626ce655236a81f5b59.jpeg","category":"article","tags":["tech"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2024-02-06T13:10:16.209Z","updatedAt":"2024-02-29T12:43:20.288Z","status":"PUBLISHED","views":181,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/a1833fc9d007137403cdf75aad7f6cf685642f78bb1fbf453d510f5b3540737c.png","html":"<h2 id=\"%E2%9C%A8%E5%BC%80%E5%A7%8B\" tabindex=\"-1\">✨开始</h2>\n<p>之前看到了<a href=\"https://cali.so/\">Cali</a>大佬的博客,其中有一个非常有意思的功能引起了我的兴趣</p>\n<figure><img src=\"https://static.vio.vin/blog/2024/02/0d5e69ac1f50803c51d20030a44d659b.gif\" alt=\"\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<p>当鼠标悬浮在链接上时,会实时生成该链接对应的网页截图,根据<a href=\"https://cali.so/blog/guide-for-cloning-my-site\">https://cali.so/blog/guide-for-cloning-my-site</a>的文章介绍,该功能使用了第三方服务<a href=\"https://urlbox.com/\">urlbox</a>来实现,这是一个付费服务,每月价格为9$,于是放弃了使用该功能的想法。�</p>\n<figure><img src=\"https://static.vio.vin/blog/2024/02/29fe25ee6ab02c5c9e9926b1faebdf83.png\" alt=\"\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<h2 id=\"%EF%BF%BDpuppeteer\" tabindex=\"-1\">�Puppeteer</h2>\n<p>后来我想起来之前有看到过一篇文章,介绍了一种以无图形界面的浏览器,又称'无头浏览器',个人更愿意成为无界面浏览器,英文名为<code>headless browser</code>。通过一个Node.js库<a href=\"https://pptr.dev/\">Puppeteer</a>可以实现对Chrome/Chromium浏览器内核的操作,Puppeteer以无界面的形式运行,通过Puppeteer和Chromium配合,可以实现无界面浏览器。</p>\n<p><a href=\"https://pptr.dev/\">Puppeteer</a>有详细的操作文档,详细的介绍了如何使用,无界面浏览器拥有普通浏览器所有的功能,但是我需要的仅仅是生成网页截图这一项功能,如果需要实现这一功能,需要自行部署Puppeteer并且使用Node.js写一个API,接受至少一个参数-网址,之后生成网页截图并返回生成的图片文件。那么有没有一种简单的方式可以实现以上这些功能的同时,又方便部署呢,答案是有的。</p>\n<h2 id=\"%EF%BF%BDmingalevme%2Fscreenshoter\" tabindex=\"-1\">�mingalevme/screenshoter</h2>\n<p><a href=\"https://github.com/mingalevme/screenshoter\">mingalevme/screenshoter</a> 是我使用Docker + Puppeteer搜索到的Github项目,该项目将Docker和Puppeteer整合,提供了一套完整的API用于生成网页截图,并且以Docker的形式运行,只需要一行命令就可以启动。</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-shell\"><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">docker</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> run</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> -d</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> --restart</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> always</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> -p</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 8080</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">:8080</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> --name</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> screenshoter</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> mingalevme/screenshoter</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"docker run -d --restart always -p 8080:8080 --name screenshoter mingalevme/screenshoter\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>之后通过调用API,传入需要截图的网址即可生成网页截图。以下是一个示例:</p>\n<figure><img src=\"https://static.vio.vin/blog/2024/02/e135f8c5decb47b0f59f5be2ddac8492.png\" alt=\"\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<h2 id=\"%EF%BF%BD%E5%AE%9E%E9%99%85%E4%BD%BF%E7%94%A8\" tabindex=\"-1\">�实际使用</h2>\n<p>通过无界面浏览器,可以轻松实现对于任意网页的截图,对于国外网站,<a href=\"https://github.com/mingalevme/screenshoter\">mingalevme/screenshoter</a>支持配置代理。</p>\n<p>基于此,我计划实现以下功能。</p>\n<ul>\n<li>友链网址截图</li>\n</ul>\n<p>我打算将该功能过加到网站的友链功能上,后端对于友链中的网址进行预请求,将截图上传到本站图床Cloudflare R2上,每3天更新一次,这样在友链列表就可以看见朋友的网站内容了。</p>\n<ul>\n<li>Open Graph Image</li>\n</ul>\n<p>在Twitter中输入一个网址,Twitter将该网址显示为一张图片。例如<a href=\"https://github.com/mingalevme/screenshoter\">mingalevme/screenshoter</a>该仓库将显示为:</p>\n<figure><img src=\"https://static.vio.vin/blog/2024/02/4e179bbbae1cdffbd4b1d02b065cc736.png\" alt=\"\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<p>这是通过解析网页返回的HTML文件中Meta标签中的<code>twitter:image:src</code>实现的,通过向网站Header中加入对网站的截图,可以在Twitter、Facebook等网站中直接显示网站的内容图片,而不是一段英文链接,这对于吸引用户点就浏览是很有帮助的。</p>\n"},{"_id":"65ca3152912f6564d5af089d","shortLink":"2023-summary","title":"2023 Year-end summary","description":"2023 Year-end summary,2023年终总结","cover":"https://static.vio.vin/blog/2023/12/a0c3209cc9c8515b9466d29db77c8904.jpeg","category":"article","tags":["article"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-12-12T16:07:20.741Z","updatedAt":"2024-02-28T02:16:03.115Z","status":"PUBLISHED","views":92,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/4efd1259d877e75d876c5ea3b7a34777d80abc67f58c507479c22fabf8b69d45.png","html":"<blockquote>\n<p>2023年。我在这一年毕业,在毕业前,我已经有了一份很一般的工作,从一月份到五月毕业前,我在上班的同时,完成了毕业设计和毕业论文,七月份正式毕业,同时离开了毕业后的第一家公司,直到十月底,我才找到下一份工作,一直工作到年底。</p>\n</blockquote>\n<h2 id=\"1%E6%9C%88-3%E6%9C%88\" tabindex=\"-1\">1月-3月</h2>\n<p>由于我是去年12月工作才入职这家公司,以实习生的身份,所以公司并没有安排什么工作给我,这样的状态一直持续到我离职。在过年前三天,我请假回家过年去了,比较无聊。</p>\n<p>直到三月份,我离开了住了三个月的地方,租的房子,是在一个城中村里边,房租每月1100,电费1块钱,记得十二月到一月那会,新冠很严重,每天在城中村的出租屋里甚至看不见阳光,出门的感受也是脏乱差,周围的人也是奇奇怪怪,感觉特别压抑,受不了了,于是在三个月合同到期之后,果断选择搬走了,换到了一个离公司更近的地方,每天步行上班只需要20分钟左右。最重要的是从城中村搬到了小区里,虽然是合租但是是高层,小区物业保安也很好。房间有暖气,想起来城中村的时候没有暖气,三楼特别冷,自己还阳了,基本上空调能开一天,退房的时候电费算了我六百多块钱,看到数字直接就震惊了,还好水电费从押金了扣了,不然真付不起了,以后再也不去城中村了。现在这房间有暖气,冬天很舒服,平时中午的时候阳光能直接晒到我床上,自己非常满意了已经。</p>\n<p>二月开始写我的毕业设计,当时正好可以用ChatGPT,在代码和论文上对我都有帮助。</p>\n<h2 id=\"4%E6%9C%88-5%E6%9C%88\" tabindex=\"-1\">4月-5月</h2>\n<p>大约是三月底的时候,我大学的室友和我入职了同一家公司,他入职没多久,我的工位就调整到了他旁边,每天上班累了就闲聊一会,工作上也没什么活,算是摸鱼了两个月。当然是上班摸鱼,下班写毕业设计、论文。</p>\n<h2 id=\"6%E6%9C%88\" tabindex=\"-1\">6月</h2>\n<p>到5月份的时候,指导老师就会找同学们指导论文,看进度等等。我是真的幸运,选择了全校最好的指导老师(自认为),对论文,她是真的负责,别的同学都没有开题答辩、中期答辩,但是我的指导老师一直在找空闲时间帮我们看论文。可能一开始有的同学还不理解,但是等到六月份回学校答辩的时候,大家都明白了,指导老师对我们论文跟的紧,回学校之后论文已经大体成型了,只剩下些小问题小修小改就好了,然而其他的指导老师和同学就没这么幸运了,在学校熬夜改论文,指导老师忙,也不咋帮。</p>\n<p>答辩的时候我的指导老师同时是我的答辩评审老师,而且还是评审组组长。其实知道这些消息的时候,对答辩我应该就完全不紧张了,但是怪自己没经验,答辩前一晚还是非常紧张的,生怕比不了业。答辩的过程非常顺利,我在讲台上讲,老师帮我看论文,之后演示毕业设计系统,系统演示完都没有提问(别的同学都有提问)就结束了,给我说了几点论文的问题就结束了,最后也是取得了94分的答辩分,异常顺利。</p>\n<p>六月也是今年最忙的一个月,准备毕业前几周,每天都做一个半小时公交往返学校,累是真的累,经常在公交车上补觉,不过和同学们在一起还是很有趣的。</p>\n<h2 id=\"7%E6%9C%88-10%E6%9C%88\" tabindex=\"-1\">7月-10月</h2>\n<p>六月底我就离职了,七月到十月底一直没有上班。七月整个月都在和前公司扯皮,因为签了协议,不过最后还好,公司不屑于和我一个应届生计较,放我走了。八月到九月投的简历很少,确实当时工作非常难找,社招没经验,应届生都招下一届的了。直到十月底才找到一家公司。</p>\n<p>这期间我爸休假时还来看我,顺便到城市里到处转转。那时候每天都投简历,投出去回复很少,面试更少,每天都很焦虑,压力很大。我记得有几天早上早早起来,开始投简历,等回复,一天都没玩电脑。后面终于找到了才松了口气。</p>\n<p>运气很好,在入职新公司的第一天就遇到了大学同学,这让接下来的工作压力小了很多。关于这份新工作,只是目前感觉还行,以后会怎样还不好说,我对工作的喜欢与否,有很多个人理解,最主要的是这份工作是否有趣,其次是公司制度、雰围等等。</p>\n<p>如果要说这几个月有什么成果的话,给一起打游戏的朋友们建了Teamspeak频道,建立了一套直播 + 录播系统,方便直播给朋友看。这一切的动机其实非常简单,建Teamspeak频道是因为开黑啦 KOOK降噪要开会员,建直播系统是因为我在B站直播Apex直播间被封了,应为没挡住屏幕左边好友申请和屏幕下边击杀信息,于是我自己搭了整套直播系统。最开始的时候使用了开源方案,云服务器配合SRS实现推拉流,但是不怎么稳定,经常有卡顿,前端是Wordpress。后来换了腾讯云直播,稳定性提高了很多,花费也不是很高,还能将录播直接保存到COS中,于是采用了这套方案,一直在使用,前端自己用Nuxt写了个简单界面,托管到Vercel,为了看录播,还selfhost了Alist,方便看录播。</p>\n<p>我在公司加班,朋友们在直播玩Cyberpubk 2077,哈哈哈。</p>\n<h2 id=\"11%E6%9C%88\" tabindex=\"-1\">11月</h2>\n<p>令人印象深刻,凌晨四点打车到医院,找急症但是下车点在相反的方向,忍着疼痛横穿整个医院才到急症,滴滴的问题。这病两三年必得一次,这已经是第三次了,没啥办法。</p>\n<p>对了,11月份开始重写了博客,直到目前仍在开发中,不追求完美,使用为主。工作了,不能在像以前摆烂了,得不断学习了。</p>\n<h2 id=\"12%E6%9C%88\" tabindex=\"-1\">12月</h2>\n<p>工作,加班,等过年,想回家。</p>\n<h2 id=\"%E4%B8%80%E7%82%B9%E6%84%9F%E8%A7%A6\" tabindex=\"-1\">一点感触</h2>\n<p>从我在第一家公司工作的经历来看,如果想让别人尊重你,注意到你说的话,只有提高自己的技术水平。我记我们实习生在一起刚开始培训的时候,刚开始互相认识,团队协作,自己说的话根本不会有人在乎,问别人问题最后得到的回复是流汗黄豆,两周之后,能力水平的高低体现出来,才有了基本的尊重,会有人问你问题,说话也好使了。</p>\n<h2 id=\"github-2023\" tabindex=\"-1\">Github 2023</h2>\n<figure><img src=\"https://static.vio.vin/blog/2024/01/b94a7c9e95fdacacacd9345baedb9f0f.jpg\" alt=\"\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<h2 id=\"ps5\" tabindex=\"-1\">PS5</h2>\n<p><img src=\"https://static.vio.vin/blog/2024/01/15781c068eb4835f39006cf58992da0e.jpg\" alt=\"\" />\n<img src=\"https://static.vio.vin/blog/2024/01/40284314a5c5f5197b497b4638378d90.jpg\" alt=\"\" />\n<img src=\"https://static.vio.vin/blog/2024/01/e62c99054715518357b3152069e61a14.jpg\" alt=\"\" />\n<img src=\"https://static.vio.vin/blog/2024/01/d6b345c4579a9a3bc4eea2e0054a9e49.jpg\" alt=\"\" /></p>\n"},{"_id":"65ca3152912f6564d5af089c","shortLink":"my-ip","title":"MyIP","description":"A IP Toolbox. Easy to check what's your IPs, IP informations, check for DNS leaks, examine WebRTC connections, and test website.","cover":"https://static.vio.vin/blog/2023/12/ab502b13b500f01de927aaa9f397c105.png","category":"project","tags":["opensource"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-12-06T17:08:56.937Z","updatedAt":"2024-02-17T01:03:12.330Z","status":"PUBLISHED","views":2,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/f07caeedffa4d4df7319bd6de449447359f6403e4a0c1f844b2e24990827eefa.png","link":"https://myip.lnbiuc.com/"},{"_id":"65ca3152912f6564d5af089b","shortLink":"aoplog","title":"AopLog","category":"short","tags":["codesnap","aop"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-12-04T13:55:55.998Z","updatedAt":"2024-03-01T17:06:05.491Z","status":"PUBLISHED","views":21,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/2c0dcf1cc004135db4586959be6f7661bbc3d1f68c00c9a7d0d4cbe92868b376.png","html":"\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Aspect</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Component</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Slf4j</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> class</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> AopLog</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> /**</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> * 切入点</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> */</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Pointcut</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"execution(public * vin.vio.blognextapi.controller.*Controller.*(..))\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> log</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() {</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> /**</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> * 环绕操作</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> *</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> * </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">@param</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> point</span><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> 切入点</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> * </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">@return</span><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> 原方法返回值</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> * </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">@throws</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> Throwable</span><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> 异常信息</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> */</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Around</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"log()\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Object </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">aroundLog</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(ProceedingJoinPoint </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">point</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">throws</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Throwable {</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 开始打印请求日志</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ServletRequestAttributes attributes </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (ServletRequestAttributes) RequestContextHolder.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getRequestAttributes</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> HttpServletRequest request </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Objects.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">requireNonNull</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(attributes).</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getRequest</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 打印请求相关参数</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> long</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> startTime </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> System.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">currentTimeMillis</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Object result </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> point.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">proceed</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String header </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> request.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getHeader</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"User-Agent\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> UserAgent userAgent </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> UserAgent.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">parseUserAgentString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(header);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> final</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Log l </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Log.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">builder</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">threadId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Long.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Thread.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">currentThread</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()))</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">threadName</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Thread.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">currentThread</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getName</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">())</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">ip</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getIp</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(request))</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">url</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(request.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getRequestURL</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">())</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">classMethod</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(String.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">format</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"%s.%s\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, point.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getSignature</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDeclaringTypeName</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(),</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> point.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getSignature</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getName</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()))</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">httpMethod</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(request.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getMethod</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">())</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">requestParams</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getNameAndValue</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(point))</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">result</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(result)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">timeCost</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(System.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">currentTimeMillis</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">-</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> startTime)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">userAgent</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(header)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">browser</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(userAgent.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getBrowser</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">())</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">os</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(userAgent.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getOperatingSystem</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()).</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">build</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> log.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">info</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Request Log Info : {}\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, JSONUtil.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toJsonStr</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(l));</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> result;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getNameAndValue</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(ProceedingJoinPoint </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">joinPoint</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> final</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Signature signature </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> joinPoint.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getSignature</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> MethodSignature methodSignature </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (MethodSignature) signature;</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> final</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">[] names </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> methodSignature.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getParameterNames</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> final</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">[] args </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> joinPoint.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getArgs</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (ArrayUtil.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">isEmpty</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(names) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">||</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ArrayUtil.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">isEmpty</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(args)) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Collections.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">emptyMap</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (names.length </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">!=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> args.length) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> log.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">warn</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"{}方法参数名和参数值数量不一致\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, methodSignature.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getName</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Collections.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">emptyMap</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> map </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> HashMap&#x3C;>();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">int</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> i </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 0</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">; i </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> names.length; i</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">++</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> map.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(names[i], args[i]);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> map;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> static</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> final</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String UNKNOWN </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> \"unknown\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> /**</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> * 获取ip地址</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> */</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> static</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getIp</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(HttpServletRequest </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">request</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String ip </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> request.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getHeader</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"x-forwarded-for\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (ip </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">==</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> ||</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ip.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">isEmpty</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">||</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> UNKNOWN.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equalsIgnoreCase</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(ip)) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ip </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> request.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getHeader</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"Proxy-Client-IP\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (ip </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">==</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> ||</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ip.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">isEmpty</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">||</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> UNKNOWN.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equalsIgnoreCase</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(ip)) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ip </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> request.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getHeader</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"WL-Proxy-Client-IP\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (ip </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">==</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> ||</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ip.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">isEmpty</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">||</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> UNKNOWN.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equalsIgnoreCase</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(ip)) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ip </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> request.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getRemoteAddr</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String comma </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> \",\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String localhost </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> \"127.0.0.1\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (ip.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">contains</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(comma)) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ip </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ip.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">split</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\",\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)[</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">0</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">];</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (localhost.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(ip)) {</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 获取本机真正的ip地址</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> try</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ip </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> InetAddress.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getLocalHost</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getHostAddress</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> } </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">catch</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (UnknownHostException </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">e</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> log.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">error</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(e.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getMessage</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(), e);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ip;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Data</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Builder</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">NoArgsConstructor</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">AllArgsConstructor</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> static</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> class</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> Log</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 线程id</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String threadId;</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 线程名称</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String threadName;</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // ip</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String ip;</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // url</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String url;</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // http方法 GET POST PUT DELETE PATCH</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String httpMethod;</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 类方法</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String classMethod;</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 请求参数</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Object requestParams;</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 返回参数</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Object result;</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 接口耗时</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Long timeCost;</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 操作系统</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String os;</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 浏览器</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String browser;</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // user-agent</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String userAgent;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"@Aspect\n@Component\n@Slf4j\npublic class AopLog {\n /**\n * 切入点\n */\n @Pointcut(&quot;execution(public * vin.vio.blognextapi.controller.*Controller.*(..))&quot;)\n public void log() {\n\n }\n\n /**\n * 环绕操作\n *\n * @param point 切入点\n * @return 原方法返回值\n * @throws Throwable 异常信息\n */\n @Around(&quot;log()&quot;)\n public Object aroundLog(ProceedingJoinPoint point) throws Throwable {\n\n // 开始打印请求日志\n ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();\n HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();\n\n // 打印请求相关参数\n long startTime = System.currentTimeMillis();\n Object result = point.proceed();\n String header = request.getHeader(&quot;User-Agent&quot;);\n UserAgent userAgent = UserAgent.parseUserAgentString(header);\n\n final Log l = Log.builder()\n .threadId(Long.toString(Thread.currentThread().getId()))\n .threadName(Thread.currentThread().getName())\n .ip(getIp(request))\n .url(request.getRequestURL().toString())\n .classMethod(String.format(&quot;%s.%s&quot;, point.getSignature().getDeclaringTypeName(),\n point.getSignature().getName()))\n .httpMethod(request.getMethod())\n .requestParams(getNameAndValue(point))\n .result(result)\n .timeCost(System.currentTimeMillis() - startTime)\n .userAgent(header)\n .browser(userAgent.getBrowser().toString())\n .os(userAgent.getOperatingSystem().toString()).build();\n\n log.info(&quot;Request Log Info : {}&quot;, JSONUtil.toJsonStr(l));\n\n return result;\n }\n\n\n private Map<String, Object> getNameAndValue(ProceedingJoinPoint joinPoint) {\n\n final Signature signature = joinPoint.getSignature();\n MethodSignature methodSignature = (MethodSignature) signature;\n final String[] names = methodSignature.getParameterNames();\n final Object[] args = joinPoint.getArgs();\n\n if (ArrayUtil.isEmpty(names) || ArrayUtil.isEmpty(args)) {\n return Collections.emptyMap();\n }\n if (names.length != args.length) {\n log.warn(&quot;{}方法参数名和参数值数量不一致&quot;, methodSignature.getName());\n return Collections.emptyMap();\n }\n Map<String, Object> map = new HashMap<>();\n for (int i = 0; i < names.length; i++) {\n map.put(names[i], args[i]);\n }\n return map;\n }\n\n private static final String UNKNOWN = &quot;unknown&quot;;\n\n /**\n * 获取ip地址\n */\n public static String getIp(HttpServletRequest request) {\n String ip = request.getHeader(&quot;x-forwarded-for&quot;);\n if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {\n ip = request.getHeader(&quot;Proxy-Client-IP&quot;);\n }\n if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {\n ip = request.getHeader(&quot;WL-Proxy-Client-IP&quot;);\n }\n if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) {\n ip = request.getRemoteAddr();\n }\n String comma = &quot;,&quot;;\n String localhost = &quot;127.0.0.1&quot;;\n if (ip.contains(comma)) {\n ip = ip.split(&quot;,&quot;)[0];\n }\n if (localhost.equals(ip)) {\n // 获取本机真正的ip地址\n try {\n ip = InetAddress.getLocalHost().getHostAddress();\n } catch (UnknownHostException e) {\n log.error(e.getMessage(), e);\n }\n }\n return ip;\n }\n\n @Data\n @Builder\n @NoArgsConstructor\n @AllArgsConstructor\n static class Log {\n // 线程id\n private String threadId;\n // 线程名称\n private String threadName;\n // ip\n private String ip;\n // url\n private String url;\n // http方法 GET POST PUT DELETE PATCH\n private String httpMethod;\n // 类方法\n private String classMethod;\n // 请求参数\n private Object requestParams;\n // 返回参数\n private Object result;\n // 接口耗时\n private Long timeCost;\n // 操作系统\n private String os;\n // 浏览器\n private String browser;\n // user-agent\n private String userAgent;\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>okok</p>\n"},{"_id":"65ca3152912f6564d5af089a","shortLink":"bos-plugin-template","title":"Bos Plugin Template","description":"Bos Plugin Template","category":"short","tags":["bos"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-12-04T02:24:31.553Z","updatedAt":"2024-02-28T14:19:56.488Z","status":"PUBLISHED","views":20,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/321c232ef696e9f21fd35d55185f8ab689d268b0c37957c3e17a67892d36da9f.png","html":"<h2 id=\"%E6%89%B9%E9%87%8F%E6%96%B0%E5%A2%9E%E8%A1%8C\" tabindex=\"-1\">批量新增行</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> class</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> orderproreqbillFromEdit</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> extends</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> AbstractFormPlugin</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> </span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> afterDoOperation</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(AfterDoOperationEventArgs </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">args</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> super</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">afterDoOperation</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(args);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String operateKey </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> args.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getOperateKey</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> OperationResult operationResult </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> args.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getOperationResult</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"batchcreate\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(operateKey) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x26;&#x26;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> operationResult.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">isSuccess</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()) {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getModel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">batchCreateNewEntryRow</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"分录标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">10</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"public class orderproreqbillFromEdit extends AbstractFormPlugin {\n \n @Override\n public void afterDoOperation(AfterDoOperationEventArgs args)\n {\n super.afterDoOperation(args);\n String operateKey = args.getOperateKey();\n OperationResult operationResult = args.getOperationResult();\n if (&quot;batchcreate&quot;.equals(operateKey) && operationResult.isSuccess()) {\n this.getModel().batchCreateNewEntryRow(&quot;分录标识&quot;,10);\n }\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E6%9F%A5%E8%AF%A2%E5%8D%95%E6%8D%AE%EF%BC%88%E4%B8%80%E5%BC%A0%EF%BC%89\" tabindex=\"-1\">查询单据(一张)</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">DynamicObject dynamicObject </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> BusinessDataServiceHelper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">loadSingle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"单据标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"id,billno,billstatus,分录标识,分录标识.字段标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> QFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">[]{</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> QFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"字段\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, QCP.equals, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"过滤值\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)});</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> dynamicObject.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">set</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">,</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"赋值\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> SaveServiceHelper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">save</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> DynamicObject</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">[]{dynamicObject});</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle(&quot;单据标识&quot;, &quot;id,billno,billstatus,分录标识,分录标识.字段标识&quot;,\n new QFilter[]{new QFilter(&quot;字段&quot;, QCP.equals, &quot;过滤值&quot;)});\n dynamicObject.set(&quot;标识&quot;,&quot;赋值&quot;);\n SaveServiceHelper.save(new DynamicObject[]{dynamicObject});\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1\" tabindex=\"-1\">定时任务</h2>\n<p>!!! abstract 文档\n<a href=\"https://developer.kingdee.com/article/226086468627134208?productLineId=29\">https://developer.kingdee.com/article/226086468627134208?productLineId=29</a></p>\n<p>!!!</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> class</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> ResourceFilterTask</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> extends</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> AbstractTask</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> execute</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(RequestContext </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">requestContext</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">map</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">throws</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> KDException</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> </span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"public class ResourceFilterTask extends AbstractTask\n{\n @Override\n public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException\n {\n \n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E6%9F%A5%E8%AF%A2%E4%B8%80%E5%BC%A0%E5%8D%95%E6%8D%AE\" tabindex=\"-1\">查询一张单据</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">DynamicObject resource </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> BusinessDataServiceHelper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">loadSingle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(dynamicObject.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getLong</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识.id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">),</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"DynamicObject resource = BusinessDataServiceHelper.loadSingle(dynamicObject.getLong(&quot;标识.id&quot;),&quot;标识&quot;);\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E6%9F%A5%E8%AF%A2%E5%A4%9A%E5%BC%A0%E5%8D%95%E6%8D%AE\" tabindex=\"-1\">查询多张单据</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">DynamicObject</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">[] basemodelib </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> BusinessDataServiceHelper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">load</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"DynamicObject[] basemodelib = BusinessDataServiceHelper.load(&quot;标识&quot;, &quot;id&quot;, null);\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%93%8D%E4%BD%9C%EF%BC%88%E6%8F%90%E4%BA%A4%EF%BC%8C%E5%AE%A1%E6%A0%B8%EF%BC%8C%E5%8F%8D%E5%AE%A1%E6%A0%B8%EF%BC%89\" tabindex=\"-1\">代码执行操作(提交,审核,反审核)</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">OperationServiceHelper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">executeOperate</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"disable\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, resource.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDynamicObjectType</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getName</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(), </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> DynamicObject</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">[]{resource}, Utils.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getOption</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"OperationServiceHelper.executeOperate(&quot;disable&quot;, resource.getDynamicObjectType().getName(), new DynamicObject[]{resource}, Utils.getOption());\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E6%9C%8D%E5%8A%A1%E6%8F%92%E4%BB%B6%E8%8E%B7%E5%8F%96%E5%AD%90%E5%8D%95%E6%8D%AE%E4%BD%93\" tabindex=\"-1\">服务插件获取子单据体</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(DynamicObject entity</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> entities)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 收款单 收款明细</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DynamicObjectCollection collection </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> entity.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDynamicObjectCollection</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(collection.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">isEmpty</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">())</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> continue</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(DynamicObject dynamicObject</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> collection)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 认领明细(子单据体)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DynamicObjectCollection subCollection </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> dynamicObject.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDynamicObjectCollection</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(subCollection.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">isEmpty</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">())</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> continue</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"for(DynamicObject entity: entities)\n{\n // 收款单 收款明细\n DynamicObjectCollection collection = entity.getDynamicObjectCollection(&quot;标识&quot;);\n if(collection.isEmpty())\n {\n continue;\n }\n for(DynamicObject dynamicObject: collection)\n {\n // 认领明细(子单据体)\n DynamicObjectCollection subCollection = dynamicObject.getDynamicObjectCollection(&quot;标识&quot;);\n if(subCollection.isEmpty())\n {\n continue;\n }\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E6%A0%B9%E6%8D%AE%E4%BA%BA%E5%91%98%E6%90%BA%E5%B8%A6%E9%83%A8%E9%97%A8\" tabindex=\"-1\">根据人员携带部门</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\">/**</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> * 根据申请人携带所属部门</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> */</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">private</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> bringDept</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DynamicObject dataEntity </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getModel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDataEntity</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> long</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> applyUser </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> dataEntity.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getLong</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识.id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(applyUser </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">></span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 0</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DynamicObject mainUserdep </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> CommonUtils.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getMainUserdep</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(applyUser);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(mainUserdep </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">!=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getModel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setValue</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, mainUserdep.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getLong</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">));</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> else</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getModel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setValue</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> else</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getModel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setValue</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"/**\n * 根据申请人携带所属部门\n */\nprivate void bringDept()\n{\n DynamicObject dataEntity = this.getModel().getDataEntity();\n long applyUser = dataEntity.getLong(&quot;标识.id&quot;);\n if(applyUser > 0)\n {\n DynamicObject mainUserdep = CommonUtils.getMainUserdep(applyUser);\n if(mainUserdep != null)\n {\n this.getModel().setValue(&quot;标识&quot;, mainUserdep.getLong(&quot;id&quot;));\n }\n else\n {\n this.getModel().setValue(&quot;标识&quot;, null);\n }\n }\n else\n {\n this.getModel().setValue(&quot;标识&quot;, null);\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E5%8D%95%E6%8D%AE%E4%BD%93%E8%A1%8C%E7%9D%80%E8%89%B2\" tabindex=\"-1\">单据体行着色</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">EntryGrid entryGrid </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getControl</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">entryGrid.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setRowBackcolor</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"rgba(251,35,35,0.1)\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, rows.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">stream</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">mapToInt</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Integer</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">::</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">intValue).</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toArray</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"EntryGrid entryGrid = this.getControl(&quot;标识&quot;);\nentryGrid.setRowBackcolor(&quot;rgba(251,35,35,0.1)&quot;, rows.stream().mapToInt(Integer::intValue).toArray());\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E4%BB%A3%E7%A0%81%E8%AE%BE%E7%BD%AE%E5%AD%97%E6%AE%B5%E5%BF%85%E5%BD%95\" tabindex=\"-1\">代码设置字段必录</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">FieldEdit control </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getControl</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">control.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setMustInput</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"FieldEdit control = this.getView().getControl(&quot;标识&quot;);\ncontrol.setMustInput(true);\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E5%8D%95%E6%8D%AE%E4%BD%93%E6%96%B0%E5%A2%9E%E8%A1%8C\" tabindex=\"-1\">单据体新增行</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">IDataModel model </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getModel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">int</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> entryRow </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> model.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">createNewEntryRow</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"分录标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">model.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setValue</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"字段标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"P\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, entryRow);</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"IDataModel model = this.getModel();\nint entryRow = model.createNewEntryRow(&quot;分录标识&quot;);\nmodel.setValue(&quot;字段标识&quot;, &quot;P&quot;, entryRow);\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E5%88%97%E8%A1%A8%E8%BF%87%E6%BB%A4\" tabindex=\"-1\">列表过滤</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> class</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> listFilter</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> extends</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> AbstractListPlugin</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> setFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(SetFilterEvent </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">e</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">QFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> qFilterList </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> e.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getQFilters</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> qFilterList.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">add</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> QFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, QCP.equals, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"B\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">));</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"public class listFilter extends AbstractListPlugin\n{\n @Override\n public void setFilter(SetFilterEvent e)\n {\n List<QFilter> qFilterList = e.getQFilters();\n qFilterList.add(new QFilter(&quot;标识&quot;, QCP.equals, &quot;B&quot;));\n }\n}\n\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E4%BB%8E%E9%99%84%E4%BB%B6%E9%9D%A2%E6%9D%BF%E8%8E%B7%E5%8F%96%E9%99%84%E4%BB%B6\" tabindex=\"-1\">从附件面板获取附件</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">AttachmentPanel panel </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getControl</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">))</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">List&#x3C;Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>> attachmentData </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> panel.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getAttachmentData</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"AttachmentPanel panel = this.getControl(&quot;标识&quot;))\nList<Map<String, Object>> attachmentData = panel.getAttachmentData();\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E4%B8%8B%E6%8E%A8-%E5%8D%95%E6%8D%AE%E8%BD%AC%E6%8D%A2%E6%8F%92%E4%BB%B6\" tabindex=\"-1\">下推 单据转换插件</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> class</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> ShippingDetailToTransferOrderConvert</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> extends</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> AbstractConvertPlugIn</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> afterConvert</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(AfterConvertEventArgs </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">e</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> super</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">afterConvert</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(e);</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 目标单据</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String targetName </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getTgtMainType</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getName</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 来源单据</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String sourceName </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getSrcMainType</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getName</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">!</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(targetName) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">||</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> !</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(sourceName)) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> ExtendedDataEntity</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">[] findByEntityKeys </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> e.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getTargetExtDataEntitySet</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">FindByEntityKey</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(targetName);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (ExtendedDataEntity findByEntityKey </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> findByEntityKeys) {</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // origin data</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DynamicObject dataEntity </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> findByEntityKey.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDataEntity</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> long</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> sourcebillid </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> dataEntity.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getLong</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DynamicObject sourceEntryData </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> BusinessDataServiceHelper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">loadSingle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(sourcebillid, sourceName);</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 商品明细</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DynamicObjectCollection materialinfo </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> sourceEntryData.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDynamicObjectCollection</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 出运汇总</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DynamicObjectCollection salesorderTotal </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> sourceEntryData.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDynamicObjectCollection</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Long</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">DynamicObjectCollection</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> map </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> LinkedHashMap&#x3C;>();</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (DynamicObject object </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> salesorderTotal) {</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 明细行号ID</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> long</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> id </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> object.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getLong</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (DynamicObject materialinfoEntitiy </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> materialinfo) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (id </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">==</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> materialinfoEntitiy.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getLong</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> map.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(object.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getLong</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">), materialinfoEntitiy.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDynamicObjectCollection</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">));</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DynamicObjectCollection targetMaterialinfo </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> dataEntity.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDynamicObjectCollection</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (DynamicObject object </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> targetMaterialinfo) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> long</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> sourceentryid </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> object.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getLong</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (map.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">containsKey</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(sourceentryid)) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DynamicObjectCollection multiconfig </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> object.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDynamicObjectCollection</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> multiconfig.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">addAll</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(map.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(sourceentryid));</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"public class ShippingDetailToTransferOrderConvert extends AbstractConvertPlugIn\n{\n @Override\n public void afterConvert(AfterConvertEventArgs e)\n {\n super.afterConvert(e);\n // 目标单据\n String targetName = this.getTgtMainType().getName();\n // 来源单据\n String sourceName = this.getSrcMainType().getName();\n if (!&quot;标识&quot;.equals(targetName) || !&quot;标识&quot;.equals(sourceName)) {\n return;\n }\n ExtendedDataEntity[] findByEntityKeys = e.getTargetExtDataEntitySet().FindByEntityKey(targetName);\n for (ExtendedDataEntity findByEntityKey : findByEntityKeys) {\n // origin data\n DynamicObject dataEntity = findByEntityKey.getDataEntity();\n long sourcebillid = dataEntity.getLong(&quot;标识&quot;);\n DynamicObject sourceEntryData = BusinessDataServiceHelper.loadSingle(sourcebillid, sourceName);\n // 商品明细\n DynamicObjectCollection materialinfo = sourceEntryData.getDynamicObjectCollection(&quot;标识&quot;);\n\n // 出运汇总\n DynamicObjectCollection salesorderTotal = sourceEntryData.getDynamicObjectCollection(&quot;标识&quot;);\n\n Map<Long, DynamicObjectCollection> map = new LinkedHashMap<>();\n\n for (DynamicObject object : salesorderTotal) {\n\n // 明细行号ID\n long id = object.getLong(&quot;标识&quot;);\n\n for (DynamicObject materialinfoEntitiy : materialinfo) {\n if (id == materialinfoEntitiy.getLong(&quot;id&quot;)) {\n map.put(object.getLong(&quot;id&quot;), materialinfoEntitiy.getDynamicObjectCollection(&quot;标识&quot;));\n }\n }\n }\n\n DynamicObjectCollection targetMaterialinfo = dataEntity.getDynamicObjectCollection(&quot;标识&quot;);\n for (DynamicObject object : targetMaterialinfo) {\n long sourceentryid = object.getLong(&quot;标识&quot;);\n if (map.containsKey(sourceentryid)) {\n DynamicObjectCollection multiconfig = object.getDynamicObjectCollection(&quot;标识&quot;);\n multiconfig.addAll(map.get(sourceentryid));\n }\n }\n }\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E4%BB%8E%E9%99%84%E4%BB%B6%E9%9D%A2%E6%9D%BF%E8%8E%B7%E5%8F%96%E9%99%84%E4%BB%B6-1\" tabindex=\"-1\">从附件面板获取附件</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">AttachmentServiceHelper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getAttachments</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"单据标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, file.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getPkValue</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(), </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"附件面板标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"AttachmentServiceHelper.getAttachments(&quot;单据标识&quot;, file.getPkValue().toString(), &quot;附件面板标识&quot;);\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E4%BB%A3%E7%A0%81%E8%B5%8B%E5%80%BC%EF%BC%8C%E4%BD%86%E4%B8%8D%E8%A7%A6%E5%8F%91%E5%80%BC%E6%9B%B4%E6%96%B0\" tabindex=\"-1\">代码赋值,但不触发值更新</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getModel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">beginInit</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">model.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setValue</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, calcedTotalWeight, index);</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">updateView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getModel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">endInit</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"this.getModel().beginInit();\nmodel.setValue(&quot;标识&quot;, calcedTotalWeight, index);\nthis.getView().updateView(&quot;标识&quot;);\nthis.getModel().endInit();\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E6%89%93%E5%BC%80%E5%8D%95%E6%8D%AE\" tabindex=\"-1\">打开单据</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> static</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> OpenFrom</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(IFormView view, Object okid, String Formid)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> BillShowParameter parameter </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> BillShowParameter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(); </span><span style=\"color:#6A737D;--shiki-dark:#6A737D\">//跳转指定单据</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setPkId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(okid);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getOpenStyle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setShowType</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(ShowType.MainNewTabPage);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setFormId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Formid);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setStatus</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(OperationStatus.EDIT);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> view.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">showForm</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(parameter);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"public static void OpenFrom(IFormView view, Object okid, String Formid)\n{\n BillShowParameter parameter = new BillShowParameter(); //跳转指定单据\n parameter.setPkId(okid);\n parameter.getOpenStyle().setShowType(ShowType.MainNewTabPage);\n parameter.setFormId(Formid);\n parameter.setStatus(OperationStatus.EDIT);\n view.showForm(parameter);\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E9%99%84%E4%BB%B6%E5%9B%9E%E5%A1%AB\" tabindex=\"-1\">附件回填</h2>\n<h3 id=\"%E5%8A%A8%E6%80%81%E8%A1%A8%E5%8D%95\" tabindex=\"-1\">动态表单</h3>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> class</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> ContractResignEdit</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> extends</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> AbstractFormPlugin</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> implements</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> UploadListener</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> static</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> final</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Log log </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> LogFactory.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getLog</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(ContractResignEdit.class);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> registerListener</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(EventObject </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">e</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> super</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">registerListener</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(e);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> AttachmentPanel attachmentPanel </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getControl</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"附件面板\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> attachmentPanel.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">addUploadListener</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">addClickListeners</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"btncancel\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"btnok\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> beforeUpload</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(BeforeUploadEvent </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">evt</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> UploadListener.super.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">beforeUpload</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(evt);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> IPageCache pageCache </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getPageCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> pageCache.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"falg\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> afterUpload</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(UploadEvent </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">evt</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">addAttachmentContext</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getModel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(), </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> IPageCache pageCache </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getPageCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> pageCache.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"falg\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> addAttachmentContext</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(IDataModel </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">model</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, IFormView </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">view</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> IPageCache cache </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getPageCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>> addAttachmentData </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> getCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(cache);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> cache.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"attach\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, addAttachmentData.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> log.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">error</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"上传附件之后:\"</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> +</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> upload</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(UploadEvent </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">evt</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">[] urls </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> evt.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getUrls</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> IPageCache cache </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getPageCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>> addAttachmentData </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> getCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(cache);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (Object url </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> urls) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">SuppressWarnings</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"unchecked\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> att </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (Map</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">String, Object</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) url;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">add</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(att);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> log.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">error</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"上传附件:\"</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> +</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> cache.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"attach\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, JSONObject.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toJSONString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(addAttachmentData));</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> remove</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(UploadEvent </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">evt</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">removeAttachmentContext</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(), </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getModel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(), evt);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> removeAttachmentContext</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(IFormView </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">view</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, IDataModel </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">model</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, UploadEvent </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">evt</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> IFormView parentView </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> view.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getParentView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> AttachmentPanel panel </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> parentView.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getControl</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"附件面板\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> AttachmentPanel source </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (AttachmentPanel) evt.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getSource</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> IPageCache cache </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getPageCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>> addAttachmentData </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> getCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(cache);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">[] urls </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> evt.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getUrls</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (Object url </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> urls) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">SuppressWarnings</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"unchecked\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> att </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (Map</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">String, Object</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) url;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> panel.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">remove</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(att);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">int</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> i </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 0</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">; i </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">size</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(); i</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">++</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> map </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(i);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (map.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"name\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">).</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(att.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"name\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">))) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">remove</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(i);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> cache.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"attach\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, JSONObject.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toJSONString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(addAttachmentData));</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> log.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">error</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"删除附件:\"</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> +</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> evt.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setCancel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>> attachmentData </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> panel.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getAttachmentData</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> attachmentData.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">addAll</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(addAttachmentData);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> source.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">bindData</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(attachmentData);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> parentView.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">invokeOperation</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"refresh\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> view.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">sendFormAction</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(parentView);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> click</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(EventObject </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">e</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> super</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">click</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(e);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Control source </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (Control) e.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getSource</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String key </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> source.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getKey</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"btncancel\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(key)) {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">returnDataToParent</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">close</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"btnok\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(key)) {</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> btnOk</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> btnOk</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DynamicObject dataEntity </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getModel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDataEntity</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> HashMap&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> hashMap </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> HashMap&#x3C;>();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> IPageCache cache </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getPageCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>> addAttachmentData </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> getCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(cache);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> hashMap.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"attach\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, addAttachmentData);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> long</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> user </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> dataEntity.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getLong</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"用户.id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Date date </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> dataEntity.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDate</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"日期\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> hashMap.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"user\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, user);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> hashMap.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"date\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, date);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> log.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">error</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"关闭界面之前:\"</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> +</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData);</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">returnDataToParent</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(hashMap);</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">close</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">clear</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span><span style=\"color:#6A737D;--shiki-dark:#6A737D\">//关闭界面清空上传附件</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> log.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">error</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"关闭界面:\"</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> +</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> afterCreateNewData</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(EventObject </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">e</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> super</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">afterCreateNewData</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(e);</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">creadteAttach</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(), </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getModel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(), e);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> IPageCache cache </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getPageCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>> addAttachmentData </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> getCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(cache);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> log.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">error</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"刷新界面\"</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> +</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> creadteAttach</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(IFormView </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">view</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, IDataModel </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">model</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, EventObject </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">e</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> FormShowParameter showParameter </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> view.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getFormShowParameter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> filtername </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ArrayList&#x3C;>();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>> attach </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> showParameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getCustomParam</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"attach\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (attach </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">!=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> &#x26;&#x26;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> attach.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">size</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">></span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 0</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> AttachmentPanel panel </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> view.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getControl</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"附件面板\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> map </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> attach) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> map.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"lastModified\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> Date</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getTime</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> filtername.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">add</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">((String)map.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"name\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">));</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> panel.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">upload</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(attach);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> view.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">updateView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"附件面板\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> /**</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> * 从缓存中获取附件</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> * </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">@param</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> cache</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> * </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">@return</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> */</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>> </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(IPageCache </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">cache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String attach </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> cache.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"attach\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>> addAttachmentData </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (attach </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">!=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> getJson</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(attach) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">==</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> ?</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ArrayList&#x3C;>() </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> getJson</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(attach);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">else</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ArrayList&#x3C;>();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> addAttachmentData;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> /**</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> * 将从缓存中取到的附件转换成List&#x3C;Map&#x3C;String,Object>></span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> * </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">@param</span><span style=\"color:#E36209;--shiki-dark:#FFAB70\"> attach</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> * </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">@return</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> */</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">SuppressWarnings</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"unchecked\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>> </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getJson</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(String </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">attach</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> parseArray </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (List</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">Object</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) JSONArray.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">parseObject</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(attach, List.class);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List&#x3C;Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">>> List </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ArrayList&#x3C;>();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (Object parse </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> parseArray) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> map </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (Map</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">String, Object</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) parse;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">add</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(map);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"public class ContractResignEdit extends AbstractFormPlugin implements UploadListener\n{\n private static final Log log = LogFactory.getLog(ContractResignEdit.class);\n\n\n @Override\n public void registerListener(EventObject e)\n {\n super.registerListener(e);\n\n AttachmentPanel attachmentPanel = this.getView().getControl(&quot;附件面板&quot;);\n attachmentPanel.addUploadListener(this);\n\n this.addClickListeners(&quot;btncancel&quot;, &quot;btnok&quot;);\n }\n\n @Override\n public void beforeUpload(BeforeUploadEvent evt) {\n UploadListener.super.beforeUpload(evt);\n IPageCache pageCache = this.getView().getPageCache();\n pageCache.put(&quot;falg&quot;, null);\n }\n\n @Override\n public void afterUpload(UploadEvent evt) {\n this.addAttachmentContext(this.getModel(), this.getView());\n IPageCache pageCache = this.getView().getPageCache();\n pageCache.put(&quot;falg&quot;, null);\n }\n\n private void addAttachmentContext(IDataModel model, IFormView view) {\n IPageCache cache = this.getPageCache();\n List<Map<String, Object>> addAttachmentData = getCache(cache);\n\n cache.put(&quot;attach&quot;, addAttachmentData.toString());\n log.error(&quot;上传附件之后:&quot; + addAttachmentData);\n }\n\n @Override\n public void upload(UploadEvent evt) {\n Object[] urls = evt.getUrls();\n IPageCache cache = this.getPageCache();\n List<Map<String, Object>> addAttachmentData = getCache(cache);\n for (Object url : urls) {\n @SuppressWarnings(&quot;unchecked&quot;)\n Map<String, Object> att = (Map<String, Object>) url;\n addAttachmentData.add(att);\n log.error(&quot;上传附件:&quot; + addAttachmentData);\n }\n cache.put(&quot;attach&quot;, JSONObject.toJSONString(addAttachmentData));\n }\n\n @Override\n public void remove(UploadEvent evt) {\n this.removeAttachmentContext(this.getView(), this.getModel(), evt);\n }\n\n private void removeAttachmentContext(IFormView view, IDataModel model, UploadEvent evt) {\n IFormView parentView = view.getParentView();\n AttachmentPanel panel = parentView.getControl(&quot;附件面板&quot;);\n AttachmentPanel source = (AttachmentPanel) evt.getSource();\n\n IPageCache cache = this.getPageCache();\n List<Map<String, Object>> addAttachmentData = getCache(cache);\n\n Object[] urls = evt.getUrls();\n for (Object url : urls) {\n @SuppressWarnings(&quot;unchecked&quot;)\n Map<String, Object> att = (Map<String, Object>) url;\n panel.remove(att);\n\n for (int i = 0; i < addAttachmentData.size(); i++) {\n Map<String, Object> map = addAttachmentData.get(i);\n if (map.get(&quot;name&quot;).equals(att.get(&quot;name&quot;))) {\n addAttachmentData.remove(i);\n }\n }\n }\n cache.put(&quot;attach&quot;, JSONObject.toJSONString(addAttachmentData));\n log.error(&quot;删除附件:&quot; + addAttachmentData);\n evt.setCancel(true);\n List<Map<String, Object>> attachmentData = panel.getAttachmentData();\n attachmentData.addAll(addAttachmentData);\n source.bindData(attachmentData);\n parentView.invokeOperation(&quot;refresh&quot;);\n view.sendFormAction(parentView);\n }\n\n @Override\n public void click(EventObject e)\n {\n super.click(e);\n Control source = (Control) e.getSource();\n String key = source.getKey();\n if (&quot;btncancel&quot;.equals(key)) {\n this.getView().returnDataToParent(null);\n this.getView().close();\n }\n if (&quot;btnok&quot;.equals(key)) {\n btnOk();\n }\n }\n\n private void btnOk() {\n DynamicObject dataEntity = this.getModel().getDataEntity();\n HashMap<String, Object> hashMap = new HashMap<>();\n IPageCache cache = this.getPageCache();\n List<Map<String, Object>> addAttachmentData = getCache(cache);\n hashMap.put(&quot;attach&quot;, addAttachmentData);\n long user = dataEntity.getLong(&quot;用户.id&quot;);\n Date date = dataEntity.getDate(&quot;日期&quot;);\n hashMap.put(&quot;user&quot;, user);\n hashMap.put(&quot;date&quot;, date);\n log.error(&quot;关闭界面之前:&quot; + addAttachmentData);\n this.getView().returnDataToParent(hashMap);\n this.getView().close();\n addAttachmentData.clear();//关闭界面清空上传附件\n log.error(&quot;关闭界面:&quot; + addAttachmentData);\n }\n\n @Override\n public void afterCreateNewData(EventObject e) {\n super.afterCreateNewData(e);\n this.creadteAttach(this.getView(), this.getModel(), e);\n IPageCache cache = this.getPageCache();\n List<Map<String, Object>> addAttachmentData = getCache(cache);\n log.error(&quot;刷新界面&quot; + addAttachmentData);\n }\n\n private void creadteAttach(IFormView view, IDataModel model, EventObject e) {\n FormShowParameter showParameter = view.getFormShowParameter();\n List<String> filtername = new ArrayList<>();\n List<Map<String, Object>> attach = showParameter.getCustomParam(&quot;attach&quot;);\n if (attach != null && attach.size() > 0) {\n AttachmentPanel panel = view.getControl(&quot;附件面板&quot;);\n for (Map<String, Object> map : attach) {\n map.put(&quot;lastModified&quot;, new Date().getTime());\n filtername.add((String)map.get(&quot;name&quot;));\n }\n panel.upload(attach);\n view.updateView(&quot;附件面板&quot;);\n\n }\n }\n\n /**\n * 从缓存中获取附件\n * @param cache\n * @return\n */\n private List<Map<String, Object>> getCache(IPageCache cache) {\n String attach = cache.get(&quot;attach&quot;);\n List<Map<String, Object>> addAttachmentData = null;\n if (attach != null) {\n addAttachmentData = getJson(attach) == null ? new ArrayList<>() : getJson(attach);\n }else {\n addAttachmentData = new ArrayList<>();\n }\n return addAttachmentData;\n }\n\n /**\n * 将从缓存中取到的附件转换成List<Map<String,Object>>\n * @param attach\n * @return\n */\n @SuppressWarnings(&quot;unchecked&quot;)\n private List<Map<String, Object>> getJson(String attach) {\n List<Object> parseArray = (List<Object>) JSONArray.parseObject(attach, List.class);\n List<Map<String, Object>> List = new ArrayList<>();\n for (Object parse : parseArray) {\n Map<String, Object> map = (Map<String, Object>) parse;\n List.add(map);\n }\n return List;\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h3 id=\"%E5%8D%95%E6%8D%AE\" tabindex=\"-1\">单据</h3>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> beforeDoOperation</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(BeforeDoOperationEventArgs e)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 双签附件回填</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"contractresigning\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(operateKey))</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String billstatus </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> dataEntity.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"billstatus\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"C\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(billstatus))</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> FormShowParameter parameter </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> FormShowParameter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setStatus</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(OperationStatus.ADDNEW);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getOpenStyle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setShowType</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(ShowType.Modal);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setFormId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"动态表单标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setCloseCallBack</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> CloseCallBack</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"关闭标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">));</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> view.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">showForm</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(parameter);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> else</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">showErrorNotification</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"当前合同还未审核,不允许回签!\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> putAttachmentData</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Map </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String, Object </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> attachInfor, IDataModel modal, IFormView view)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String entityId </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> view.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getEntityId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> view.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">invokeOperation</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"refresh\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(attachInfor </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">!=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List &#x3C; Map &#x3C; </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> >> retData </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (List </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Map </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String, Object </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">>></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ) attachInfor.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"attach\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Long userId </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (Long) attachInfor.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"user\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Date date </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (Date) attachInfor.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"date\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DynamicObject dataEntity </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> modal.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDataEntity</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // ...</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(retData </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">!=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> &#x26;&#x26;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> !</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">retData.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">isEmpty</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">())</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Map &#x3C; </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> > map</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> retData)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String url </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (String) map.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"url\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String name </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (String) map.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"name\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 持久化附件到服务器</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> url </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> SalesOrderUtils.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">uploadTempfile</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(url, name);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> map.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"url\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, url);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> map.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"creator\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, UserServiceHelper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getCurrentUserId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> map.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"modifytime\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> Date</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getTime</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> AttachmentServiceHelper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">upload</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(entityId, dataEntity.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getPkValue</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(), </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"yem_attachmentpanelap\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, retData);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> SaveServiceHelper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">save</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> DynamicObject</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">[]</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> dataEntity</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> });</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> view.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">invokeOperation</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"refresh\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> closedCallBack</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(ClosedCallBackEvent e)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"关闭标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(actionId))</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> putAttachmentData</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">((Map </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String, Object </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">></span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ) returnData, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getModel</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(), </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\">// 附件持久化</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> static</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">uploadTempfile</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(String url, String name)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> TempFileCache cache </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> CacheFactory.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getCommonCacheFactory</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getTempFileCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> InputStream in </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> cache.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getInputStream</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(url);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> FileService service </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> FileServiceFactory.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getAttachmentFileService</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> RequestContext requestContext </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> RequestContext.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String uuid </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> UUID.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">randomUUID</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">replace</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"-\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 生成文件路径-上传附件时远程服务器需要存储文件的位置</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String pathParam </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> FileNameUtils.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getAttachmentFileName</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(requestContext.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getTenantId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(), requestContext.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getAccountId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(), uuid, name); </span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> FileItem fileItem </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> FileItem</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(name, pathParam, in );</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 上传附件到文件服务器</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> service.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">upload</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(fileItem);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"@Override\npublic void beforeDoOperation(BeforeDoOperationEventArgs e)\n{\n // 双签附件回填\n if(&quot;contractresigning&quot;.equals(operateKey))\n {\n String billstatus = dataEntity.getString(&quot;billstatus&quot;);\n if(&quot;C&quot;.equals(billstatus))\n {\n FormShowParameter parameter = new FormShowParameter();\n parameter.setStatus(OperationStatus.ADDNEW);\n parameter.getOpenStyle().setShowType(ShowType.Modal);\n parameter.setFormId(&quot;动态表单标识&quot;);\n parameter.setCloseCallBack(new CloseCallBack(this, &quot;关闭标识&quot;));\n view.showForm(parameter);\n }\n else\n {\n this.getView().showErrorNotification(&quot;当前合同还未审核,不允许回签!&quot;);\n }\n }\n}\n\npublic void putAttachmentData(Map < String, Object > attachInfor, IDataModel modal, IFormView view)\n{\n String entityId = view.getEntityId();\n view.invokeOperation(&quot;refresh&quot;);\n if(attachInfor != null)\n {\n List < Map < String, Object >> retData = (List < Map < String, Object >> ) attachInfor.get(&quot;attach&quot;);\n Long userId = (Long) attachInfor.get(&quot;user&quot;);\n Date date = (Date) attachInfor.get(&quot;date&quot;);\n DynamicObject dataEntity = modal.getDataEntity(true);\n // ...\n if(retData != null && !retData.isEmpty())\n {\n for(Map < String, Object > map: retData)\n {\n String url = (String) map.get(&quot;url&quot;);\n String name = (String) map.get(&quot;name&quot;);\n // 持久化附件到服务器\n url = SalesOrderUtils.uploadTempfile(url, name);\n map.put(&quot;url&quot;, url);\n map.put(&quot;creator&quot;, UserServiceHelper.getCurrentUserId());\n map.put(&quot;modifytime&quot;, new Date().getTime());\n }\n AttachmentServiceHelper.upload(entityId, dataEntity.getPkValue(), &quot;yem_attachmentpanelap&quot;, retData);\n }\n SaveServiceHelper.save(new DynamicObject[]\n {\n dataEntity\n });\n view.invokeOperation(&quot;refresh&quot;);\n }\n}\n\n@Override\npublic void closedCallBack(ClosedCallBackEvent e)\n{\n if(&quot;关闭标识&quot;.equals(actionId))\n {\n putAttachmentData((Map < String, Object > ) returnData, this.getModel(), this.getView());\n }\n}\n\n// 附件持久化\npublic static String uploadTempfile(String url, String name)\n{\n TempFileCache cache = CacheFactory.getCommonCacheFactory().getTempFileCache();\n InputStream in = cache.getInputStream(url);\n FileService service = FileServiceFactory.getAttachmentFileService();\n RequestContext requestContext = RequestContext.get();\n String uuid = UUID.randomUUID().toString().replace(&quot;-&quot;, &quot;&quot;);\n // 生成文件路径-上传附件时远程服务器需要存储文件的位置\n String pathParam = FileNameUtils.getAttachmentFileName(requestContext.getTenantId(), requestContext.getAccountId(), uuid, name); \n FileItem fileItem = new FileItem(name, pathParam, in );\n // 上传附件到文件服务器\n return service.upload(fileItem);\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E8%A1%8C%E6%94%BF%E7%BB%84%E7%BB%87%2F%E4%B8%9A%E5%8A%A1%E5%8D%95%E5%85%83%E9%80%9A%E8%BF%87%E4%B8%8A%E7%BA%A7%E7%BB%84%E7%BB%87\" tabindex=\"-1\">行政组织/业务单元通过上级组织</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">List&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Long</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> ids </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ArrayList&#x3C;>();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">long</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> orgId </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> org.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getLong</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">ids.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">add</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(orgId);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">QFilter qFilter </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> QFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"org.id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, QCP.equals, orgId);</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\">// 业务单元视图默认方案</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">qFilter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">and</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> QFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"view.number\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, QCP.equals, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"15\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">));</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">DynamicObject single </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> BusinessDataServiceHelper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">loadSingle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"bos_org_structure\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, qFilter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toArray</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (single </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">==</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">List&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Long</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> allSubordinateOrgs </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> OrgUnitServiceHelper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getAllSubordinateOrgs</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(single.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"parent.number\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">), ids, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">QFilter qFilterA </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> QFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, QCP.in, allSubordinateOrgs);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">e.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">addCustomQFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(qFilterA);</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"List<Long> ids = new ArrayList<>();\nlong orgId = org.getLong(&quot;id&quot;);\nids.add(orgId);\nQFilter qFilter = new QFilter(&quot;org.id&quot;, QCP.equals, orgId);\n// 业务单元视图默认方案\nqFilter.and(new QFilter(&quot;view.number&quot;, QCP.equals, &quot;15&quot;));\nDynamicObject single = BusinessDataServiceHelper.loadSingle(&quot;bos_org_structure&quot;, qFilter.toArray());\nif (single == null) return;\nList<Long> allSubordinateOrgs = OrgUnitServiceHelper.getAllSubordinateOrgs(single.getString(&quot;parent.number&quot;), ids, true);\nQFilter qFilterA = new QFilter(&quot;id&quot;, QCP.in, allSubordinateOrgs);\ne.addCustomQFilter(qFilterA);\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> static</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> QFilter </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getOrgFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(DynamicObject org) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (org </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">==</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">return</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> List &#x3C; </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Long</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> > ids </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ArrayList &#x3C; > ();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String number </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> org.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"number\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> QFilter qFilter </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> QFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"longnumber\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, QCP.like, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"%!\"</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> +</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> number </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">+</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> \"!%\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> qFilter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">and</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> QFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"view.number\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, QCP.equals, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"15\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">));</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> DynamicObject</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">[] entries </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> BusinessDataServiceHelper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">load</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"bos_org_structure\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"id, org.id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, qFilter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toArray</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> for</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (DynamicObject dynamicObject</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">:</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> entries) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> long</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> orgId </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> dynamicObject.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getLong</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"org.id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ids.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">add</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(orgId);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> QFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, QCP.in, ids);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"public static QFilter getOrgFilter(DynamicObject org) {\n if (org == null) return null;\n List < Long > ids = new ArrayList < > ();\n String number = org.getString(&quot;number&quot;);\n QFilter qFilter = new QFilter(&quot;longnumber&quot;, QCP.like, &quot;%!&quot; + number + &quot;!%&quot;);\n qFilter.and(new QFilter(&quot;view.number&quot;, QCP.equals, &quot;15&quot;));\n DynamicObject[] entries = BusinessDataServiceHelper.load(&quot;bos_org_structure&quot;, &quot;id, org.id&quot;, qFilter.toArray());\n for (DynamicObject dynamicObject: entries) {\n long orgId = dynamicObject.getLong(&quot;org.id&quot;);\n ids.add(orgId);\n }\n return new QFilter(&quot;id&quot;, QCP.in, ids);\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"bigdecimal%E6%AF%94%E8%BE%83%E5%A4%A7%E5%B0%8F\" tabindex=\"-1\">BigDecimal比较大小</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (a.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">compareTo</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(b) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">==</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> -</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">1</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">){</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> System.out.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">println</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"a小于b\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (a.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">compareTo</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(b) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">==</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 0</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">){</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> System.out.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">println</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"a等于b\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (a.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">compareTo</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(b) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">==</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 1</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">){</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> System.out.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">println</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"a大于b\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (a.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">compareTo</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(b) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">></span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> -</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">1</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">){</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> System.out.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">println</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"a大于等于b\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (a.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">compareTo</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(b) </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">&#x3C;</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 1</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">){</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> System.out.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">println</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"a小于等于b\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"if (a.compareTo(b) == -1){\n System.out.println(&quot;a小于b&quot;);\n}\nif (a.compareTo(b) == 0){\n System.out.println(&quot;a等于b&quot;);\n}\nif (a.compareTo(b) == 1){\n System.out.println(&quot;a大于b&quot;);\n}\nif (a.compareTo(b) > -1){\n System.out.println(&quot;a大于等于b&quot;);\n}\nif (a.compareTo(b) < 1){\n System.out.println(&quot;a小于等于b&quot;);\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E5%A4%9A%E9%80%89%E5%9F%BA%E7%A1%80%E8%B5%84%E6%96%99%E5%8F%96%E5%80%BC\" tabindex=\"-1\">多选基础资料取值</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">DynamicObjectCollection shipports </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> dataEntity.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDynamicObjectCollection</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"shipports\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">DynamicObject dynamicObject </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> shipports.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getDynamicObject</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"fbasedataid\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">dynamicObject.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"namecn\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"DynamicObjectCollection shipports = dataEntity.getDynamicObjectCollection(&quot;shipports&quot;);\nDynamicObject dynamicObject = shipports.getDynamicObject(&quot;fbasedataid&quot;);\ndynamicObject.getString(&quot;namecn&quot;)\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E8%8E%B7%E5%8F%96%E5%88%97%E8%A1%A8%E8%BF%87%E6%BB%A4%E6%9D%A1%E4%BB%B6%E5%AD%97%E6%AE%B5%E5%80%BC\" tabindex=\"-1\">获取列表过滤条件字段值</h2>\n<ul>\n<li>列表</li>\n</ul>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">List&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> selectedMainOrgIds </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getControlFilters</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"org.id\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getPageCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">put</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"currSelectedOrg\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, JSON.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toJSONString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(selectedMainOrgIds));</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"List<Object> selectedMainOrgIds = this.getControlFilters().getFilter(&quot;org.id&quot;);\nthis.getPageCache().put(&quot;currSelectedOrg&quot;, JSON.toJSONString(selectedMainOrgIds));\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<ul>\n<li>单据</li>\n</ul>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">String currSelectedOrg </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getParentView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getPageCache</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"currSelectedOrg\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">Object parse </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> JSON.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">parse</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(currSelectedOrg);</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"String currSelectedOrg = this.getView().getParentView().getPageCache().get(&quot;currSelectedOrg&quot;);\nObject parse = JSON.parse(currSelectedOrg);\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"beforedooperation\" tabindex=\"-1\">beforeDoOperation</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> beforeDoOperation</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(BeforeDoOperationEventArgs args)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">{</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> super</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">beforeDoOperation</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(args);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> FormOperate operate </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (FormOperate) args.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getSource</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String operateKey </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> operate.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getOperateKey</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"new\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(operateKey)) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"@Override\npublic void beforeDoOperation(BeforeDoOperationEventArgs args)\n{\n super.beforeDoOperation(args);\n FormOperate operate = (FormOperate) args.getSource();\n String operateKey = operate.getOperateKey();\n if (&quot;new&quot;.equals(operateKey)) {\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"formshowparameter\" tabindex=\"-1\">FormShowParameter</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">FormShowParameter parameter </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> FormShowParameter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setStatus</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(OperationStatus.ADDNEW);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getOpenStyle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setShowType</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(ShowType.Modal);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setFormId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"formId\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setCustomParam</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"opType\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, operateKey);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setCloseCallBack</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> CloseCallBack</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"formId\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">));</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">view.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">showForm</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(parameter);</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"FormShowParameter parameter = new FormShowParameter();\nparameter.setStatus(OperationStatus.ADDNEW);\nparameter.getOpenStyle().setShowType(ShowType.Modal);\nparameter.setFormId(&quot;formId&quot;);\nparameter.setCustomParam(&quot;opType&quot;, operateKey);\nparameter.setCloseCallBack(new CloseCallBack(this, &quot;formId&quot;));\nview.showForm(parameter);\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"listshowparameter\" tabindex=\"-1\">ListShowParameter</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">ListShowParameter parameter </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> ListShowParameter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setBillFormId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"单据标识\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setMultiSelect</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setParentPageId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getPageId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setStatus</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(OperationStatus.VIEW);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getOpenStyle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setShowType</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(ShowType.Modal);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getOpenStyle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setCacheId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getPageId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setLookUp</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">StyleCss css </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> StyleCss</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">css.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setHeight</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"580\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">css.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setWidth</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"960\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getOpenStyle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setInlineStyleCss</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(css);</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\">// 过滤条件</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">ListFilterParameter listFilterParameter </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> ListFilterParameter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">listFilterParameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setFilter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(qFilter);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setListFilterParameter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(listFilterParameter);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">parameter.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setCloseCallBack</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> CloseCallBack</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"actionId\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">));</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"ListShowParameter parameter = new ListShowParameter();\nparameter.setBillFormId(&quot;单据标识&quot;);\nparameter.setMultiSelect(true);\nparameter.setParentPageId(this.getView().getPageId());\nparameter.setStatus(OperationStatus.VIEW);\nparameter.getOpenStyle().setShowType(ShowType.Modal);\nparameter.getOpenStyle().setCacheId(parameter.getPageId());\nparameter.setLookUp(true);\nStyleCss css = new StyleCss();\ncss.setHeight(&quot;580&quot;);\ncss.setWidth(&quot;960&quot;);\nparameter.getOpenStyle().setInlineStyleCss(css);\n// 过滤条件\nListFilterParameter listFilterParameter = new ListFilterParameter();\nlistFilterParameter.setFilter(qFilter);\nparameter.setListFilterParameter(listFilterParameter);\nparameter.setCloseCallBack(new CloseCallBack(this, &quot;actionId&quot;));\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E4%BA%8C%E6%AC%A1%E7%A1%AE%E8%AE%A4%E5%BC%B9%E7%AA%97\" tabindex=\"-1\">二次确认弹窗</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> registerListener</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(EventObject e) {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">addClickListeners</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"btnok\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> confirmCallBack</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(MessageBoxClosedEvent e) {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> super</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">confirmCallBack</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(e);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String callBackId </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> e.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getCallBackId</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"btnok\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(callBackId)) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (MessageBoxResult.Yes.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(e.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getResult</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">())) {</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> btnOk</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Override</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> void</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> click</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(EventObject e) {</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> super</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">click</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(e);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Control control </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (Control) e.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getSource</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> String key </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> control.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getKey</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"btnok\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">equals</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(key)) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ConfirmCallBackListener confirmCallBackListener </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> ConfirmCallBackListener</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"btnok\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> this</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getView</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">showConfirm</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(sb.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">toString</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(), MessageBoxOptions.YesNo, confirmCallBackListener);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"@Override\npublic void registerListener(EventObject e) {\n this.addClickListeners(&quot;btnok&quot;);\n}\n\n@Override\npublic void confirmCallBack(MessageBoxClosedEvent e) {\n super.confirmCallBack(e);\n String callBackId = e.getCallBackId();\n if (&quot;btnok&quot;.equals(callBackId)) {\n if (MessageBoxResult.Yes.equals(e.getResult())) {\n btnOk();\n }\n }\n}\n\n@Override\npublic void click(EventObject e) {\n super.click(e);\n Control control = (Control) e.getSource();\n String key = control.getKey();\n if (&quot;btnok&quot;.equals(key)) {\n ConfirmCallBackListener confirmCallBackListener = new ConfirmCallBackListener(&quot;btnok&quot;, this);\n this.getView().showConfirm(sb.toString(), MessageBoxOptions.YesNo, confirmCallBackListener);\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n"},{"_id":"65ca3152912f6564d5af0899","shortLink":"blog-bug-track","title":"Blog BUG Track","description":"记录目前Blog存在的bug和修复计划","category":"short","tags":["bug"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-12-02T16:55:08.652Z","updatedAt":"2024-02-28T20:03:44.593Z","status":"PUBLISHED","views":20,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/3cb99c5a624b62fcc84a5de1b0879d0581b1c971b74faed78f18f50705e0f520.png","html":"<ul class=\"task-list\">\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_0\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_0\"> � 搜索功能响应数据为空</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_1\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_1\"> <s>� 搜索功能优化(接入第三方搜索)</s></label>\n<ul class=\"task-list\">\n<li>不使用第三方搜索,改为使用搜索弹窗</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_2\" disabled=\"true\" /><label for=\"cbx_2\"> <code>Commanf</code> + <code>K</code>全局搜索</label></li>\n</ul>\n</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_3\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_3\"> admin自动保存只有在有更改之后才开启</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_4\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_4\"> twitter卡片不显示</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_5\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_5\"> md-ediitor-v3 theme亮色时显示错误</label>\n<ul>\n<li>手动配置Markdown-it</li>\n</ul>\n</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_6\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_6\"> 修改自动保存逻辑,文字编辑过之后固定15秒更新,<code>ctrl</code> + <code>s</code>立即更新</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_7\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_7\"> 主页添加feated article、short、project</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_8\" disabled=\"true\" /><label for=\"cbx_8\"> 文章底部添加上一篇和下一篇卡片</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_9\" disabled=\"true\" /><label for=\"cbx_9\"> 无限滚动</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_10\" disabled=\"true\" /><label for=\"cbx_10\"> 点赞功能</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_11\" disabled=\"true\" /><label for=\"cbx_11\"> AI生成摘要功能</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_12\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_12\"> 路由切换时,保留已请求的数据(将请求数据缓存到pinia中)</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_13\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_13\"> 响应的数据中包含类型信息(article、short、project)</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_14\" disabled=\"true\" /><label for=\"cbx_14\"> <s>project页面重绘</s></label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_15\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_15\"> <s>自动隐藏,显示的header</s></label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_16\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_16\"> 写一篇完整的about</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_17\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_17\"> 返回顶部按钮</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_18\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_18\"> 手机端响应式header</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_19\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_19\"> 首页字体</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_20\" disabled=\"true\" /><label for=\"cbx_20\"> 获取GitHub贡献图,在首页显示</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_21\" disabled=\"true\" /><label for=\"cbx_21\"> Java根据文章内容生成twitter卡片图(参考Github图)</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_22\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_22\"> 缓存,缓存更新</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_23\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_23\"> redis统计文章阅读数,定时写入mongo</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_24\" disabled=\"true\" /><label for=\"cbx_24\"> RSS</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_25\" disabled=\"true\" /><label for=\"cbx_25\"> read later,从telegram接收消息,写入read later列表</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_26\" disabled=\"true\" /><label for=\"cbx_26\"> <s>文章如果有更新,定时以文件形式提交到GitHub,文件头中写入发布时间、更新时间、分类、标签信息</s></label>\n<ul>\n<li>改为上传到r2中</li>\n</ul>\n</li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_27\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_27\"> project卡片左上角添加右上角的新标签页打开提示</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_28\" disabled=\"true\" /><label for=\"cbx_28\"> <s>鼠标悬停在link上时,显示连接对应网页画面</s></label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_29\" checked=\"true\" disabled=\"true\" /><label for=\"cbx_29\"> header中颜色动态变化</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_30\" disabled=\"true\" /><label for=\"cbx_30\"> 友链功能</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_31\" disabled=\"true\" /><label for=\"cbx_31\"> SEO OG image生成</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_32\" disabled=\"true\" /><label for=\"cbx_32\"> NuxtUI边框颜色会会变化</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_33\" disabled=\"true\" /><label for=\"cbx_33\"> 缓存更新问题</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_34\" disabled=\"true\" /><label for=\"cbx_34\"> MDC支持</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_35\" disabled=\"true\" /><label for=\"cbx_35\"> 显示Twitter卡片,支持MDC之后</label></li>\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_36\" disabled=\"true\" /><label for=\"cbx_36\"> admin 大文件10mb 上传请求超时问题</label>\n<ul class=\"task-list\">\n<li class=\"task-list-item\"><input type=\"checkbox\" id=\"cbx_37\" disabled=\"true\" /><label for=\"cbx_37\"> 上传之后存表,包括文件hash和文件地址,如果hash相同直接返回地址</label></li>\n</ul>\n</li>\n</ul>\n"},{"_id":"65ca3152912f6564d5af0898","shortLink":"singleton-pattern","title":"Singleton Pattern","description":"Singleton Pattern Template","category":"short","tags":["codesnap"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-12-01T15:22:11.521Z","updatedAt":"2024-02-27T03:25:42.457Z","status":"PUBLISHED","views":17,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/f2a46c5c6cc93358b95090b290e5f4face31c8602cb4c4764601b4e31e19b480.png","html":"\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> class</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> DateUtils</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> static</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DateUtils instance;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> </span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> private</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> DateUtils</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() {</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 私有构造函数,防止外部实例化</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> </span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> static</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> DateUtils </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getInstance</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">() {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (instance </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">==</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> synchronized</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (DateUtils.class) {</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> if</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> (instance </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">==</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> null</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> instance </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> DateUtils</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> instance;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> </span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> int</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> getYear</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Date </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">date</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Calendar calendar </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Calendar.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">getInstance</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> calendar.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setTime</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(date);</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> calendar.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">get</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Calendar.YEAR);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">}</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"public class DateUtils {\n private static DateUtils instance;\n \n private DateUtils() {\n // 私有构造函数,防止外部实例化\n }\n \n public static DateUtils getInstance() {\n if (instance == null) {\n synchronized (DateUtils.class) {\n if (instance == null) {\n instance = new DateUtils();\n }\n }\n }\n return instance;\n }\n \n public int getYear(Date date) {\n Calendar calendar = Calendar.getInstance();\n calendar.setTime(date);\n return calendar.get(Calendar.YEAR);\n }\n}\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n"},{"_id":"65ca3152912f6564d5af0897","shortLink":"bos-plugin-lifecyle","title":"Bos Plugin lifecycle","description":"金蝶Bos中各类插件执行顺序","category":"short","tags":["bos"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-11-28T02:18:14.180Z","updatedAt":"2024-02-27T03:25:49.809Z","status":"PUBLISHED","views":17,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/b1080410165d912a403e8b7cc5fcb7bf985aec05f8174a67ee2b340215207804.png","cover":"","html":"<h2 id=\"abstractbillplugin\" tabindex=\"-1\">AbstractBillPlugIn</h2>\n<p>用于配置业务规则。(如值更新、按钮点击事件)</p>\n<p>!!! abstract SDK\n<a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/index.html?nav=class&amp;module=kd.bos.svc.watermark&amp;package=kd.bos.form.plugin&amp;name=AbstractFormPlugin\">https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/index.html?nav=class&amp;module=kd.bos.svc.watermark&amp;package=kd.bos.form.plugin&amp;name=AbstractFormPlugin</a>\n!!!</p>\n<table>\n<thead>\n<tr>\n<th>分类</th>\n<th>事件</th>\n<th>触发时机</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>界面显示前</td>\n<td>setPluginName</td>\n<td>显示界面,准备构建界面显示配置formConfig前,构建插件时触发此事件,传入脚本名称</td>\n</tr>\n<tr>\n<td>显示界面前</td>\n<td>preOpenForm</td>\n<td>显示界面前,准备构建界面显示参数时,触发此事件</td>\n</tr>\n<tr>\n<td>显示界面前</td>\n<td>loadCustomControlMetas</td>\n<td>显示界面前,构建界面显示参数时,触发事件</td>\n</tr>\n<tr>\n<td>界面初始化</td>\n<td>setView</td>\n<td>表单视图模型初始化,创建插件时调用此方法,向插件传入表单视图模型IFOrmView</td>\n</tr>\n<tr>\n<td>界面初始化</td>\n<td>initialize</td>\n<td>表单视图模型初始化,创建插件后,触发</td>\n</tr>\n<tr>\n<td>界面初始化</td>\n<td>registerListener</td>\n<td>于表单控件发生交互时触发</td>\n</tr>\n<tr>\n<td>界面初始化</td>\n<td>getEntityType</td>\n<td>表单基于实体模型,创建数据包之前触发</td>\n</tr>\n<tr>\n<td>页面初始化或刷新</td>\n<td>createNewData</td>\n<td>页面初始化或刷新,开始新建数据包之前触发</td>\n</tr>\n<tr>\n<td>页面初始化或刷新</td>\n<td>afterCreateNewData</td>\n<td>页面初始化或刷新,新建数据包完成之后触发</td>\n</tr>\n<tr>\n<td>界面数据包构建完成</td>\n<td>afterBindData</td>\n<td>界面数据包构建完成,生成指令,刷新值,状态之后触发</td>\n</tr>\n<tr>\n<td>用户交互事件</td>\n<td>beforeItemClick</td>\n<td>用户点击时,执行操作之前</td>\n</tr>\n<tr>\n<td>用户交互事件</td>\n<td>itemClick</td>\n<td>用户点击时触发</td>\n</tr>\n<tr>\n<td>用户交互事件</td>\n<td>beforeDoOperation</td>\n<td>用户点击按钮,菜单,执行绑定操作前</td>\n</tr>\n<tr>\n<td>用户交互事件</td>\n<td>afterDoOperation</td>\n<td>用户点击按钮,菜单,执行绑定操作之后</td>\n</tr>\n<tr>\n<td>用户交互事件</td>\n<td>confirmCallBack</td>\n<td>前端交互提示确认后,通知插件后续处理</td>\n</tr>\n<tr>\n<td>用户交互事件</td>\n<td>closedCallBack</td>\n<td>子界面关闭时,父界面触发</td>\n</tr>\n<tr>\n<td>用户交互事件</td>\n<td>flexBeforeClosed</td>\n<td>弹性域维护界面关闭时,触发父界面此事件</td>\n</tr>\n<tr>\n<td>获取控件时</td>\n<td>onGetControl</td>\n<td>getControl时触发</td>\n</tr>\n<tr>\n<td>触发自定义控件的定制事件</td>\n<td>customEvent</td>\n<td>触发自定义控件的定制事件</td>\n</tr>\n<tr>\n<td>定时触发</td>\n<td>timerElapsed</td>\n<td>定时触发</td>\n</tr>\n<tr>\n<td>界面关闭</td>\n<td>beforeClosed</td>\n<td>界面关闭之后触发</td>\n</tr>\n<tr>\n<td>界面关闭</td>\n<td>destory</td>\n<td>界面关闭后,释放资源时触发</td>\n</tr>\n<tr>\n<td>界面关闭</td>\n<td>pageRelease</td>\n<td>界面关闭后,释放资源时触发</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"abstractoperationserviceplugin\" tabindex=\"-1\">AbstractOperationServicePlugIn</h2>\n<p>!!! abstract SDK\n<a href=\"https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/index.html?nav=class&amp;module=kd.bos.kddm&amp;package=kd.bos.entity.plugin&amp;name=IOperationServicePlugIn\">https://dev.kingdee.com/sdk/Cosmic%20V6.0.1/index.html?nav=class&amp;module=kd.bos.kddm&amp;package=kd.bos.entity.plugin&amp;name=IOperationServicePlugIn</a>\n!!!</p>\n<table>\n<thead>\n<tr>\n<th>事件</th>\n<th>触发时机</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>onPreparePropertys</td>\n<td>在单据列表上执行单据操作,系统需要先根据传入的单据内码,加载单据数据包;在加载单据数据包之前,触发此事件;插件需要在此事件,添加需要用到的字段</td>\n</tr>\n<tr>\n<td>onAddValidators</td>\n<td>系统预置的操作校验器加载完毕,执行校验之前,触发此事件</td>\n</tr>\n<tr>\n<td>beforeExecuteOperationTransaction</td>\n<td>校验通过,开启事务之前触发,对数据进行预处理</td>\n</tr>\n<tr>\n<td>beginOperationTransaction</td>\n<td>校验通过,事务开启之后,数据提交到数据库之前触发</td>\n</tr>\n<tr>\n<td>rollbackOperation</td>\n<td>事务更新失败,回滚之后触发</td>\n</tr>\n<tr>\n<td>endOperationTransaction</td>\n<td>数据更新已提交,事务未提交之前触发</td>\n</tr>\n<tr>\n<td>afterExecuteOperationTransaction</td>\n<td>操作执行之后,事务提交之后触发</td>\n</tr>\n<tr>\n<td>onReturnOperation</td>\n<td>操作结束时触发此事件</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"abstractformplugin\" tabindex=\"-1\">AbstractFormPlugin</h2>\n<table>\n<thead>\n<tr>\n<th>事件</th>\n<th>触发时机</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>addClickListeners</td>\n<td>监听控件的点击事件(如按钮点击)</td>\n</tr>\n<tr>\n<td>addItemClickListeners</td>\n<td>监听控件的的子项点击事件(如工具栏)</td>\n</tr>\n<tr>\n<td>afterBindData</td>\n<td>表单界面数据绑定完毕事件</td>\n</tr>\n<tr>\n<td>afterDoOperation</td>\n<td>表单操作结束事件</td>\n</tr>\n<tr>\n<td>beforeBindData</td>\n<td>表单界面数据绑定前事件</td>\n</tr>\n<tr>\n<td>beforeClick</td>\n<td>控件点击前事件</td>\n</tr>\n<tr>\n<td>beforeClosed</td>\n<td>关闭表单前事件</td>\n</tr>\n<tr>\n<td>beforeDoOperation</td>\n<td>表单操作前事件</td>\n</tr>\n<tr>\n<td>click</td>\n<td>控件点击事件</td>\n</tr>\n<tr>\n<td>closedCallBack</td>\n<td>子界面关闭后的回调事件</td>\n</tr>\n<tr>\n<td>itemClick</td>\n<td>控件子项点击</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"abstractconvertplugin\" tabindex=\"-1\">AbstractConvertPlugIn</h2>\n<table>\n<thead>\n<tr>\n<th>事件</th>\n<th>方法</th>\n<th>描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>初始化变量事件</td>\n<td>initVariable</td>\n<td>获取上下文信息,构建一些必须的变量</td>\n</tr>\n<tr>\n<td>构建取数参数后事件</td>\n<td>afterBuildQueryParemeter</td>\n<td>添加额外的字段、过滤条件</td>\n</tr>\n<tr>\n<td>编译数据筛选条件前事件</td>\n<td>beforeBuildRowCondition</td>\n<td>设置忽略规则原生的条件,改用插件定制条件,或者在规则条件基础上,追加定制条件</td>\n</tr>\n<tr>\n<td>取源单数据前事件</td>\n<td>beforeGetSourceData</td>\n<td>修改取数语句、取数条件</td>\n</tr>\n<tr>\n<td>取源单数据后事件</td>\n<td>afterGetSourceData</td>\n<td>根据源单数据,获取其他定制的引用数据;也可以替换系统自动获取到的数据</td>\n</tr>\n<tr>\n<td>构建分单、行合并模式之前事件</td>\n<td>beforeBuildGroupMode</td>\n<td>调整分单、合并策略及依赖的字段</td>\n</tr>\n<tr>\n<td>初始化创建目标单据数据包前事件</td>\n<td>beforeCreateTarget</td>\n<td>这个事件,只在选单时触发:选单时,需要基于现有的目标单数据包,进行追加处理;插件可以在此事件,获取到现有的目标单数据包,提前进行定制处理</td>\n</tr>\n<tr>\n<td>创建目标单据数据包后事件</td>\n<td>afterCreateTarget</td>\n<td>这个事件,只在下推时触发,把根据分单规则创建好的目标单,传递给插件</td>\n</tr>\n<tr>\n<td>目标字段赋值完毕后事件</td>\n<td>afterFieldMapping</td>\n<td>插件可以在此基础上,继续填写目标字段值</td>\n</tr>\n<tr>\n<td>记录关联关系前事件</td>\n<td>beforeCreateLink</td>\n<td>取消记录关联关系</td>\n</tr>\n<tr>\n<td>记录关联关系后事件</td>\n<td>afterCreateLink</td>\n<td>根据系统自动记录的关联关系,进行相关数据的同步携带,如携带其他子单据体数据</td>\n</tr>\n<tr>\n<td>单据转换后事件,最后执行</td>\n<td>afterConvert</td>\n<td>插件可以在这个事件中,对生成的目标单数据,进行最后的修改</td>\n</tr>\n</tbody>\n</table>\n"},{"_id":"65ca3152912f6564d5af0896","shortLink":"proxy-settings","title":"Proxy Settings","category":"short","tags":["npm"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-11-27T15:22:38.519Z","updatedAt":"2024-03-01T03:36:23.376Z","status":"PUBLISHED","views":31,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/a87bab95d8a93c434187cd7c5d019311ca84de61d45d165f9bc2fd7e8be76361.png","html":"<h1 id=\"windows-cmd\" tabindex=\"-1\">Windows CMD</h1>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 设置http代理</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">set</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> http_proxy=http://127.0.0.1:7890</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">set</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> https_proxy=http://127.0.0.1:7890</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 设置socks5代理</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">set</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> http_proxy=socks5://127.0.0.1:7890</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">set</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> https_proxy=socks5://127.0.0.1:7890</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 取消代理</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">set</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> http_proxy=</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">set</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> https_proxy=</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"# 设置http代理\nset http_proxy=http://127.0.0.1:7890\nset https_proxy=http://127.0.0.1:7890\n\n# 设置socks5代理\nset http_proxy=socks5://127.0.0.1:7890\nset https_proxy=socks5://127.0.0.1:7890\n\n# 取消代理\nset http_proxy=\nset https_proxy=\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h1 id=\"powershell\" tabindex=\"-1\">PowerShell</h1>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">$Env:http_proxy=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"http://127.0.0.1:7890\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">$Env:https_proxy=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"http://127.0.0.1:7890\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"$Env:http_proxy=&quot;http://127.0.0.1:7890&quot;;\n$Env:https_proxy=&quot;http://127.0.0.1:7890&quot;;\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h1 id=\"git\" tabindex=\"-1\">Git</h1>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 设置http代理</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">git</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> config</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> --global</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> http.proxy</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> http://127.0.0.1:7890</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">git</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> config</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> --global</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> https.proxy</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> http://127.0.0.1:7890</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 设置socks5代理(可选)</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">git</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> config</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> --global</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> http.proxy</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> \"socks5://127.0.0.1:7890\"</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">git</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> config</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> --global</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> https.proxy</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> \"socks5://127.0.0.1:7890\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 取消代理</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">git</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> config</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> --global</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> --unset</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> http.proxy</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">git</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> config</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> --global</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> --unset</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> https.proxy</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"# 设置http代理\ngit config --global http.proxy http://127.0.0.1:7890\ngit config --global https.proxy http://127.0.0.1:7890\n\n# 设置socks5代理(可选)\ngit config --global http.proxy &quot;socks5://127.0.0.1:7890&quot;\ngit config --global https.proxy &quot;socks5://127.0.0.1:7890&quot;\n\n# 取消代理\ngit config --global --unset http.proxy\ngit config --global --unset https.proxy\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h1 id=\"bash\" tabindex=\"-1\">Bash</h1>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 设置http代理</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> http_proxy</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"http://127.0.0.1:7890\"</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> https_proxy</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"http://127.0.0.1:7890\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 设置socks5代理</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> http_proxy</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"socks5://127.0.0.1:7890\"</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">export</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> https_proxy</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"socks5://127.0.0.1:7890\"</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 取消代理</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">unset</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> http_proxy</span></span>\n<span class=\"line\"><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">unset</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> https_proxy</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"# 设置http代理\nexport http_proxy=&quot;http://127.0.0.1:7890&quot;\nexport https_proxy=&quot;http://127.0.0.1:7890&quot;\n\n# 设置socks5代理\nexport http_proxy=&quot;socks5://127.0.0.1:7890&quot;\nexport https_proxy=&quot;socks5://127.0.0.1:7890&quot;\n\n# 取消代理\nunset http_proxy\nunset https_proxy\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h1 id=\"npm\" tabindex=\"-1\">npm</h1>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 设置http代理</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">npm</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> config</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> set</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> proxy</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> http://127.0.0.1:7890</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">npm</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> config</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> set</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> https-proxy</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> http://127.0.0.1:7890</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 取消代理</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">npm</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> config</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> delete</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> proxy</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">npm</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> config</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> delete</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> https-proxy</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># NPM Mirror</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">npm</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> config</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> set</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> registry</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> https://registry.npmmirror.com</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 查看</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">npm</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> config</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> get</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> registry</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 使用一次</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">npm</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> install</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> --registry=http://registry.npmmirror.com</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 删除</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">npm</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> config</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> delete</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> registry</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"# 设置http代理\nnpm config set proxy http://127.0.0.1:7890\nnpm config set https-proxy http://127.0.0.1:7890\n\n# 取消代理\nnpm config delete proxy\nnpm config delete https-proxy\n\n# NPM Mirror\nnpm config set registry https://registry.npmmirror.com\n\n# 查看\nnpm config get registry\n\n# 使用一次\nnpm install --registry=http://registry.npmmirror.com\n\n# 删除\nnpm config delete registry\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n"},{"_id":"65ca3152912f6564d5af0895","shortLink":"project-umami","title":"Umami Analytics","description":"Umami Analytics for this site.","cover":"https://static.vio.vin/blog/2023/11/795a39bc36e1c2a447301088ecbacefb.png","category":"project","tags":["umami"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-11-27T14:02:14.854Z","updatedAt":"2024-02-28T13:55:25.725Z","status":"PUBLISHED","views":2,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/6f58548af3a1efe06963103a806592d42525a662cf847be669c6c3ca04578f62.png","link":"https://umami.vio.vin/share/ZxMIwBCbR54s3qvu/vio.vin","html":""},{"_id":"65ca3152912f6564d5af0894","shortLink":"project-music","title":"YesPlayMusic","description":"A visually stunning third-party Netease Cloud Music player.","cover":"https://static.vio.vin/blog/2023/11/e52a384f54f891b7d3b2ebd83bc39423.png","category":"project","tags":["opensource"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-11-27T02:15:06.921Z","updatedAt":"2024-02-15T06:42:08.610Z","status":"DELETED","views":2,"likes":0,"ogImage":"https://static.vio.vin/screenshot/2024/02/12/f5e60bd1-a978-431b-a5a7-c99024d863f2.png"},{"_id":"65ca3152912f6564d5af0893","shortLink":"project-live-room","title":"Live Stream Room","description":"My live streaming platform - a cutting-edge project that enables seamless live broadcasting for up to 5 simultaneous streamers.","cover":"https://static.vio.vin/blog/2023/11/5b3d320632d19c4c3085cc7bf9a6a4f2.png","category":"project","tags":["Nuxt.js","TencentCloud"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-11-27T02:10:37.932Z","updatedAt":"2024-02-17T01:03:16.964Z","status":"PUBLISHED","views":2,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/7c3951eb26de62de1365d3c1533e3cdfec7ba33e9b6d0cad28770b47e75bd55d.png","link":"https://live.vio.vin/"},{"_id":"65ca3152912f6564d5af0892","shortLink":"project-my-blog","title":"Nuxt Fullstock Blog","description":"My latest blog. Build with Nuxt.js","cover":"https://static.vio.vin/blog/2024/02/7790036e07cf3715f57d80e62ae45e04f79a8f1217f6032f08ff37d8ec745c36.png","category":"project","tags":["Nuxt.js","SpringBoot"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-11-27T02:06:41.112Z","updatedAt":"2024-02-25T06:53:32.464Z","status":"PUBLISHED","views":2,"likes":0,"ogImage":"https://static.vio.vin/screenshot/2024/02/bda1fe8b0770968fb45458bb887a2456483d19254ba6055509dbc6b4d79ed398.png","link":"https://vio.vin/"},{"_id":"65ca3152912f6564d5af0891","shortLink":"mysql-common","title":"MySQL","description":"MySQL数据库基础、MySQL架构、存储引擎、事务、锁、索引、日志等","cover":"https://static.vio.vin/blog/2024/02/5d47ec94e8443a65c6e958843dc585a6.png","category":"article","tags":["mysql"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-11-26T14:13:24.454Z","updatedAt":"2024-03-01T12:16:33.761Z","status":"PUBLISHED","views":64,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/6d8475838da094662629d0bc5314f360f77e8f992070e268424c569f0997c826.png","html":"<h1 id=\"%E7%9B%B8%E5%85%B3%E6%A6%82%E5%BF%B5\" tabindex=\"-1\">相关概念</h1>\n<ul>\n<li><strong>元组</strong>:二维表中,行称为元组。关系型数据库中,关系是一场表,表中的每行(即数据库中的每条纪律)是一个元组,每列是一个属性。</li>\n<li><strong>码</strong>:二维表中,列常委码。能唯一标识实体的属性,对应表中的列。</li>\n<li><strong>候选码</strong><span 学号=\"true\"><span 学号=\"true\"><span 学号=\"true\"><span 学号=\"true\">:关系中某一属性或属性的值能唯一标识一个元组,而其任何子集都不能在表示,则该属性组为候选码。例如:学生表中,</span></span></span></span>和都是候选码。</li>\n<li><strong>主码</strong>:主键,从候选码中选出来。</li>\n<li><strong>外码</strong>:外键。如果一个关系中的一个属性同时是另一个关系中的主码,则这个属性为外码。</li>\n<li><strong>主属性</strong>:候选码中出现的属性称为主属性。</li>\n<li><strong>非主属性</strong>:不包含在任何一个候选码中的属性。</li>\n</ul>\n<h2 id=\"drop%E3%80%81delete-%E4%B8%8E-truncate\" tabindex=\"-1\">drop、delete 与 truncate</h2>\n<h3 id=\"%E7%94%A8%E6%B3%95%E4%B8%8D%E5%90%8C\" tabindex=\"-1\">用法不同</h3>\n<h3 id=\"%E7%B1%BB%E5%9E%8B%E4%B8%8D%E5%90%8C\" tabindex=\"-1\">类型不同</h3>\n<ul>\n<li>DML语言:数据库操作语言(Data Manipulation Language),数据库增删改查,针对表中数据</li>\n<li>DDL语言:数据定义语言(Data Definition Language),对数据库内部对象创建、删除、修改的语言,针对数据库结构。</li>\n</ul>\n<p>delete为DML语言,执行之后delete操作会放到 rollback segement中,事务提交之后生效,也可回滚。</p>\n<p>drop和truncate为DLL原,执行之后立即生效,数据不能回滚。</p>\n<h4 id=\"%E6%89%A7%E8%A1%8C%E9%80%9F%E5%BA%A6%E4%B8%8D%E5%90%8C\" tabindex=\"-1\">执行速度不同</h4>\n<p>drop &gt; truncate &gt; delete</p>\n<h2 id=\"utf8-%E5%92%8C-utf8mb4\" tabindex=\"-1\">utf8 和 utf8mb4</h2>\n<ul>\n<li>\n<p><strong><code>utf8</code></strong> :</p>\n<ul>\n<li><code>utf8</code>编码只支持<code>1-3</code>个字节</li>\n<li>中文占 3 个字节,其他数字、英文、符号占一个字节。</li>\n<li>emoji 符号占 4 个字节,所以utf8不能存储emoji符号</li>\n</ul>\n</li>\n<li>\n<p><strong><code>utf8mb4</code></strong> : UTF-8 的完整实现。最多支持使用 4 个字节表示字符。可以用来存储 emoji 符号。</p>\n</li>\n</ul>\n<h1 id=\"%E6%95%B0%E6%8D%AE%E5%BA%93%E8%8C%83%E5%BC%8F\" tabindex=\"-1\">数据库范式</h1>\n<h2 id=\"%E7%AC%AC%E4%B8%80%E8%8C%83%E5%BC%8F-1nf\" tabindex=\"-1\">第一范式 1NF</h2>\n<p>原子性:数据库中属性(数据表中的列)不可再分割。</p>\n<h2 id=\"%E7%AC%AC%E4%BA%8C%E8%8C%83%E5%BC%8F-2nf\" tabindex=\"-1\">第二范式 2NF</h2>\n<p>在第一范式的基础上,表中的每一列都应该与主键关联。</p>\n<p>如在同一张表中存储学生基本信息和学生成绩,违背了第二范式。</p>\n<p><strong>每个表中的非主属性完全依赖于码</strong></p>\n<h2 id=\"%E7%AC%AC%E4%B8%89%E8%8C%83%E5%BC%8F-3nf\" tabindex=\"-1\">第三范式 3NF</h2>\n<p><strong>表中出非主属性之间不能互相依赖</strong></p>\n<p>在第二范式的基础上,消除非主属性之间的依赖关系,只保留非主属性与码的依赖关系</p>\n<h1 id=\"mysql%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B\" tabindex=\"-1\">MySQL数据类型</h1>\n<h2 id=\"%E6%95%B4%E5%BD%A2\" tabindex=\"-1\">整形</h2>\n<p><code>tinyint</code>,<code>smallint</code>,<code>middleint</code>,<code>int</code>,<code>bigint</code>,分别占用8、16、24、32、64存储空间</p>\n<h2 id=\"%E6%B5%AE%E7%82%B9%E6%95%B0\" tabindex=\"-1\">浮点数</h2>\n<ul>\n<li><code>float</code></li>\n<li><code>double</code></li>\n<li><code>decimal</code>:高精度小数类型。</li>\n</ul>\n<p>三种浮点数都可以指定列宽,例如使用<code>decimal(18,9)</code>表示总共18位,取9位保存小数部分,剩下的保存整数部分。</p>\n<h2 id=\"%E5%AD%97%E7%AC%A6%E4%B8%B2\" tabindex=\"-1\">字符串</h2>\n<ul>\n<li><code>char</code>:定长,会自动去除末尾的空格</li>\n<li><code>varchar</code>:变长,不会删除末尾的空格</li>\n<li><code>blog</code>:使用二进制形式保存</li>\n<li><code>text:使用字符串形式保存</code></li>\n</ul>\n<h2 id=\"%E6%97%B6%E9%97%B4\" tabindex=\"-1\">时间</h2>\n<ul>\n<li><code>datatime</code>:保存从1001年到999年的日期和时间,精度为秒,使用8字节存储空间,没有时区信息。</li>\n<li><code>timestamp</code>:保存1970-01-01开的时间。使用4字节保存,只能表示到2038年,有时区信息。</li>\n</ul>\n<h1 id=\"mysql%E5%9F%BA%E7%A1%80%E6%9E%B6%E6%9E%84\" tabindex=\"-1\">MySQL基础架构</h1>\n<figure><img src=\"https://typora-1308549476.cos.ap-nanjing.myqcloud.com/img/image-20220929151127280.png\" alt=\"image-20220929151127280\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<h1 id=\"mysql%E5%AD%98%E5%82%A8%E5%BC%95%E6%93%8E\" tabindex=\"-1\">MySQL存储引擎</h1>\n<p>使用<code>show engines</code>命令查看MySQL的存储引擎</p>\n<figure><img src=\"https://typora-1308549476.cos.ap-nanjing.myqcloud.com/img/image-20220919170313380.png\" alt=\"image-20220919170313380\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<p>常用的有InnoDB和MyISAM引擎</p>\n<p>默认使用InnoDB引擎</p>\n<h2 id=\"myisam\" tabindex=\"-1\">MyISAM</h2>\n<ul>\n<li>不支持事务</li>\n<li>不支持行级锁,只能对整张表加锁。<strong>读</strong>时加共享锁,<strong>写</strong>时加排他锁。</li>\n<li>数据丢失风险</li>\n</ul>\n<h2 id=\"innodb\" tabindex=\"-1\">InnoDB</h2>\n<ul>\n<li>支持事务,实现了四个隔离级别,默认级别时可重复读,通过MVCC(多版本并发控制)+Next-KeyLocking(间隙锁)防止幻读</li>\n<li>主索引是聚集索引</li>\n</ul>\n<h2 id=\"myisam-%E5%92%8C-innodb\" tabindex=\"-1\">MyISAM 和 InnoDB</h2>\n<ul>\n<li><strong>锁</strong>:MyISAM使用表级锁,InnoDB使用行级锁</li>\n<li><strong>事务</strong>:MyISAM不支持事务,InnoDb支持事务</li>\n<li><strong>外键</strong>:MyISAM不支持外键,InnoDB支持外键</li>\n<li><strong>崩溃恢复</strong>:MyISAM不支持奔溃后安全恢复,InnorDB支持奔溃后通过日志安全恢复</li>\n<li><strong>索引实现方式不同</strong>:两者都使用B+树的数据结构。MyISAM中索引文件和数据文件分离,InnorDB数据文件同时是索引文件</li>\n</ul>\n<h1 id=\"mysql-%E4%BA%8B%E5%8A%A1\" tabindex=\"-1\">MySQL 事务</h1>\n<p>事务:逻辑上的一组操作,要么都执行,要么都不执行。</p>\n<h2 id=\"%E4%BA%8B%E5%8A%A1%E7%9A%84%E7%89%B9%E6%80%A7\" tabindex=\"-1\">事务的特性</h2>\n<ol>\n<li>原子性(Atomicitly):一个事务包含的所有操作,要么全部成功,要么全部失败。</li>\n<li>一致性(Consistency):事务执行前后状态一致。例如转账:转账完成钱的总数不变。</li>\n<li>隔离性(Isolation):是否读未提交。</li>\n<li>持久性(Durability):事务提交后,数据库的更改是永久的。</li>\n</ol>\n<p>简称ACID</p>\n<h2 id=\"%E4%BA%8B%E5%8A%A1%E5%BC%95%E5%8F%91%E7%9A%84%E9%97%AE%E9%A2%98\" tabindex=\"-1\">事务引发的问题</h2>\n<ul>\n<li><strong>脏读</strong>:未提交的事务读到了另一个事务未提交的数据。</li>\n<li><strong>不可重复读</strong>:一个运行较慢事务在事务读取用一记录,两次读到的数据不同,主要针对update和delete。</li>\n<li><strong>幻读</strong>:两次读取到数据条数不同,针对insert。</li>\n</ul>\n<h2 id=\"%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB\" tabindex=\"-1\">事务隔离级别</h2>\n<ul>\n<li>(READ-UNCOMMITTED)读未提交:最低级别,允许读取尚未提交的数据变更,可能会导致脏读,不可重复读,幻读。</li>\n<li>(READ-COMMITTED)读已提交:允许读取已提交的数据,只能防止脏读。</li>\n<li>(REPEATABLE-READ)可重复读:一个事务开始,事务过程中所读取到的所有数据不允许被其他事物修改,不能防止幻读。</li>\n<li>(SERIALIZABLE)串行化:最高级别,防止所有问题,所有事务以串行化方式逐个执行。</li>\n</ul>\n<h2 id=\"%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB%E5%AE%9E%E7%8E%B0%E6%96%B9%E5%BC%8F\" tabindex=\"-1\">事务隔离级别实现方式</h2>\n<p>基于锁和MVCC机制实现。</p>\n<p>串行化隔离级别通过锁实现,其余隔离级别基于MVCC实现。</p>\n<h2 id=\"%E9%BB%98%E8%AE%A4%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB\" tabindex=\"-1\">默认隔离级别</h2>\n<p>通过执行<code>SELECT @@transaction_isolation;</code>命令查看</p>\n<figure><img src=\"https://typora-1308549476.cos.ap-nanjing.myqcloud.com/img/image-20220921121902513.png\" alt=\"image-20220921121902513\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<p>默认隔离级别是可重复读</p>\n<h1 id=\"mysql%E9%94%81\" tabindex=\"-1\">MySQL锁</h1>\n<h2 id=\"%E8%A1%A8%E7%BA%A7%E9%94%81%E5%92%8C%E8%A1%8C%E7%BA%A7%E9%94%81\" tabindex=\"-1\">表级锁和行级锁</h2>\n<ul>\n<li><strong>表级锁</strong>:锁定粒度最大的锁,针对非索引字段加锁,对整张表枷锁,实现简单,资源消耗少,枷锁快,不会出现死锁。</li>\n<li><strong>行级锁</strong>:锁定粒度最小的锁,针对索引字段加锁,对操作行加锁。加锁慢,可能出现死锁。</li>\n</ul>\n<h2 id=\"%E8%A1%8C%E7%BA%A7%E9%94%81%E4%BD%BF%E7%94%A8\" tabindex=\"-1\">行级锁使用</h2>\n<p>InnoDB使用行级锁针对索引字段加锁。</p>\n<p>当执行<code>update</code>,<code>delete</code>方法时,如果<code>where</code>条件字段没有命中唯一索引,或者索引失效时,会导致扫描全表并对全表行加锁。</p>\n<h2 id=\"%E5%B8%B8%E8%A7%81%E9%94%81%E7%9A%84%E7%B1%BB%E5%9E%8B\" tabindex=\"-1\">常见锁🔒的类型</h2>\n<ul>\n<li>\n<p><strong>共享锁</strong>(S锁):又称<strong>读锁</strong>,事务在读取数据(select)时取得共享锁,允许多个事务同时获取(锁兼容)。</p>\n</li>\n<li>\n<p><strong>排他锁</strong>(X锁):又称<strong>写锁</strong>、<strong>独占锁</strong>,事务在修改记录(update)的时候获得排他锁,不允许多个事务同时获取。如果一个记录已经被加了拍他锁,则其他事务不能在加其它类型的锁(锁不兼容)。</p>\n<p>默认不加锁,可以显示声明使用锁</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-sql\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">SELECT</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ... LOCK </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">IN</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> SHARE MODE; # 共享锁</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">SELECT</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ... </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">FOR</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> UPDATE</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">; # 排他锁</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"SELECT ... LOCK IN SHARE MODE; # 共享锁\nSELECT ... FOR UPDATE; # 排他锁\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n</li>\n<li>\n<p><strong>意向锁</strong>:表级锁,用于快速判断表中有没有行锁。</p>\n<ul>\n<li><strong>意向共享锁</strong>:如果事务有意向对表中数据加共享锁,必须先加意向共享锁。</li>\n<li><strong>意向排他锁</strong>:如果事务有意向丢表中数据加排他锁,必须先加意向排他锁。</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"innodb%E4%B8%AD%E7%9A%84%E9%94%81\" tabindex=\"-1\">InnoDB中的锁</h2>\n<p>InnoDB有三种行锁:</p>\n<ul>\n<li><strong>记录锁(Record Lock)</strong>:单个行记录上的锁。</li>\n<li><strong>间隙锁(Gap Lock)</strong>:锁定一个范围,不包含记录本身。</li>\n<li><strong>临键锁(Next-Key Lock)</strong>:同时使用记录锁和临键锁。</li>\n</ul>\n<h2 id=\"%E5%BD%93%E5%89%8D%E8%AF%BB%E5%92%8C%E5%BF%AB%E7%85%A7%E8%AF%BB%EF%BC%88%EF%BC%89\" tabindex=\"-1\">当前读和快照读()</h2>\n<p>InnoDB默认隔离级别(可重读)可以解决幻读问题,通过当前读和快照读。</p>\n<ul>\n<li><strong>当前读</strong>(一致性锁定读):使用临键锁(Next-Key Lock)进行加锁保证不出现幻读。</li>\n<li><strong>快照读</strong>(一致性非锁定读):有MVCC机制保障不出现幻读。</li>\n</ul>\n<p><em>两者的区别</em></p>\n<p><strong>快照读</strong>:即正常使用<code>select</code>时,使用快照读。如果读取到的数据正在执行<code>update/delete</code>操作,读取操作不会等待记录上的<strong>排他锁</strong>释放,而是会读取行的上一个快照。</p>\n<p><strong>当前读</strong>:当在事务隔离级别RC(读已提交)和RR(可重读)下,InnoDB会使用锁定读。</p>\n<ul>\n<li>在RC级别下:对于快照数据,当前读会读取被锁定行的最新一份快照数据。</li>\n<li>在RR级别下:对于快照数据,当前读会读取本事务开始时的行数据版本。</li>\n</ul>\n<p><strong>快照</strong>即记录的历史版本,每行记录可能存在多个历史版本。</p>\n<h1 id=\"mysql%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96\" tabindex=\"-1\">MySQL性能优化</h1>\n<h2 id=\"%E6%96%87%E4%BB%B6%E5%AD%98%E5%82%A8\" tabindex=\"-1\">文件存储</h2>\n<p>不建议使用MySQL存储二进制文件数据。</p>\n<p>建议使用对象存储保存文件,MySQL保存文件地址。</p>\n<h2 id=\"ip%E5%9C%B0%E5%9D%80%E5%AD%98%E5%82%A8\" tabindex=\"-1\">IP地址存储</h2>\n<p>可以将IP地址转换成整形存储。</p>\n<ul>\n<li><code>INET_ATON()</code> :把 ip 转为无符号整型 (4-8 位)</li>\n<li><code>INET_NTOA()</code> :把整型的 ip 转为地址</li>\n</ul>\n<h2 id=\"%E5%B0%BD%E5%8F%AF%E8%83%BD%E5%B0%86%E5%88%97%E5%AE%9A%E4%B9%89%E4%B8%BA-not-null\" tabindex=\"-1\">尽可能将列定义为 NOT NULL</h2>\n<p>除非有特别的原因使用 NULL 值,应该总是让字段保持 NOT NULL。</p>\n<ul>\n<li>索引 NULL 列需要额外的空间来保存,所以要占用更多的空间;</li>\n<li>进行比较和计算时要对 NULL 值做特别的处理。</li>\n</ul>\n<h1 id=\"mysql%E7%B4%A2%E5%BC%95\" tabindex=\"-1\">MySQL索引</h1>\n<h2 id=\"%E4%BB%80%E4%B9%88%E6%98%AF%E7%B4%A2%E5%BC%95\" tabindex=\"-1\">什么是索引</h2>\n<p>索引是一种用于快速查找和检索数据的数据结构,常见索引结构有:B树、B+树、Hash表等。</p>\n<h2 id=\"%E7%B4%A2%E5%BC%95%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84\" tabindex=\"-1\">索引的数据结构</h2>\n<h3 id=\"hash%E8%A1%A8\" tabindex=\"-1\">Hash表</h3>\n<p>哈希表时键值对的集合,通过key可以快速得出value。O(1)。通过对key使用哈希算法计算索引,在通过索引找到value。</p>\n<p>缺点:</p>\n<ol>\n<li>Hash冲突</li>\n<li>Hash索引不支持顺序和范围查询</li>\n</ol>\n<h3 id=\"b%E6%A0%91\" tabindex=\"-1\">B树</h3>\n<blockquote>\n<p><a href=\"https://beyondhorizon.top/article/xclfxsXC\">二叉搜索树,平衡二叉树,红黑树🔗</a></p>\n</blockquote>\n<blockquote>\n<p><a href=\"https://www.codedump.info/post/20200609-btree-1/\">B树 推荐阅读🔗</a></p>\n</blockquote>\n<p>B树的详细解释以及插入删除操作等相关内容上文有详细说明。</p>\n<p>个人对于B树的理解:普通二叉树的缺点,每个节点只能有两个子节点,每个节点只能容纳一个数据,这导致了两个问题:1. 树的高度很高;2. 逻辑上挨着的节点数据可能树里离的很远,这对于内存中操作数据来说问题不大。</p>\n<p>但是在数据库里,数据首先会存储于磁盘上而不是内存上。过高的树需要多次查找,取出结果,比较,再查找,比较,树的高度越高,需要访问磁盘的次数也越多。对于磁盘来说并不是很好的选择。如果满足“局部性原理”,即逻辑上相邻的数据,物理上尽量存储在一起。这样可以减少磁盘访问次数。</p>\n<p>B树解决了这一问题,B树的特点:1. 多路树,不再局限于一个节点只能有两个子节点;2. 所有子节点的高度相同。</p>\n<p>B树每个节点能容纳更多的数据,这样降低了树的高度,同时逻辑上相邻的数据在物理上存储在相邻的磁盘空间中。在查询时减少磁盘交互次数。</p>\n<p>B树:</p>\n<figure><img src=\"https://typora-1308549476.cos.ap-nanjing.myqcloud.com/img/image-20220921213418932.png\" alt=\"image-20220921213418932\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<p>在上图中,叶子节点有多个数据,查找是会将叶子节点上的数据一次读入内存中,通过在内存中遍历比较,找到需要的数据。</p>\n<p>B树每个节点能保存4K的数据,由于磁盘存储数据采用分块的方式,而每个块的大小为4K。每次读取数据都会读取一个节点,4K的数据到内存中。</p>\n<h3 id=\"b%2B%E6%A0%91\" tabindex=\"-1\">B+树</h3>\n<p>B+树子节点不保存数据,只保存关键字的索引,所有的数据都保存在叶子节点上。同时所有叶子节点上的数据构成了一个有序链表。</p>\n<figure><img src=\"https://typora-1308549476.cos.ap-nanjing.myqcloud.com/img/image-20220921214432723.png\" alt=\"image-20220921214432723\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<h3 id=\"b%2B%E6%A0%91%E5%92%8Cb%E6%A0%91%E6%AF%94%E8%BE%83\" tabindex=\"-1\">B+树和B树比较</h3>\n<ol>\n<li>B+树查询速度更稳定。B+树所有数据都存放在叶子节点,而叶子节点高度相同,每次查找次数相同,所以查询速度稳定。</li>\n<li>B+树叶子节点有序。B+树所有叶子节点数据构成一个有序链表,查询大小区间的数据时更快。</li>\n<li>B+树全节点遍历更快。B+树只需要遍历叶子节点,B树需要遍历全部节点。</li>\n<li>B树如果访问的数据离根节点近,此时查找速度快于B+树。</li>\n</ol>\n<h2 id=\"myisam%E5%92%8Cinnodb%E7%B4%A2%E5%BC%95\" tabindex=\"-1\">MyISAM和InnoDB索引</h2>\n<p>两者都是用B+树作为索引结构</p>\n<ul>\n<li>\n<p><strong>MyISAM使用非聚簇索引</strong>:B+树节点data域中保存数据的地址,在查找时,先找到节点,再通过节点里的地址找到数据。</p>\n</li>\n<li>\n<p><strong>InnoDB使用聚簇索引</strong>:B+树节点data域中保存完整数据,索引的key是数据库主键。</p>\n</li>\n</ul>\n<h2 id=\"%E7%B4%A2%E5%BC%95%E7%B1%BB%E5%9E%8B\" tabindex=\"-1\">索引类型</h2>\n<h3 id=\"%E4%B8%BB%E9%94%AE%E7%B4%A2%E5%BC%95\" tabindex=\"-1\">主键索引</h3>\n<p>数据表的主键列使用的是主键索引。</p>\n<p>如果一张表没有设置主键,InnoDB会先查找表中是否有唯一且不允许为空的字段,如果有则使用该字段为主键,如果没有InnoDB会自己创建一个6Byte的自增主键。</p>\n<h3 id=\"%E4%BA%8C%E7%BA%A7%E7%B4%A2%E5%BC%95%EF%BC%88%E8%BE%85%E5%8A%A9%E7%B4%A2%E5%BC%95%EF%BC%89\" tabindex=\"-1\">二级索引(辅助索引)</h3>\n<p>二级索引的叶子节点保存的数据时主键,通过二级索引可以找到主键。</p>\n<p>二级索引包含唯一索引、普通索引、前缀索引、全文索引</p>\n<ul>\n<li><strong>唯一索引</strong>(UNIQUE):数据表中设置了唯一的字段,不允许重复,允许为null</li>\n<li><strong>普通索引</strong>(INDEX):数据表中手动设置的索引字段,可以重复,可以为null</li>\n<li><strong>前缀索引</strong>:对于字符串类型的数据,截取字符串前几个字符创建索引。</li>\n<li><strong>全文索引</strong>(FULLTEXT):检索大文本数据中的关键字信息。</li>\n</ul>\n<h2 id=\"%E8%81%9A%E9%9B%86%E7%B4%A2%E5%BC%95%E5%92%8C%E9%9D%9E%E8%81%9A%E9%9B%86%E7%B4%A2%E5%BC%95\" tabindex=\"-1\">聚集索引和非聚集索引</h2>\n<h3 id=\"%E8%81%9A%E9%9B%86%E7%B4%A2%E5%BC%95\" tabindex=\"-1\">聚集索引</h3>\n<p>聚集索引即索引结构和数据存放在一次的索引。主键索引就是聚集索引。特点:查询快,修改慢。</p>\n<ul>\n<li><strong>优点</strong>:查询速度快,因为叶子节点存放数据并且数据有序,所以查到叶子节点就是查到数据</li>\n<li><strong>缺点</strong>:\n<ul>\n<li>依赖于有序的数据:查询依赖于数据的物理存储地址按照索引的顺序排列。</li>\n<li>更新代价大:由于数据的物理存储地址按照索引的顺序排列,所以每次插入删除都需要移动数据,使数据在物理上有序,连续。</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"%E9%9D%9E%E8%81%9A%E9%9B%86%E7%B4%A2%E5%BC%95\" tabindex=\"-1\">非聚集索引</h3>\n<p>索引结构和数据分开存放。二级索引是非聚集索引。二级索引的叶子节点就存放的是主键,根据主键再回表查数据。</p>\n<ul>\n<li><strong>优点</strong>:更新快,叶子节点不存放数据。</li>\n<li><strong>缺点</strong>:\n<ul>\n<li>依赖于有序的数据。</li>\n<li>可能需要回表二次查询。</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"%E8%A6%86%E7%9B%96%E7%B4%A2%E5%BC%95\" tabindex=\"-1\">覆盖索引</h2>\n<p>覆盖索引即需要<em><strong>查询的字段正好是索引的字段</strong></em>,那么直接根据该索引,就可以查到数据了,而无需回表查询。</p>\n<h2 id=\"%E8%81%94%E5%90%88%E7%B4%A2%E5%BC%95\" tabindex=\"-1\">联合索引</h2>\n<p>使用表中多个字段创建索引</p>\n<h2 id=\"%E6%9C%80%E5%B7%A6%E5%89%8D%E7%BC%80%E5%8C%B9%E9%85%8D%E5%8E%9F%E5%88%99\" tabindex=\"-1\">最左前缀匹配原则</h2>\n<p>使用联合索引是,根据联合索引中字段的顺序,从左到右依次匹配查询条件中与联合索引中最左字段匹配的字段。</p>\n<h2 id=\"%E7%B4%A2%E5%BC%95%E5%AD%97%E6%AE%B5%E5%88%9B%E5%BB%BA%E5%8E%9F%E5%88%99\" tabindex=\"-1\">索引字段创建原则</h2>\n<ol>\n<li>需要频繁查询、作查询条件、关联查询的字段</li>\n<li>不为null的字段</li>\n<li>需要频繁排序的字段</li>\n<li>不会频繁更新的字段</li>\n<li>尽量使用联合索引而不是单列索引</li>\n</ol>\n<h1 id=\"mysql%E6%97%A5%E5%BF%97\" tabindex=\"-1\">MySQL日志</h1>\n<p>MySQL日志主要由二进制日志(binlog,归档日志),事务日志(redo log)、回滚日志(undo log)组成</p>\n<h2 id=\"redo-log\" tabindex=\"-1\">redo log</h2>\n<p>Redo log是InnoDB所使用的日志系统,记录在每个数据页上做的修改,通过redo log可以用于从错误中恢复数据。保证数据的持久性和完整性。如果MySQL服务异常停机,重启MySQL之后会通过redo log恢复数据。</p>\n<p>MySQL数据查询时,从磁盘读取数据以页为单位,查询时会一次性加载一页数据(16kb)<code>Buffer Pool</code>中。后续查询会优先在<code>Buffer Pool</code>中查找。在执行更新操作时,也是有限更新<code>Buffer Pool</code>中的数据,同时记录重做日志缓存(redo log buffer),之后在适当的时机,将缓存刷盘到redo log文件中。</p>\n<h3 id=\"%E5%88%B7%E7%9B%98%E6%97%B6%E6%9C%BA\" tabindex=\"-1\">刷盘时机</h3>\n<p>刷盘:将数据从内存写入磁盘</p>\n<ol>\n<li>使用<code>innodb_flush_log_at_trx_commit</code>参数可以控制刷盘时机:\n<ul>\n<li>0:每次事务提交时不进行刷盘操作(数据丢失分险)</li>\n<li>1:每次事务提交都进行刷盘(默认值)(不会有数据丢失,因为丢失的都是未提交的事务)</li>\n<li>2:每次事务提交都把<code>redo log buffer</code>内容写入系统缓存<code>page cache</code>\n在默认情况下,每当事务提交时都会调用<code>fsunc</code>对redo log进行刷盘</li>\n</ul>\n</li>\n<li>同时,InnoDB每隔 1 s,会自动将<code>redo log buffer</code>内容写入系统缓存<code>page cache</code>,之后调用<code>fsunc</code>刷盘。</li>\n<li>当<code>redo log buffer</code>占用的空间超过<code>innodb_log_buffer_size</code>一半时,触发刷盘。</li>\n</ol>\n<h3 id=\"%E6%97%A5%E5%BF%97%E6%96%87%E4%BB%B6%E7%BB%84\" tabindex=\"-1\">日志文件组</h3>\n<p>多个文件存储redo log日志,一个文件写满写写一个,最后一个写满再回头写第一个。</p>\n<h2 id=\"binlog\" tabindex=\"-1\">binlog</h2>\n<p>binlog记录数据库操作逻辑,记录每次数据表更新。</p>\n<p>MySQL主从同步时,会使用binlog来同步数据。</p>\n<h3 id=\"%E8%AE%B0%E5%BD%95%E6%A0%BC%E5%BC%8F\" tabindex=\"-1\">记录格式</h3>\n<p>通过<code>binlog_format</code>参数指定记录格式</p>\n<ul>\n<li><strong>statement</strong>:记录SQL语句原文,但是在执行<code>update_time=now()</code>会导致时间不同。</li>\n<li><strong>row</strong>:记录执行SQL的参数,记录具体时间</li>\n<li><strong>mixed</strong>:自动判断该SQL是否会有数据不一致问题,如果有使用row,没有使用statement记录</li>\n</ul>\n<h3 id=\"%E5%86%99%E5%85%A5%E6%9C%BA%E5%88%B6\" tabindex=\"-1\">写入机制</h3>\n<p>事务执行过程中,现将日志写到<code>binlog cache</code>,事务提交之后,在将<code>binlog cache</code>写入binlog。</p>\n<h2 id=\"%E4%B8%A4%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4\" tabindex=\"-1\">两阶段提交</h2>\n<p>通过redo log和binlog互相配合来尽量保证数据恢复能力,和数据不丢失。</p>\n<p>日志记录顺序。</p>\n<figure><img src=\"https://typora-1308549476.cos.ap-nanjing.myqcloud.com/img/image-20220922183611449.png\" alt=\"image-20220922183611449\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<p>执行更新操作时先写入redo log,并将状态设置为prepare,事务提交后,将更新的操作写入binlog,在将redo log设置为commit阶段。</p>\n<p>如果在redo log状态为prepare阶段时,MySQL服务异常,在恢复数据时由于事务没有提交,没有binlog,MySQL会选择回滚 这一事务。</p>\n<p>如果在事务提交,并且有binlog时,MySQL会选择通过binlog恢复数据,并且将redo log状态设置为commit阶段。</p>\n<h2 id=\"undo-log\" tabindex=\"-1\">undo log</h2>\n<p>undo log保证事务的原子性,用于在事务异常时回滚操作。</p>\n<p>所有的事务操作都会先记录回滚日志,在实际执行操作。同时,回滚日志先于数据持久化到磁盘上。</p>\n<h2 id=\"%E4%B8%89%E7%A7%8D%E6%97%A5%E5%BF%97%E7%9A%84%E4%BD%9C%E7%94%A8\" tabindex=\"-1\">三种日志的作用</h2>\n<ul>\n<li>使用redo log保证事务的持久性</li>\n<li>使用undo log保证事务的原子性</li>\n<li>使用redo log和undo log 保证数据不丢失</li>\n<li>使用binlog完整数据备份,主从,保证数据的一致性</li>\n</ul>\n<h1 id=\"mvcc\" tabindex=\"-1\">MVCC</h1>\n<h2 id=\"mvcc-1\" tabindex=\"-1\">MVCC</h2>\n<p>Multi-Version Concurrency Control,多版本并发控制。是一种并发控制的方法,在数据库管理系统中,实现对数据库的并发访问。</p>\n<h2 id=\"%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86\" tabindex=\"-1\">实现原理</h2>\n<h3 id=\"%E9%9A%90%E5%BC%8F%E5%AD%97%E6%AE%B5\" tabindex=\"-1\">隐式字段</h3>\n<ul>\n<li>DB_ROW_ID:隐式自增主键,如果数据表没有主见,InnoDB自动以DB_ROW_ID等字段生成聚集索引</li>\n<li>DB_TRX_ID:最近插入/修改的事务ID,记录当前记录最后一次修改该记录的事务ID</li>\n<li>DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本</li>\n<li>DRFAULT_BIT:删除flag</li>\n</ul>\n<h3 id=\"undo-log-1\" tabindex=\"-1\">undo log</h3>\n<h3 id=\"readview\" tabindex=\"-1\">ReadView</h3>\n<blockquote>\n<p>事务在进行快照操作时生成的读视图,在该事务执行快照的时候,会生成数据库系统当前的快照,记录并维护系统当前活跃事务的ID</p>\n</blockquote>\n<p>ReadView的三个属性</p>\n<ul>\n<li>trx_list:未提交事务ID列表</li>\n<li>up_limit_id:记录trx_list列表中最小的事务ID</li>\n<li>low_limit_id:下一个事务ID,就是当前最大ID + 1</li>\n</ul>\n<h1 id=\"sql%E6%89%A7%E8%A1%8C%E6%B5%81%E7%A8%8B\" tabindex=\"-1\">SQL执行流程</h1>\n<ul>\n<li>连接器:数据库连接,身份认证,权限校验</li>\n<li>分析器:词法分析(提取关键词,select、表命、查询条件等)、语法分析(检查SQL是否符合MySQL规范)</li>\n<li>优化器:使用(IO成本 + CPU成本)最小的索引来执行查询</li>\n<li>执行器:调用存储引擎接口执行SQL\n<ul>\n<li>查询BufferPool中是否有需要查询的数据,如果没有去磁盘查询,之后将数据放入BufferPool</li>\n<li>if执行的是update,记录undo log,在BufferPool中udate数据。(BufferPool中的数据又可能和数据库中的数据不一致)</li>\n<li>BufferPool中的数据已更新,记录redo log(先写入到redo log buffer中,再在合适时间写入磁盘中。)</li>\n<li>记录bin log</li>\n<li>将bin log文件名和当前语句更新内容记录到redo log</li>\n<li>redo log后添加commit(两阶段提交)</li>\n</ul>\n</li>\n</ul>\n<h1 id=\"%E7%B4%A2%E5%BC%95%E5%A4%B1%E6%95%88\" tabindex=\"-1\">索引失效</h1>\n<blockquote>\n<p>操作符( = ) 左右两边的数据类型不同时,会发生隐式转换。</p>\n</blockquote>\n<h2 id=\"%E5%A4%B1%E6%95%88%E7%9A%84%E6%83%85%E5%86%B5\" tabindex=\"-1\">失效的情况</h2>\n<ul>\n<li>当where左边为数值类型时会发生隐式转换,索引不会失效,对效率影响不大。</li>\n<li>当where左边为字符类型时会发生隐式转换,索引会失效,查询变成全表扫描,效率低。</li>\n</ul>\n<h2 id=\"%E5%AD%97%E7%AC%A6%E4%B8%B2-%3D%3E-%E6%95%B0%E5%80%BC%E8%BD%AC%E6%8D%A2%E6%96%B9%E5%BC%8F%EF%BC%9A\" tabindex=\"-1\">字符串 =&gt; 数值转换方式:</h2>\n<ul>\n<li>所有不以数字开头的字符串都转换为0。(例如<code>abc</code>,abc123 =&gt; <code>0</code>)</li>\n<li>以数字开头的字符只截取读一个数字段。(例如<code>123abc4</code> =&gt; 123,<code>012ab4</code> =&gt; 12)</li>\n</ul>\n<h2 id=\"%E5%A4%B1%E6%95%88%E6%A1%88%E4%BE%8B\" tabindex=\"-1\">失效案例</h2>\n<p>索引失效案例:num2为<code>varchar</code>类型</p>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-sql\"><span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">SELECT</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> *</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> FROM</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> `test1`</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> WHERE</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> num2 </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 10000</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">;</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"SELECT * FROM `test1` WHERE num2 = 10000;\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<p>执行这条SQL时索引失效,发生全表扫描,因为<code>'10000a'</code>,<code>'010000'</code>,<code>'10000'</code>等等都能转为浮点数<code>10000</code>,这样的情况下,是不能用到索引的</p>\n<h1 id=\"%E7%B4%A2%E5%BC%95%E5%A4%B1%E6%95%88-1\" tabindex=\"-1\">索引失效</h1>\n<ol>\n<li>上述例子中,由于类型转换导致索引失效</li>\n<li>使用!= &gt; &lt; 导致索引失效</li>\n<li>模糊查询,如%S%,会导致索引失效,S%不会导致索引失效</li>\n</ol>\n<h1 id=\"mysql%E4%B8%AD%E8%AF%AD%E5%8F%A5%E6%89%A7%E8%A1%8C%E4%BC%98%E5%85%88%E7%BA%A7\" tabindex=\"-1\">MySQL中语句执行优先级</h1>\n<h2 id=\"%E5%8D%95%E8%A1%A8\" tabindex=\"-1\">单表</h2>\n<p>form &gt; where &gt; group by &gt; select &gt; order by &gt; limit</p>\n<h2 id=\"%E5%A4%9A%E8%A1%A8\" tabindex=\"-1\">多表</h2>\n<p>from &gt; join &gt; on &gt; where &gt; group by &gt; AVG,SUM &gt; having &gt; select &gt; distinct &gt; order by &gt; limit</p>\n<h1 id=\"%E6%85%A2%E6%9F%A5%E8%AF%A2%E4%BC%98%E5%8C%96\" tabindex=\"-1\">慢查询优化</h1>\n<p>使用EXPLINE关键字分析查询语句</p>\n<h2 id=\"%E6%9F%A5%E8%AF%A2%E4%BD%BF%E7%94%A8%E7%B4%A2%E5%BC%95\" tabindex=\"-1\">查询使用索引</h2>\n<ul>\n<li>使用LIKE 模糊查询时,第一个时%查询不走索引</li>\n</ul>\n<h2 id=\"%E4%BC%98%E5%8C%96%E6%95%B0%E6%8D%AE%E5%BA%93%E7%BB%93%E6%9E%84\" tabindex=\"-1\">优化数据库结构</h2>\n<p>将字段较多的表拆分,将不经常查询的数据新建表</p>\n"},{"_id":"65ca3152912f6564d5af0890","shortLink":"redis-common","title":"Redis","description":"Redis中数据类型、数据结构。","cover":"https://static.vio.vin/blog/2024/02/7daee46716cd11938f5d8772f499e0de.png","category":"article","tags":["redis"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-11-26T14:08:59.988Z","updatedAt":"2024-02-27T03:26:21.211Z","status":"PUBLISHED","views":63,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/dee2932061a138ac05dd4e32b5a1c3e09ee348f94f273939a1f211932a69a6e8.png","html":"<h1 id=\"%E7%AE%80%E4%BB%8B\" tabindex=\"-1\">简介</h1>\n<h2 id=\"%E4%BB%80%E4%B9%88%E6%98%AFredis\" tabindex=\"-1\">什么是Redis</h2>\n<p>Redis是内存高速缓存数据库。全称为:Remote Dictionary Server(远程数据服务)。</p>\n<p>Redis由c语言编写,key-value存储系统,支持string、list、set、zset、hash物种数据类型。</p>\n<p>Redis可用于缓存、事件发布或订阅、高速队列等场景。基于内存,可持久化。</p>\n<h2 id=\"redis%E7%9A%84%E4%BC%98%E5%8A%BF\" tabindex=\"-1\">Redis的优势</h2>\n<ul>\n<li>读写性能优异</li>\n<li>丰富的数据类型</li>\n<li>原子性</li>\n<li>丰富的特性(发布订阅、通知、过期)</li>\n<li>支持持久化(RDB和AOF方式持久化)</li>\n<li>分布式</li>\n</ul>\n<h2 id=\"redis%E5%8F%AF%E4%BB%A5%E5%81%9A%E4%BB%80%E4%B9%88\" tabindex=\"-1\">Redis可以做什么</h2>\n<ul>\n<li>数据缓存</li>\n<li>限时业务</li>\n<li>计数器(incrby)</li>\n<li>分布式锁(基于Redisson实现分布式锁)</li>\n<li>限流(使用Redis中的List作为消息队列)</li>\n<li>消息队列</li>\n</ul>\n<h1 id=\"%E5%AE%89%E8%A3%85%2F%E5%90%AF%E5%8A%A8\" tabindex=\"-1\">安装/启动</h1>\n<h2 id=\"%E5%90%AF%E5%8A%A8\" tabindex=\"-1\">启动</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 在前台启动</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">redis-server</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 在后台启动</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">brew</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> services</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> start</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> redis</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"># 关闭</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">brew</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> services</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> stop</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> redis</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"# 在前台启动\nredis-server\n# 在后台启动\nbrew services start redis\n# 关闭\nbrew services stop redis\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"%E8%BF%9E%E6%8E%A5\" tabindex=\"-1\">连接</h2>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">redis-cli</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"redis-cli\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<blockquote>\n<p>默认6379端口</p>\n<p>redis默认有16个数据库,0-15</p>\n<p>使用<code>select 1</code>来切换</p>\n</blockquote>\n<h1 id=\"%E5%9F%BA%E7%A1%80%E5%91%BD%E4%BB%A4\" tabindex=\"-1\">基础命令</h1>\n<ul>\n<li><code>keys *</code>查看当前数据库中有哪些key(有16个数据库)</li>\n<li><code>exists key</code>判断这个key是否存在</li>\n<li><code>type key</code>查看这个key的类型</li>\n<li><code>del key</code>或<code>unlink key</code>删除某个key\n<ul>\n<li><code>unlink</code>异步删除</li>\n</ul>\n</li>\n<li><code>expire key 10</code>设置key过期时间 秒</li>\n<li><code>ttl key</code>查看key多少秒过期 -1永不过期 -2已经过期</li>\n<li><code>select</code>切换数据库</li>\n<li><code>dbsize</code>查看当前数据库中key数量</li>\n<li><code>flushdb</code>清除当前数据库所有key</li>\n</ul>\n<h1 id=\"%E5%9F%BA%E7%A1%80%E7%B1%BB%E5%9E%8B%EF%BC%885%E7%A7%8D%EF%BC%89\" tabindex=\"-1\">基础类型(5种)</h1>\n<h2 id=\"string%EF%BC%88%E5%AD%97%E7%AC%A6%E4%B8%B2%EF%BC%89\" tabindex=\"-1\">string(字符串)</h2>\n<blockquote>\n<ul>\n<li>string类型是二进制安全的,可以包含任何数据</li>\n<li>string是redis的基本数据类型,一个value最大512Mb</li>\n</ul>\n</blockquote>\n<h3 id=\"%E5%91%BD%E4%BB%A4\" tabindex=\"-1\">命令</h3>\n<ul>\n<li><code>set &lt;key&gt; &lt;value&gt;</code></li>\n<li><code>get &lt;key&gt;</code>查看</li>\n<li><code>append &lt;key&gt; &lt;value&gt;</code>在key后追加value\n<ul>\n<li>如果这个key不存在,则会创建</li>\n</ul>\n</li>\n<li><code>strlen &lt;key&gt;</code>获取这个key对应value长度</li>\n<li><code>setnx &lt;key&gt; &lt;value&gt;</code>只有当key不存在是创建</li>\n<li><code>incr &lt;key&gt;</code>这个key的value+1</li>\n<li><code>decr &lt;key&gt;</code>value-1</li>\n<li><code>incrby/decrby &lt;key&gt; &lt;num&gt;</code>key的value加num或者减num</li>\n</ul>\n<p>这些操作是原子性操作,在执行操作期间不会别别的线程打断,因为redis是单线程</p>\n<ul>\n<li><code>mset &lt;key&gt; &lt;value&gt; &lt;key&gt; &lt;value&gt; &lt;key&gt; &lt;value&gt;</code>一次设置多个ky</li>\n<li><code>mget &lt;key&gt; &lt;key&gt; &lt;key&gt;</code>一次获取多个key</li>\n<li><code>msetnx &lt;key&gt; &lt;value&gt; &lt;key&gt; &lt;value&gt;</code>一次设置多个 当key不存在时候\n<ul>\n<li>原子性操作 一个失败全部失败</li>\n</ul>\n</li>\n<li><code>getrange &lt;key&gt; &lt;开始&gt; &lt;结束&gt;</code>获取key中第&lt;开始&gt;&lt;结束&gt;中间的所有value</li>\n<li><code>setrange &lt;key&gt; &lt;offset&gt; &lt;value&gt;</code>在key中第offset之后覆盖设置value</li>\n<li><code>setex &lt;key&gt; &lt;过期时间&gt; &lt;value&gt;</code>在设置key时设置过期时间</li>\n<li><code>get set &lt;key&gt; &lt;value&gt;</code>取之前的,取完之后再设置新的</li>\n</ul>\n<h3 id=\"%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84\" tabindex=\"-1\">数据结构</h3>\n<p>Arraylist</p>\n<h3 id=\"%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF\" tabindex=\"-1\">使用场景</h3>\n<ol>\n<li>缓存:使用Redis作为MySQL缓存,降低MySQL读写压力</li>\n<li>计数器:Redis是单线程的优势</li>\n<li>session:spring session + redis实现session共享</li>\n</ol>\n<h2 id=\"list%EF%BC%88%E5%88%97%E8%A1%A8%EF%BC%89\" tabindex=\"-1\">list(列表)</h2>\n<blockquote>\n<p>单键多值,底层双向链表</p>\n</blockquote>\n<h3 id=\"%E5%91%BD%E4%BB%A4-1\" tabindex=\"-1\">命令</h3>\n<ul>\n<li><code>lpush/rpush &lt;key&gt; &lt;v1&gt; &lt;v2&gt; &lt;v3&gt;</code>从双向链表左右两边push值</li>\n<li><code>Large &lt;key&gt; 0 -1</code>编列链表,获取所有</li>\n<li><code>rpop/lpop &lt;key&gt;</code>从左右获取并删除值</li>\n<li><code>rpoplpush &lt;k1&gt; &lt;k2&gt;</code>从k1右边pop一个值,在push到k2左边</li>\n<li><code>lindex &lt;key&gt; idnex</code>获取第index个值</li>\n<li><code>llen &lt;k&gt;</code>获取长度</li>\n<li><code>linsert before/after &lt;v1&gt; &lt;v2&gt;</code>在v1前/后插入v2</li>\n<li><code>lrem &lt;key&gt; &lt;n&gt; &lt;v&gt;</code>从做百年删除n个value</li>\n<li><code>lset &lt;k&gt; &lt;idnex&gt; &lt;v&gt;</code>将index设置成v</li>\n</ul>\n<h3 id=\"%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-1\" tabindex=\"-1\">数据结构</h3>\n<p>元素较少的情况下是ziplist,元素多了之后会将多个ziplist组成一个quicklist</p>\n<h3 id=\"%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF-1\" tabindex=\"-1\">使用场景</h3>\n<ol>\n<li>消息队列</li>\n</ol>\n<h2 id=\"set%EF%BC%88%E9%9B%86%E5%90%88%EF%BC%89\" tabindex=\"-1\">set(集合)</h2>\n<blockquote>\n<p>set集合中的元素不能重复,底层hash表,增删改查都是O(1)复杂度</p>\n</blockquote>\n<h3 id=\"%E5%91%BD%E4%BB%A4-2\" tabindex=\"-1\">命令</h3>\n<ul>\n<li><code>sadd &lt;k&gt; &lt;v1&gt; &lt;v2&gt;</code>添加</li>\n<li><code>smamber &lt;k&gt;</code>取出该集合中所有值</li>\n<li><code>sismamber &lt;k&gt; &lt;v&gt;</code>判断是否存在这个value</li>\n<li><code>scard &lt;k&gt;</code>返回这个集合长度</li>\n<li><code>srem &lt;k&gt; &lt;v&gt; &lt;v&gt;</code>删除</li>\n<li><code>spop &lt;k&gt;</code>随机取出并删除一个</li>\n<li><code>srandmameber &lt;k&gt; &lt;n&gt;</code>随机取出n个,不删除</li>\n<li><code>smove &lt;k1&gt; &lt;k2&gt; &lt;v&gt;</code>把k1中的value取出来,放到k2中</li>\n<li><code>sinter &lt;k1&gt; &lt;k2&gt;</code>返回 交集</li>\n<li><code>sunion &lt;k1&gt; &lt;k2&gt;</code> 返回 并集</li>\n<li><code>sdiff &lt;k1&gt; &lt;k2&gt;</code>返回差集</li>\n</ul>\n<h3 id=\"%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF-2\" tabindex=\"-1\">使用场景</h3>\n<ol>\n<li>点赞、转发、收藏等</li>\n</ol>\n<h2 id=\"hash%EF%BC%88%E6%95%A3%E5%88%97%EF%BC%89\" tabindex=\"-1\">hash(散列)</h2>\n<blockquote>\n<p>类似于java中的<code>map&lt;string,object&gt;</code>,key是对象名,value里边是fild和value</p>\n</blockquote>\n<h3 id=\"%E5%91%BD%E4%BB%A4-3\" tabindex=\"-1\">命令</h3>\n<ul>\n<li><code>hset &lt;k&gt; &lt;field&gt; &lt;value&gt;</code>设置key 和key中的field和value</li>\n<li><code>hget &lt;k&gt; &lt;field&gt;</code> 获取k中field中的value</li>\n<li><code>hmset &lt;k&gt; &lt;field1&gt; &lt;v1&gt; &lt;field2&gt; &lt;v2&gt;</code>一次设置多个</li>\n<li><code>hexists &lt;k1&gt; &lt;field&gt;</code>查看key中的filed是否存在</li>\n<li><code>hkeys &lt;key&gt;</code>获取该key的所有field</li>\n<li><code>havals &lt;key&gt;</code>获取该key的所有vlaue,没有field</li>\n<li><code>hincrby &lt;k&gt; &lt;f&gt; &lt;n&gt;</code>给f的value加n</li>\n<li><code>hsetnx &lt;k&gt; &lt;f&gt; &lt;v&gt;</code>filed不存在则设置value</li>\n</ul>\n<h3 id=\"%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-2\" tabindex=\"-1\">数据结构</h3>\n<p>当field-value长度短且个数少时使用ziplist,否则使用hashtable</p>\n<h3 id=\"%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF-3\" tabindex=\"-1\">使用场景</h3>\n<ol>\n<li>缓存</li>\n</ol>\n<h2 id=\"zset%EF%BC%88%E6%9C%89%E5%BA%8F%E9%9B%86%E5%90%88%EF%BC%89\" tabindex=\"-1\">Zset(有序集合)</h2>\n<blockquote>\n<p>有序集合</p>\n<p>每个元素都有评分(score),使用这个score来给集合排序,score可以重复</p>\n<p>加权排序set,类似于Java中优先队列,只不过redis中将队列更换为set</p>\n</blockquote>\n<h3 id=\"%E5%91%BD%E4%BB%A4-4\" tabindex=\"-1\">命令</h3>\n<ul>\n<li><code>zadd &lt;k&gt; &lt;score&gt; &lt;k&gt; &lt;score&gt; &lt;k&gt; &lt;score&gt;</code>添加key和score,会根据score排名</li>\n<li><code>arange &lt;k&gt; &lt;start&gt; &lt;stop&gt; withscores</code>获取scores在开始和结束之间的元素</li>\n<li><code>zrangebyscore &lt;k&gt; &lt;mim&gt; &lt;max&gt;</code>返回并且排名 最小scores和最大scores</li>\n<li><code>zincrbg &lt;k&gt; &lt;n&gt; &lt;v&gt;</code>为元素v添加n的scores</li>\n<li><code>zrem &lt;k&gt; &lt;v&gt;</code>删除</li>\n<li><code>zcount &lt;k&gt; &lt;min&gt; &lt;max&gt;</code>统计min scores 和max scores之间元素个数</li>\n<li><code>zrank &lt;k&gt; &lt;v&gt;</code>获取该元素的排名,从0开始</li>\n</ul>\n<h3 id=\"%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-3\" tabindex=\"-1\">数据结构</h3>\n<p>hash 跳跃表</p>\n<h3 id=\"%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF-4\" tabindex=\"-1\">使用场景</h3>\n<ol>\n<li>排行榜</li>\n</ol>\n<h1 id=\"%E7%89%B9%E6%AE%8A%E7%B1%BB%E5%9E%8B%EF%BC%883%E7%A7%8D%EF%BC%89\" tabindex=\"-1\">特殊类型(3种)</h1>\n<blockquote>\n<p>以下内容的学习均来自于此,使用了代码片段</p>\n<p><a href=\"https://www.pdai.tech/md/db/nosql-redis/db-redis-data-type-special.html#hyperloglogs%E5%9F%BA%E6%95%B0%E7%BB%9F%E8%AE%A1\">原文地址🔗</a></p>\n</blockquote>\n<h2 id=\"hyperloglogs%EF%BC%88%E5%9F%BA%E6%95%B0%E7%BB%9F%E8%AE%A1%EF%BC%89\" tabindex=\"-1\">HyperLogLogs(基数统计)</h2>\n<h3 id=\"%E4%BB%80%E4%B9%88%E6%98%AF%E5%9F%BA%E6%95%B0\" tabindex=\"-1\">什么是基数</h3>\n<p>两个集合的全集</p>\n<p>例如:<code>A = {1,2,3,4,5,6}</code> ; B = <code>{5,6,7,8,9}</code> ; 基数 = <code>{1,2,3,4,7,8,9}</code>,即不重复元素。</p>\n<h3 id=\"%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF-5\" tabindex=\"-1\">使用场景</h3>\n<p>统计和计数,用于统计注册IP数,每日访问IP书,页面实时UV,在线用户数等。</p>\n<h3 id=\"%E4%BC%98%E5%8A%BF\" tabindex=\"-1\">优势</h3>\n<p>基于基数估算的算法,能比较准确的估算出基数,可以使用少量固定的内存存储并识别集合中唯一的原色。</p>\n<p>这个算法并不一定准确,有0.81%的错误率,基数统计适合接受一定容错的场景,比如统计访客数量等。</p>\n<h3 id=\"%E5%91%BD%E4%BB%A4-5\" tabindex=\"-1\">命令</h3>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> pfadd</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> key1</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> a</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> b</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> c</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> d</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> e</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> f</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> g</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> h</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> i</span><span style=\"color:#6A737D;--shiki-dark:#6A737D\">\t# 创建第一组元素</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 1</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> pfcount</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> key1</span><span style=\"color:#6A737D;--shiki-dark:#6A737D\">\t\t\t\t\t# 统计元素的基数数量</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 9</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> pfadd</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> key2</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> c</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> j</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> k</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> l</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> m</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> e</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> g</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> a</span><span style=\"color:#6A737D;--shiki-dark:#6A737D\">\t\t# 创建第二组元素</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 1</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> pfcount</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> key2</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 8</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> pfmerge</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> key3</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> key1</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> key2</span><span style=\"color:#6A737D;--shiki-dark:#6A737D\">\t\t\t# 合并两组:key1 key2 -> key3 并集</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">OK</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> pfcount</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> key3</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 13</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"127.0.0.1:6379> pfadd key1 a b c d e f g h i\t# 创建第一组元素\n(integer) 1\n127.0.0.1:6379> pfcount key1\t\t\t\t\t# 统计元素的基数数量\n(integer) 9\n127.0.0.1:6379> pfadd key2 c j k l m e g a\t\t# 创建第二组元素\n(integer) 1\n127.0.0.1:6379> pfcount key2\n(integer) 8\n127.0.0.1:6379> pfmerge key3 key1 key2\t\t\t# 合并两组:key1 key2 -> key3 并集\nOK\n127.0.0.1:6379> pfcount key3\n(integer) 13\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"bitmap%EF%BC%88%E4%BD%8D%E5%AD%98%E5%82%A8%EF%BC%89\" tabindex=\"-1\">Bitmap(位存储)</h2>\n<p>Bitmap是通过二进制记录信息,只有 0 和 1 两个状态</p>\n<h3 id=\"%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF-6\" tabindex=\"-1\">使用场景</h3>\n<ol>\n<li>统计用户登陆信息,登陆和未登陆</li>\n<li>统计用户点赞信息,点了和没点</li>\n<li>统计员工打卡信息,打了和没打</li>\n</ol>\n<h3 id=\"%E5%91%BD%E4%BB%A4-6\" tabindex=\"-1\">命令</h3>\n<ul>\n<li>\n<p>使用<code>setbit &lt;key&gt; &lt;offset&gt; &lt;value&gt;</code>写入数据,其中key可以任意,offset只能为Integer,value只能为0或1</p>\n<p>如果要统计员工一周的打卡情况,key可以设置为sign,offset设置为0-6,打卡为0,未打卡为1</p>\n</li>\n</ul>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> setbit</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> sign</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 0</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 1</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 0</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> setbit</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> sign</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 1</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 1</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 0</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> setbit</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> sign</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 2</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 0</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 0</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> setbit</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> sign</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 3</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 1</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 0</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> setbit</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> sign</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 4</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 0</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 0</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> setbit</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> sign</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 5</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 0</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 0</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> setbit</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> sign</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 6</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 1</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 0</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"127.0.0.1:6379> setbit sign 0 1\n(integer) 0\n127.0.0.1:6379> setbit sign 1 1\n(integer) 0\n127.0.0.1:6379> setbit sign 2 0\n(integer) 0\n127.0.0.1:6379> setbit sign 3 1\n(integer) 0\n127.0.0.1:6379> setbit sign 4 0\n(integer) 0\n127.0.0.1:6379> setbit sign 5 0\n(integer) 0\n127.0.0.1:6379> setbit sign 6 1\n(integer) 0\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<ul>\n<li>使用<code>getbit &lt;key&gt; &lt;offset&gt;</code>来查看某一个key的状态,返回0或1</li>\n</ul>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> getbit</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> sign</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 3</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 1</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> getbit</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> sign</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 5</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 0</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"127.0.0.1:6379> getbit sign 3\n(integer) 1\n127.0.0.1:6379> getbit sign 5\n(integer) 0\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<ul>\n<li>使用<code>bitcount &lt;key&gt;</code>统计某一项数据的总数</li>\n</ul>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> bitcount</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> sign</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 3</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"127.0.0.1:6379> bitcount sign\n(integer) 3\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<h2 id=\"geospatial%EF%BC%88%E5%9C%B0%E7%90%86%E4%BD%8D%E7%BD%AE%EF%BC%89\" tabindex=\"-1\">geospatial(地理位置)</h2>\n<p>可以用户推算地理位置信息,如两地之间距离等</p>\n<h3 id=\"%E5%91%BD%E4%BB%A4-7\" tabindex=\"-1\">命令</h3>\n<ul>\n<li><code>geoadd</code>添加位置</li>\n</ul>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> geoadd</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> china:city</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 118.76</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 32.04</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> nanjing</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 112.55</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 37.86</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> taiyuan</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 123.43</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 41.80</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> shenyang</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 3</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> geoadd</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> china:city</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 144.05</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 22.52</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> shengzhen</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 120.16</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 30.24</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> hangzhou</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 108.96</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\"> 34.26</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> xian</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">integer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 3</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"127.0.0.1:6379> geoadd china:city 118.76 32.04 nanjing 112.55 37.86 taiyuan 123.43 41.80 shenyang\n(integer) 3\n127.0.0.1:6379> geoadd china:city 144.05 22.52 shengzhen 120.16 30.24 hangzhou 108.96 34.26 xian\n(integer) 3\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<ul>\n<li><code>geopop</code>获取指定成员的地理位置</li>\n</ul>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> geopos</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> china:city</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> taiyuan</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> nanjing</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">1</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 1) </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"112.54999905824661255\"</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> 1</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"37.86000073876942196\"</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">2</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) 1) </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"118.75999957323074341\"</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> 1</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"32.03999960287850968\"</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"127.0.0.1:6379> geopos china:city taiyuan nanjing\n1) 1) &quot;112.54999905824661255&quot;\n 1) &quot;37.86000073876942196&quot;\n2) 1) &quot;118.75999957323074341&quot;\n 1) &quot;32.03999960287850968&quot;\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<ul>\n<li><code>geodist</code>获取两地之间的距离,可以指定单位</li>\n</ul>\n\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> geodist</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> china:city</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> taiyuan</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> shenyang</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> m</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">\"1026439.1070\"</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">127.0.0.1:6379></span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> geodist</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> china:city</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> taiyuan</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> shenyang</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\"> km</span></span>\n<span class=\"line\"><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">\"1026.4391\"</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"127.0.0.1:6379> geodist china:city taiyuan shenyang m\n&quot;1026439.1070&quot;\n127.0.0.1:6379> geodist china:city taiyuan shenyang km\n&quot;1026.4391&quot;\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n<ul>\n<li><code>georadius</code></li>\n</ul>\n<p><a href=\"https://cloud.tencent.com/developer/section/1374022\">这里有详细解释🔗</a></p>\n<p>附近的人,获得所有附近的人的地址, 定位, 通过半径来查询</p>\n<ul>\n<li><code>georadiusbymember</code></li>\n</ul>\n<p><a href=\"https://cloud.tencent.com/developer/section/1374023\">link🔗</a></p>\n<p>显示与指定成员一定半径范围内的其他成员</p>\n<h1 id=\"redis%E4%B8%AD%E7%9A%84%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84\" tabindex=\"-1\">Redis中的数据结构</h1>\n<ul>\n<li>5种基础数据结构:string(字符串)、list(列表)、set(集合)、hash(散列)、zset(有序集合)</li>\n<li>3种特殊数据结构:HyperLogLogs(基数统计)、Bitmap(位存储)、Geospatial(地理位置)</li>\n</ul>\n<h1 id=\"%E5%AF%B9%E5%BA%94%E5%85%B3%E7%B3%BB\" tabindex=\"-1\">对应关系</h1>\n<blockquote>\n<p><a href=\"https://www.pdai.tech/md/db/nosql-redis/db-redis-data-type-enc.html\">图片来自</a></p>\n</blockquote>\n<figure><img src=\"https://typora-1308549476.cos.ap-nanjing.myqcloud.com/img/image-20221016185227739.png\" alt=\"image-20221016185227739\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n<h1 id=\"%E5%8A%A8%E6%80%81%E5%AD%97%E7%AC%A6%E4%B8%B2sds\" tabindex=\"-1\">动态字符串SDS</h1>\n<p>Redis并没有使用C中的字符串,而是自己定义了一种数据结构,即简单动态字符串(Simple Dynamic String SDS)。Redis中String的底层数据结构使用的就是SDS。</p>\n<h2 id=\"sds%E5%86%85%E5%AD%98%E7%BB%93%E6%9E%84\" tabindex=\"-1\">SDS内存结构</h2>\n<ul>\n<li><code>len</code>保存SDS保存字符串的长度</li>\n<li><code>buf[]</code>数组保存字符串的每个元素</li>\n<li><code>alloc</code>分别以unint8、unint16、unint32、unint64表示整个SDS</li>\n<li><code>flags</code>始终为一字符,以低三位标示着头部的类型</li>\n</ul>\n<h2 id=\"sds%E7%9A%84%E4%BC%98%E5%8A%BF\" tabindex=\"-1\">SDS的优势</h2>\n<ul>\n<li><strong>O(1)复杂度获取字符串长度</strong>:在Redis中如果要获取字符串长度只需读取len属性即可,在C中如果要获取字符串长度需要遍历整个字符串,是O(n)复杂度。使用<code>strlen &lt;K&gt;</code>获取字符串长度。</li>\n<li><strong>防止缓冲区溢出</strong>:在C中,使用<code>strcat</code>中拼接两字符串,如果没有分配足够的内存空间,会造成缓冲区溢出。SDS会先根据len先推算拼接后的长度是否满足内存空间要求。不满足会先扩展,再拼接,从而防止缓冲区溢出。</li>\n<li><strong>减少修改字符串内存重新分配次数</strong>:SDS使用<code>len</code>和<code>alloc</code>实现<strong>空间预分配</strong>和<strong>惰性空间释放</strong>。\n<ul>\n<li><strong>空间预分配</strong>:对字符串空间扩展时,扩展大于需求,从而减少字符串长度增加所需的内存重新分配次数。当字符串小于1M时,redis会分配字符串大小一倍的空间,当字符串大小大于1M是,额外多分配1M空间。</li>\n<li><strong>惰性空间释放</strong>:字符串长度减少时,不立即归还内存,而是使用<code>alloc</code>属性将这些空间记录下来,等待后续使用。如果觉得这样会浪费空间,可以自行设置定时释放未使用空间。</li>\n</ul>\n</li>\n<li><strong>二进制安全</strong>:C中使用空字符来表示一个字符串的结束。但是如果Redis中保存的二进制文件(如图片)中可能包含空字符,C无法正确读取。SDS使用<code>len</code>属性表示的长度来判断字符串是否结束。</li>\n</ul>\n<h1 id=\"%E5%8E%8B%E7%BC%A9%E5%88%97%E8%A1%A8ziplist\" tabindex=\"-1\">压缩列表ZipList</h1>\n<p>ziplist是一种为提高存储效率设计的特殊编码的双向链表。可用于存储字符串或整数。</p>\n<h2 id=\"ziplist%E5%86%85%E5%AD%98%E7%BB%93%E6%9E%84\" tabindex=\"-1\">ziplist内存结构</h2>\n<ul>\n<li><code>zlbytes</code>存储整个ziplist所占用内存字节数</li>\n<li><code>zltail</code>存储ziplist中最后一个entry的偏移量,用于快速定位最后一个entry,方便快速pop操作</li>\n<li><code>zllen</code>存储ziplist中entry的数量。</li>\n<li><code>zlend</code>是终止字节</li>\n</ul>\n<h2 id=\"entry%E7%BB%93%E6%9E%84\" tabindex=\"-1\">Entry结构</h2>\n<p><code>&lt;prevlen&gt; &lt;encoding&gt; &lt;entry-data&gt;</code></p>\n<ul>\n<li><code>prevlen</code>前一个entry的大小</li>\n<li><code>encoding</code>当前entry的类型和长度</li>\n<li><code>entry-data</code>entry数据</li>\n</ul>\n<p>PS:如果entry-data中保存的是整形数据,encoding会和entrydata合为一个,此时entry结构为<code>&lt;prevlen&gt; &lt;encoding&gt;</code></p>\n<h2 id=\"ziplist%E4%BC%98%E7%82%B9\" tabindex=\"-1\">ziplist优点</h2>\n<p>节省内存</p>\n<ul>\n<li>普通List保存是,每个元素占用空间大小一致,均为当前List中最大元素所占的空间大小,造成了空间浪费。</li>\n<li>ziplist通过特殊的数据结构,尽量是每个元素占用与自身大小相同的空间,减少空间浪费。</li>\n<li>传统List在内存中地址连续,ziplist所占大小不一致,所以地址不连续,需要通过<code>prelen</code>字段保存上一个元素的length来解决遍历问题。</li>\n</ul>\n<h2 id=\"ziplist%E7%BC%BA%E7%82%B9\" tabindex=\"-1\">ziplist缺点</h2>\n<ul>\n<li>不预留内存空间,list中元素被移除之后list无用空间立即归还,这导致每一次修改list都需要重新分配空间。</li>\n</ul>\n<h1 id=\"%E5%BF%AB%E8%A1%A8quicklist\" tabindex=\"-1\">快表QuickList</h1>\n<p>以ziplist作为结点的双端链表,如何理解QuickList:<code>List&lt;List&lt;ziplist&gt;&gt; quickList</code></p>\n<h2 id=\"quicklist%E5%9C%A8%E5%86%85%E5%AD%98%E4%B8%AD%E7%BB%93%E6%9E%84\" tabindex=\"-1\">quicklist在内存中结构</h2>\n<ul>\n<li><code>quicklistNode</code>链表中的节点,在quicklist中,这个节点是ziplist</li>\n<li><code>quickListLZF</code>ziplist经过LZ4算法压缩后,可以包装成一个<code>quickListLZF</code>结构</li>\n<li><code>quicklistBookmark</code>位于quicklist尾部</li>\n<li><code>quicklist</code>\n<ul>\n<li>head、tail指向头尾指针</li>\n<li>len表示链表中的节点</li>\n<li>count表示quicklist中ziplist中entry数目</li>\n<li>fill控制每个quicklist中ziplist最大所占空间</li>\n<li>compress控制是否要对每个ziplist以LZ4算法进行压缩以节省空间</li>\n</ul>\n</li>\n<li><code>quicklistIter</code>迭代器</li>\n<li><code>quicklistEntry</code>对ziplist中entry封装</li>\n</ul>\n<h1 id=\"%E5%93%88%E5%B8%8C%E8%A1%A8-dict-hashtable\" tabindex=\"-1\">哈希表-Dict-HashTable</h1>\n<p>哈希表于大多数语言中的HashTable无异,差别主要存在于解决哈希冲突、扩容。</p>\n<h2 id=\"%E5%93%88%E5%B8%8C%E5%86%B2%E7%AA%81\" tabindex=\"-1\">哈希冲突</h2>\n<p>使用链地址法,<a href=\"https://www.beyondhorizon.top/article/xclfxsXC\">在Java数据结构中已经学习过了</a></p>\n<h2 id=\"%E6%89%A9%E5%AE%B9\" tabindex=\"-1\">扩容</h2>\n<p>扩容步骤:</p>\n<ol>\n<li>根据原哈希表所占空间大小创建一个新哈希表,大小为原哈希表一倍,(收缩也是减小为原来一倍大小)</li>\n<li>使用哈希算法重新计算索引值</li>\n<li>新表创建并赋值完毕之后删除原表</li>\n</ol>\n<p>扩容发生条件</p>\n<ol>\n<li>redis没有执行<code>bgsave</code>或<code>bgrewriteaof</code>命令,负载因子大于等于1</li>\n<li>redis没有执行<code>bgsave</code>或<code>bgrewriteaof</code>命令,负载因子大于等于5</li>\n</ol>\n<p>负载因子 = 哈希表中节点数量 / 哈希表大小</p>\n<h1 id=\"%E6%95%B4%E6%95%B0%E9%9B%86-intset\" tabindex=\"-1\">整数集 IntSet</h1>\n<p>intset是redis中集合类型底层实现之一,当一个集合只包含整数数值元素,并且元素数量较少,redis使用intset作为集合键的底层实现</p>\n<h2 id=\"%E5%86%85%E5%AD%98%E7%BB%93%E6%9E%84\" tabindex=\"-1\">内存结构</h2>\n<ul>\n<li><code>encoding</code>编码方式</li>\n<li><code>length</code>存储整数个数</li>\n</ul>\n<h2 id=\"%E6%89%A9%E5%AE%B9-1\" tabindex=\"-1\">扩容</h2>\n<p>intset底层为数组,当新插入的元素大小大于原数组中最大元素的大小是,就需要对整个数组进行扩容,每个元素所占空间大小修改为最大元素的大小</p>\n<p>会扩容但不会缩容!</p>\n<h1 id=\"%E8%B7%B3%E8%A1%A8zskiplist\" tabindex=\"-1\">跳表ZSkipList</h1>\n<p>跳跃表的目的类似于红黑树,为了性能。跳跃表可以在对数时间内完成插入、查找、删除。但是跳跃表所占空间较大,属于空间换时间的数据结构。</p>\n<h2 id=\"%E4%BB%80%E4%B9%88%E6%98%AF%E8%B7%B3%E8%B7%83%E8%A1%A8\" tabindex=\"-1\">什么是跳跃表</h2>\n<p>传统链表如果需要查询元素,需要从头遍历整个链表知道找到查询元素,时间复杂度O(n)。跳跃表通过增加多级索引的方式减少遍历长度,从而加快查找速度。跳跃表实现了平衡树、哈希表类似的效果。</p>\n<p>为什么不使用平衡树,而是跳跃表</p>\n<blockquote>\n<p><a href=\"https://www.jianshu.com/p/8ac45fd01548\">链接🔗</a></p>\n</blockquote>\n<p><a href=\"https://www.pdai.tech/md/db/nosql-redis/db-redis-x-redis-ds.html#%E6%95%B4%E6%95%B0%E9%9B%86---intset\">图片来自</a></p>\n<figure><img src=\"https://typora-1308549476.cos.ap-nanjing.myqcloud.com/img/image-20221009184634434.png\" alt=\"image-20221009184634434\" loading=\"lazy\" decoding=\"async\" class=\"w-full h-auto rounded-md shadow hover:shadow-lg transition-all\" /></figure>\n"},{"_id":"65ca3152912f6564d5af088f","shortLink":"druid-config","title":"DruidDataSource Config","description":"DruidDataSource Config","cover":"https://static.vio.vin/blog/2023/11/6afab03f0daeb37aabb6bd9ab5cac4e8.png","category":"short","tags":["druid","springboot"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-11-26T14:01:16.757Z","updatedAt":"2024-02-27T03:26:33.417Z","status":"PUBLISHED","views":6,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/36e52c2bc17923f659345acaa51c9b9325cf9f3fb49d0eb213e742d83add225e.png","html":"\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\">spring</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> datasource</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> type</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">com.alibaba.druid.pool.DruidDataSource</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> driver-class-name</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">com.mysql.cj.jdbc.Driver</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> url</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">jdbc:mysql://d-mysql:3306/share?useUnicode=true&#x26;useSSL=false&#x26;characterEncoding=utf8&#x26;serverTimezone=Asia/Shanghai</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> username</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">root</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> password</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">mysqlforserver@date0913</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> druid</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> initial-size</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">50</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> min-idle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">20</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> max-active</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">100</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> max-wait</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">60000</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> time-between-eviction-runs-millis</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">60000</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> min-evictable-idle-time-millis</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">300000</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> validation-query</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">SELECT 1 FROM DUAL</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> test-while-idle</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> test-on-borrow</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">false</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> test-on-return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">false</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> filter</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> stat</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> db-type</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">mysql</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> enabled</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> log-slow-sql</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> slow-sql-millis</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">2000</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> slf4j</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> enabled</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> statement-log-enabled</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> statement-create-after-log-enabled</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">false</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> connection-close-after-log-enabled</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">false</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> result-set-open-after-log-enabled</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">false</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> result-set-close-after-log-enabled</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">false</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> stat-view-servlet</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">:</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> enabled</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">true</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> url-pattern</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">/druid/*</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> reset-enable</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">false</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> login-username</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">root</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> login-password</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">Dd112211</span></span>\n<span class=\"line\"><span style=\"color:#22863A;--shiki-dark:#85E89D\"> allow</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">: </span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">0.0.0.0/0</span></span></code></pre>\n\n\t<button class=\"markdown-it-code-copy \" data-clipboard-text=\"spring:\n datasource:\n type: com.alibaba.druid.pool.DruidDataSource\n driver-class-name: com.mysql.cj.jdbc.Driver\n url: jdbc:mysql://d-mysql:3306/share?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai\n username: root\n password: mysqlforserver@date0913\n druid:\n initial-size: 50\n min-idle: 20\n max-active: 100\n max-wait: 60000\n time-between-eviction-runs-millis: 60000\n min-evictable-idle-time-millis: 300000\n validation-query: SELECT 1 FROM DUAL\n test-while-idle: true\n test-on-borrow: false\n test-on-return: false\n filter:\n stat:\n db-type: mysql\n enabled: true\n log-slow-sql: true\n slow-sql-millis: 2000\n slf4j:\n enabled: true\n statement-log-enabled: true\n statement-create-after-log-enabled: false\n connection-close-after-log-enabled: false\n result-set-open-after-log-enabled: false\n result-set-close-after-log-enabled: false\n stat-view-servlet:\n enabled: true\n url-pattern: /druid/*\n reset-enable: false\n login-username: root\n login-password: Dd112211\n allow: 0.0.0.0/0\n\" style=\"position: absolute; top: 7.5px; right: 6px; cursor: pointer; outline: none;\" title=\"Copy\">\n\t\t<span style=\"font-size: 1.5em;width: 20px;height: 20px;background-size: cover;display: inline-block;\" class=\"i-carbon-copy w-30px h-30px text-violet opacity-50 hover:opacity-100 transition-all\"></span>\n\t</button>\n</div>\n"},{"_id":"65ca3152912f6564d5af088e","shortLink":"redis-cache-config","title":"Redis Cache Config","description":"Redis Cache Config","cover":"https://static.vio.vin/blog/2023/11/2b08aa3855f101388733748cdf823008.png","category":"short","tags":["redis","springboot"],"authorId":"65c9f17ccc3a7831bb5612ca","createdAt":"2023-11-26T13:53:51.560Z","updatedAt":"2024-02-27T03:28:04.050Z","status":"PUBLISHED","views":6,"likes":0,"ogImage":"https://static.vio.vin/og/2024/02/9afb59b30a33b284df41274379d00f01ae3d821a6735cacacc879258108b61c6.png","html":"\n<div style=\"position: relative\">\n\t<pre class=\"shiki shiki-themes github-light github-dark\" style=\"background-color:#fff;--shiki-dark-bg:#24292e;color:#24292e;--shiki-dark:#e1e4e8\" tabindex=\"0\"><code class=\"language-java\"><span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Configuration</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">@</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">EnableCaching</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\">public</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> class</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> CacheConfig</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> {</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Bean</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> CacheManager </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">cacheManager</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(RedisConnectionFactory </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">redisConnectionFactory</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 使用 RedisCacheManager 作为默认的缓存管理器</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> RedisCacheManager</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">builder</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(redisConnectionFactory)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">cacheDefaults</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(RedisCacheConfiguration.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">defaultCacheConfig</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">().</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">entryTtl</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Duration.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">ofHours</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">24</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">)))</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">build</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Bean</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> RedisCacheManager </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">redisCacheManager</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(RedisConnectionFactory </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">redisConnectionFactory</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 配置默认的缓存配置</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> RedisCacheConfiguration defaultCacheConfig </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> RedisCacheConfiguration.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">defaultCacheConfig</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">entryTtl</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Duration.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">ofHours</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">24</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">))</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">disableCachingNullValues</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">serializeValuesWith</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(RedisSerializationContext.SerializationPair.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">fromSerializer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> GenericJackson2JsonRedisSerializer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()));</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 配置缓存名称和具体的缓存配置</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> Map&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">RedisCacheConfiguration</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> cacheConfigurations </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> HashMap&#x3C;>();</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> return</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> RedisCacheManager.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">builder</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(redisConnectionFactory)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">cacheDefaults</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(defaultCacheConfig)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">initialCacheNames</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(Collections.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">singleton</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#032F62;--shiki-dark:#9ECBFF\">\"user\"</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">))</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">withInitialCacheConfigurations</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(cacheConfigurations)</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">transactionAware</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">()</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> .</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">build</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> }</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> @</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Bean</span></span>\n<span class=\"line\"><span style=\"color:#D73A49;--shiki-dark:#F97583\"> public</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> RedisTemplate&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> </span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">redisTemplate</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(RedisConnectionFactory </span><span style=\"color:#E36209;--shiki-dark:#FFAB70\">redisConnectionFactory</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">) {</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> RedisTemplate&#x3C;</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">String</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">, </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">Object</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">> template </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> RedisTemplate&#x3C;>();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> template.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setConnectionFactory</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(redisConnectionFactory);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 配置 ObjectMapper,用于定制序列化和反序列化行为</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> ObjectMapper objectMapper </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> ObjectMapper</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">();</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> objectMapper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setVisibility</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> objectMapper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">activateDefaultTyping</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> objectMapper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">configure</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">false</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> objectMapper.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">configure</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(SerializationFeature.FAIL_ON_EMPTY_BEANS, </span><span style=\"color:#005CC5;--shiki-dark:#79B8FF\">false</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 使用 Lettuce 提供的 GenericJackson2JsonRedisSerializer 作为序列化工具</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> GenericJackson2JsonRedisSerializer serializer </span><span style=\"color:#D73A49;--shiki-dark:#F97583\">=</span><span style=\"color:#D73A49;--shiki-dark:#F97583\"> new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> GenericJackson2JsonRedisSerializer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(objectMapper);</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#6A737D;--shiki-dark:#6A737D\"> // 设置序列化和反序列化工具</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> template.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setKeySerializer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> StringRedisSerializer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> template.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setValueSerializer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(serializer);</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> template.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setHashKeySerializer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">(</span><span style=\"color:#D73A49;--shiki-dark:#F97583\">new</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\"> StringRedisSerializer</span><span style=\"color:#24292E;--shiki-dark:#E1E4E8\">());</span></span>\n<span class=\"line\"><span style=\"color:#24292E;--shiki-dark:#E1E4E8\"> template.</span><span style=\"color:#6F42C1;--shiki-dark:#B392F0\">setHashValueSerializer</span