liyanshuang 2 weeks ago
parent
commit
088cc61ac9
  1. 60
      zhangbo/第九天技术学习笔记.txt
  2. 61
      zhangbo/第九天股票知识学习笔记.txt
  3. 0
      吴光慧学习笔记/11.3/test1.vue
  4. 0
      吴光慧学习笔记/11.3/test2.vue
  5. 0
      吴光慧学习笔记/11.3/test3.vue
  6. 0
      吴光慧学习笔记/11.3/test4.vue
  7. 0
      吴光慧学习笔记/11.4/props.vue
  8. 0
      吴光慧学习笔记/11.4/test1.vue
  9. 0
      吴光慧学习笔记/11.4/test2.vue
  10. BIN
      吴光慧学习笔记/11.5/11.5学习总结-吴光慧.docx
  11. 70
      吴光慧学习笔记/11.5/Count.txt
  12. 38
      吴光慧学习笔记/11.5/LoveTalk.txt
  13. 30
      吴光慧学习笔记/11.5/query.txt
  14. 2
      吴光慧学习笔记/11.5/备份/About.vue
  15. 12
      吴光慧学习笔记/11.5/备份/App.txt
  16. 30
      吴光慧学习笔记/11.5/备份/Detail.vue
  17. 10
      吴光慧学习笔记/11.5/备份/Home.vue
  18. 61
      吴光慧学习笔记/11.5/备份/News.txt
  19. 0
      吴光慧学习笔记/11.5/备份/hooks.vue
  20. 21
      吴光慧学习笔记/11.5/备份/index.ts
  21. 42
      吴光慧学习笔记/11.5/备份/router/index.ts
  22. BIN
      吴光慧学习笔记/11.5/道氏理论定义及基本观点.docx
  23. 4
      吴光慧学习笔记/hello_vue3/node_modules/.bin/nanoid
  24. 2
      吴光慧学习笔记/hello_vue3/node_modules/.bin/nanoid.cmd
  25. 8
      吴光慧学习笔记/hello_vue3/node_modules/.bin/nanoid.ps1
  26. 121
      吴光慧学习笔记/hello_vue3/node_modules/.package-lock.json
  27. 31
      吴光慧学习笔记/hello_vue3/node_modules/.vite/deps/_metadata.json
  28. 1
      吴光慧学习笔记/hello_vue3/node_modules/.vite/deps/vue.js
  29. 16
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/.bin/nanoid
  30. 17
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/.bin/nanoid.cmd
  31. 28
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/.bin/nanoid.ps1
  32. 20
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/LICENSE
  33. 38
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/README.md
  34. 45
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/bin/nanoid.js
  35. 29
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/index.browser.js
  36. 106
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/index.d.ts
  37. 47
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/index.js
  38. 1
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/nanoid.js
  39. 48
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/non-secure/index.d.ts
  40. 21
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/non-secure/index.js
  41. 43
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/package.json
  42. 2
      吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/url-alphabet/index.js
  43. 17
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/README.md
  44. 69
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/index.browser.cjs
  45. 34
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/index.browser.js
  46. 71
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/index.cjs
  47. 56
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/index.d.ts
  48. 35
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/index.js
  49. 26
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/index.native.js
  50. 12
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/package.json
  51. 55
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/bin/nanoid.cjs
  52. 72
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/index.browser.cjs
  53. 35
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/index.browser.js
  54. 85
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/index.cjs
  55. 91
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/index.d.cts
  56. 25
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/index.d.ts
  57. 28
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/index.js
  58. 2
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/nanoid.js
  59. 34
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/non-secure/index.cjs
  60. 23
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/non-secure/index.d.ts
  61. 6
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/non-secure/index.js
  62. 6
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/non-secure/package.json
  63. 76
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/package.json
  64. 7
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/url-alphabet/index.cjs
  65. 3
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/url-alphabet/index.js
  66. 6
      吴光慧学习笔记/hello_vue3/node_modules/nanoid/url-alphabet/package.json
  67. 125
      吴光慧学习笔记/hello_vue3/package-lock.json
  68. 4
      吴光慧学习笔记/hello_vue3/package.json
  69. 71
      吴光慧学习笔记/hello_vue3/src/App.vue
  70. 47
      吴光慧学习笔记/hello_vue3/src/components/Count.vue
  71. 45
      吴光慧学习笔记/hello_vue3/src/components/LoveTalk.vue
  72. 34
      吴光慧学习笔记/hello_vue3/src/components/News.vue
  73. 48
      吴光慧学习笔记/hello_vue3/src/components/Person.vue
  74. 13
      吴光慧学习笔记/hello_vue3/src/main.ts
  75. 29
      吴光慧学习笔记/hello_vue3/src/store/count.ts
  76. 22
      吴光慧学习笔记/hello_vue3/src/store/loveTalk.ts
  77. BIN
      尹顺宇学习笔记/尹顺宇11.05作业/尹顺宇11.05AI探牛深入学习.docx
  78. BIN
      尹顺宇学习笔记/尹顺宇11.05作业/尹顺宇11.05学习总结.docx
  79. 387
      尹顺宇学习笔记/尹顺宇11.05作业/尹顺宇11.05学习笔记.md
  80. BIN
      尹顺宇学习笔记/尹顺宇11.05作业/尹顺宇11.05学习笔记.pdf
  81. 434
      股票知识评测系统.vue

60
zhangbo/第九天技术学习笔记.txt

@ -0,0 +1,60 @@
Spring框架复习笔记整理以“三层架构”为核心
Spring框架下的三层架构
一、三层架构核心概念
三层架构是项目后端开发的经典分层结构,它将业务逻辑按职责划分为三个独立层次,目的是降低代码耦合度、提高可维护性和可扩展性。这三个层次自上而下分别是**表现层(Controller)**、**业务逻辑层(Service)** 和**数据访问层(Dao)**,每层仅与上下相邻层交互,不跨层调用。
在Spring框架中,三层架构的实现完全依赖于IoC容器和注解,每层的Bean都由Spring统一管理,层与层之间通过依赖注入(@Autowired/@Resource)建立关联。
二、各层职责与Spring实现
1. 表现层(Controller层)
核心职责:接收前端请求、参数校验、调用Service层方法、封装响应数据(如JSON)返回给前端。它是用户与系统交互的入口,不处理复杂业务逻辑。
Spring实现方式:
使用`@Controller`或`@RestController`注解声明类为表现层Bean,纳入Spring IoC容器。
通过`@RequestMapping`、`@GetMapping`、`@PostMapping`等注解映射前端请求路径和请求方式。
方法参数通过`@RequestParam`(获取URL参数)、`@RequestBody`(获取JSON请求体)等注解接收前端数据。
2. 业务逻辑层(Service层)
核心职责:处理核心业务逻辑(如用户注册时的合法性校验、订单生成时的库存扣减)、协调多个Dao层方法完成复杂业务、事务管理(如转账时的原子性保证)。它是系统的“大脑”,承上启下。
Spring实现方式:
使用`@Service`注解声明类为业务层Bean,纳入IoC容器。
业务层通常包含“接口+实现类”的结构(如`UserService`接口和`UserServiceImpl`实现类),接口定义方法,实现类写具体逻辑,降低耦合。
通过`@Autowired`注入Dao层Bean,调用Dao层方法操作数据。
使用`@Transactional`注解声明事务,确保业务操作的原子性(如失败回滚)。
3. 数据访问层(Dao层/Repository层)
核心职责:直接与数据库交互,执行数据的CRUD操作(Create/Read/Update/Delete),不包含业务逻辑。它是系统与数据库之间的“桥梁”。
Spring实现方式:
使用`@Repository`注解声明类为数据访问层Bean,纳入IoC容器(若使用MyBatis,`@Mapper`注解可替代,且需配置扫描路径)。
传统方式:Dao层通过Spring JDBC(如`JdbcTemplate`)执行SQL;实际开发中多结合MyBatis,通过XML或注解(`@Select`/`@Insert`)编写SQL。
不依赖Service层,仅对外提供数据操作方法,由Service层调用。
三、三层架构的请求流转流程
以“用户查询”功能为例,完整的请求流转如下:
1. 前端发送GET请求:`http://localhost:8080/user/1`,请求查询ID为1的用户。
2. Spring MVC拦截请求,根据`@RequestMapping("/user")`和`@GetMapping("/{id}")`,将请求分发到`UserController`的`getUserById`方法。
3. `UserController`通过`@PathVariable`接收参数`id=1`,调用注入的`UserService`的`getUserById`方法。
4. `UserService`(`UserServiceImpl`)调用注入的`UserDao`的`selectById`方法,请求数据。
5. `UserDao`执行SQL查询数据库,返回`User`对象给`UserService`。
6. `UserService`将`User`对象返回给`UserController`。
7. `UserController`将`User`对象封装成统一响应格式(如`Result<User>`),返回JSON给前端。
四、三层架构的优势与注意事项
1. 核心优势
低耦合:每层职责单一,修改某一层(如更换数据库,仅改Dao层)不影响其他层。
高可维护:代码按功能分层,定位问题时可快速锁定到具体层(如前端报错查Controller,数据错误查Dao)。
高可扩展:支持分层扩展,如增加“用户积分”功能,仅需新增`PointService`和`PointDao`,不修改现有代码。
2. 注意事项
禁止跨层调用:不能直接在Controller层调用Dao层,必须通过Service层中转,否则会破坏分层逻辑,增加耦合。
事务声明在Service层:事务必须加在Service层方法上,因为Service层是业务逻辑的处理单元,Controller层仅负责请求转发,不适合管理事务。
Bean命名规范:各层Bean命名建议加前缀,如`UserController`、`UserService`、`UserDao`,提高代码可读性。
五、三层架构与MVC的区别
三层架构和MVC,两者本质是不同维度的设计思想,核心区别如下:
| 对比维度 | 三层架构 | MVC |
|---------- |---------------------------------------------|------------------------------------------------------|
| 设计范围 | 后端代码分层(Controller/Service/Dao) | 前后端交互架构(Model/View/Controller) |
| 核心目的 | 降低后端代码耦合,优化后端开发流程 | 分离前端视图与后端数据、逻辑,优化前后端交互 |
| 对应关系 | 三层架构的“表现层(Controller)”对应MVC的“Controller”;三层架构的“Service+Dao”对应MVC的“Model”;MVC的“View”是前端页面(三层架构不包含前端) |

61
zhangbo/第九天股票知识学习笔记.txt

@ -0,0 +1,61 @@
股票知识复习
股票基础
A 股,全称人民币普通股票,如同寻宝世界里最常见的宝藏线索,是在中国境内注册、上市,以人民币标明面值,供境内投资者用人民币认购和交易的普通股股票。我们日常炒股,大多围绕 A 股展开。在这个市场中,有两类主要 “玩家”。
大股东,如同夺宝团队中的核心成员,手握公司 5% 以上的股票,拥有巨大影响力。他们的买卖行为,就像核心成员的关键决策,直接左右股价走势。比如,当大股东减持股票,就如同核心成员决定放弃部分宝藏,市场会认为公司前景可能不佳,股价往往随之下跌。
而散户,恰似寻宝世界里的小探险家,资金量小,单个操作对股价影响微弱。但我们不能忽视大股东的一举一动,要像关注核心成员动向一样,通过 “股东变动公告”,捕捉股价变化的信号,以此调整自己的投资策略。
交易规则要点速览
在股票交易中,开盘价是每天早上 9 点 30 分开市后的第一笔成交价格,它像清晨的第一缕阳光,透露着早盘投资者的情绪。若开盘价上涨,表明早盘买入意愿强烈,大家对当天行情充满期待;反之,则可能意味着市场情绪谨慎。
收盘价是下午 3 点收盘时的最后一笔成交价格(深市通过集合竞价确定),它是当天交易的终点,也是判断当日行情的重要基准,如同一天冒险结束后的总结,反映了当天市场的最终博弈结果。
涨跌停制度则是市场的 “安全阀”,普通股票每日涨跌幅限制在 10%(ST 股为 5%)。涨停时,股票价格达到当日上限,虽可卖出但难以买入,如同宝藏被暂时封存,难以获取;跌停时,价格降至下限,能买却难卖,仿佛陷入困境。这种限制防止了股价的过度波动,维护了市场的相对稳定。
成交量和成交额是判断行情真假的关键指标。成交量指一天内成交的股票数量,成交额是成交量与股价的乘积。就像寻宝时,不仅要关注找到的宝藏数量,还要考虑其价值。股价上涨时,若成交量未同步放大,如同发现的宝藏看似珍贵却缺乏足够的支撑,可能是 “假涨”;若股价上涨且成交量翻倍,则表明有大量资金涌入,如同众多寻宝者竞相追逐,是行情真实上涨的有力证据。
洞察市场大环境
股票市场如同神秘的寻宝大陆,有着明显的牛熊周期。牛市时,市场长期上涨,投资者信心爆棚,仿佛置身遍地宝藏的乐园,赚钱似乎轻而易举,如 2020 年下半年的市场行情,许多股票价格持续攀升,投资者收获颇丰。
熊市则恰恰相反,市场长期下跌,恐惧笼罩着每一个投资者,大家纷纷担忧财富缩水,就像进入了危机四伏的黑暗森林。以 2018 年为例,股市持续低迷,新手若在熊市高位入场,就如同在危险区域盲目寻宝,极易被深度套牢。
要了解市场整体情况,就需关注关键指数。上证综指反映上海股市的整体表现,深证成指展现深圳股市的全貌。它们如同寻宝地图上的重要地标,通过其涨跌,我们能知晓市场的大致走向。当上证综指上涨 1%,意味着上海市场多数股票上涨;反之,则多数股票下跌,帮助我们把握市场的整体脉搏。
评估股票价值
市盈率(PE)是衡量股票价值的常用指标,计算公式为 “股价 ÷ 每股收益”,简单来说,就是你为获取 1 元利润愿意付出的成本。低市盈率的股票通常被认为价格相对便宜,但不同行业的市盈率存在差异。科技股由于增长潜力大,投资者愿意为其未来收益支付更高价格,市盈率往往高于传统的银行股。因此,在比较市盈率时,需考虑行业特性,不能一概而论。
每股收益(EPS)等于公司总利润除以总股数,代表每一股所获得的利润。这一指标持续增长,表明公司盈利能力不断增强,如同宝藏的价值在不断提升,股价也更有可能上涨,吸引更多投资者关注。
股息率则是(每股分红 ÷ 股价)×100%,反映了股票的分红收益水平。对于追求稳定收益的投资者,如退休长辈,股息率较高的股票颇具吸引力,就像稳定的宝藏产出。银行股、水电燃气股等行业,通常具有较高的股息率,能为投资者提供相对稳定的现金流回报 。
AI 工具:股票投资的夺宝神器
在变幻莫测的股票市场中,我们就如同深入神秘遗迹的夺宝奇兵,每一次决策都关乎着财富的得失。而如今,AI 工具就像是我们手中的神奇罗盘,为我们指引着投资的方向。它能够快速处理海量的数据,精准捕捉市场的细微变化,帮助我们在复杂的股市中做出更明智的决策。接下来,让我们一同深入探索夺宝奇兵中那些强大的 AI 工具,看看它们是如何助力我们在股市中披荆斩棘,斩获财富的。
夺宝利剑:捕捉股票上涨信号
夺宝利剑是一款极具特色的 AI 工具,它依靠 4 根线来精准判断股票的趋势,每根线都肩负着独特的使命,如同寻宝团队中分工明确的成员,协同为我们传递着股票涨跌的重要信息。
天线,作为长期趋势的瞭望者,时刻关注着股票的长期走势。当这根线持续向上攀升时,就如同寻宝地图上一条清晰指向宝藏的路线,表明股票在长期内处于上涨趋势,即便短期内出现些许波动,也无需过度担忧。
飞线主要负责反映股票的中期情况,它如同寻宝过程中对周边环境的探测,关注着公司未来产能的规划以及行业发展的预期。如果飞线向上,说明公司的发展前景乐观,行业预期良好。
中线则聚焦于短期资金的动向,是我们观察近期资金流向的重要窗口。若中线向上,意味着近期有资金持续买入,为股票价格的上涨提供了动力。
流线堪称夺宝利剑的核心,它如同宝藏发出的神秘信号,专门提示股票何时可能出现暴涨行情,是我们捕捉股票启动信号的关键指标。
当 4 根线紧密靠拢,股价波动幅度不超过 3%,且流线率先向上冲刺时,这便是强启动信号,如同宝藏的大门已经缓缓开启,我们应迅速予以关注。此时,多空双方意见高度一致,资金集中涌入,股票极有可能迎来主升浪,开启大幅上涨之旅。
而当只有 3 根线靠在一起,流线尚未向上冲时,这属于弱启动信号,表明虽然长期或中期趋势向好,但还需耐心等待流线也向上运行,才能确认买入时机,以免过早入场导致踏空。
在实战过程中,我们要时刻牢记,只要天线没有向下拐头,就说明股票的长期趋势依然向好,短期的下跌只是暂时的调整,无需惊慌抛售。但如果流线突然向上冲,而飞线和天线却向下,这大概率是一个假信号,就像在寻宝途中遇到的虚假线索,此时应谨慎对待,避免盲目追涨。
以 N 奕材 - U 这只半导体股为例,由于行业景气度高,公司实力强劲,其天线陡峭向上,彰显出长期上涨的趋势。飞线也因公司产能扩张的预期而同步向上。中线则因为股票交易活跃,换手率高达 60% 以上而呈现上升态势。在上市开盘后的 15 分钟内,流线迅速与其他 3 根线汇聚,精准地捕捉到了上市首日股价近 200% 的涨幅,从 10 块左右一路飙升至 30 块,为投资者带来了丰厚的收益。
AI 探牛:辨别股票涨跌真伪
AI 探牛如同一位经验丰富的寻宝导师,凭借独特的判断逻辑,帮助我们分清股票的 “真涨” 与 “假反弹”,避免在投资中误入陷阱。
它主要依靠牵牛绳和 K 线属性这两个关键要素来判断股票的涨跌趋势。牵牛绳就像是我们手中的指南针,红色代表股票处于上涨趋势,绿色则表示下跌趋势,为我们确定了股票走势的大方向。
K 线属性则如同宝藏的不同特征,通过不同的颜色来传递股票的不同状态。红色进攻 K 线表明买入的主力正在发力,如同寻宝者全力挖掘宝藏;蓝色推进 K 线意味着股票稳步上涨,无需过度担忧;黄色防守 K 线则警示我们股票快扛不住下跌的压力,要小心谨慎;青色撤退 K 线更是明确地提醒我们赶紧卖出,股票即将下跌。
为了避免被短期的波动所迷惑,AI 探牛采用了跨周期验证的方法。比如,当某一天股票显示为红线且是进攻 K 线,但从一周的时间跨度来看却是绿线,这很可能只是短期的反弹,此时不宜大量买入。相反,如果当天和一周内都呈现红线且是进攻 K 线,说明大周期对小周期形成了有力的支撑,股票上涨的态势更为稳健。
在判断股票回调时,AI 探牛也有明确的规则。当出现绿线和撤退 K 线时,如果股票跌幅不到 5%,且未跌破一周的趋势线,这通常只是短期的回调,无需匆忙卖出。但如果跌幅超过 8%,且一周趋势线也开始向下拐头,那就必须果断止损,以免遭受更大的损失。
对于成长股而言,由于其波动较大,牵牛绳对股价变化的反应更为灵敏。例如,当股票一天涨幅达到 50% 时,牵牛绳就会迅速从绿色转为红色。而进攻 K 线的确认则更为严格,要求第一天涨幅超过 50%,并且收盘价能站在当天最高涨幅的 80% 以上,以此确保上涨信号的真实性,避免被虚假的上涨所误导。
AI 雷达:寻找股票投资机会
AI 雷达就像是寻宝过程中的探测仪,帮助我们精准寻找股票的 “底部” 和 “加速涨” 的机会,为我们在股市中把握最佳的投资时机。
它主要通过两根线和 K 线形态来进行判断。天轨(蓝色)代表着买的主力能够撑住的价格,如同宝藏上方的一道阻力,股票涨到这个位置可能会受到阻碍;地轨(黄色)则表示卖的主力能压到的价格,是股票的支撑位,当股价跌到这个位置时可能会止跌反弹。
当出现底部启动信号时,就意味着我们可能找到了宝藏的入口,是买入股票的好时机。底部启动需要满足三个条件:一是跌的阴线数量比上一波更多,表明市场的下跌动能在逐渐释放;二是股价跌到了新的低点,显示出市场的恐慌情绪达到一定程度;三是地轨往上走或者天地轨平着,这说明卖的主力力量已经逐渐耗尽。在满足这些条件后,还需要等待两根阳线的出现。第一根是 “试盘阳线”,这是主力在试探市场的买入意愿;第二根 “启动阳线” 则确认了底部的形成,此时我们就可以放心买入。
而当股票处于上涨过程中,如果天轨从平着变为往上走,对应出现的阳线就是 “拉升阳线”,这表明买的主力开始发力,如同寻宝者找到了推动宝藏上升的力量,股票即将进入加速涨阶段,我们应紧紧抓住这个机会,获取更多的收益。
然而,AI 雷达目前还存在一些待完善的地方。例如,在股票跌破地轨后,如何确定止损的标准,是跌幅达到一定比例还是持续下跌一定天数后卖出,还需要进一步明确。在震荡行情中,如何分辨真假信号,比如限定股价下跌的时间以及成交量的阈值等,也需要进一步优化。此外,不同类型的股票具有不同的特性,小盘股周期较短,蓝筹股则需要更多的成交量才能有效,因此如何针对不同股票适配不同的参数,也是未来需要解决的问题。
超级云脑:实现全流程决策
超级云脑堪称散户专属的 “智能军师”,它如同一个智慧的宝库,为我们提供全方位的投资决策支持,帮助我们在股市中实现全流程的精准决策。
超级云脑分为三层结构,每一层都承担着独特的功能。最核心的超级云脑层,运用强大的数据分析能力,精准算出股票的估值、安全等级等关键指标,为我们的投资决策提供坚实的数据基础。
云脑探秘层则以直观的图表形式展示 6 个关键信息,让我们一目了然。在这里,我们可以清晰地了解股票的估值情况,通过对比 PE/PB/EPS 等指标,判断股票是贵了、刚好还是便宜了。例如,如果一只股票的 PE 比行业平均水平低,那就说明它相对便宜,具有一定的投资价值。
安全级别通过 6 种颜色分为 5 级风险,红色代表极高风险,绿色表示非常安全,让我们对投资风险一目了然。压力支撑模块则明确地标出股票 “跌到哪能止跌”(支撑位)、“涨到哪会受阻”(压力位),为我们的买卖操作提供重要参考。
趋势研判帮助我们分清股票的长期(如半年)和短期(如一周)走势是涨是跌,让我们对股票的未来走向有更清晰的认识。庄家成本模块可以让我们了解主力和散户的成本谁低,如果我们的成本比主力还低,那么在投资中就更具优势,安全性更高。
情绪价值则如同市场的温度计,提示我们市场是过于狂热(此时应避免追高)、过于恐慌(不要轻易割肉)还是即将发生方向转变,帮助我们把握市场的情绪变化,做出更明智的决策。通过云脑探秘,我们能够全面了解一只股票,解决 “这股票值不值得买、现在能不能买、该拿着还是卖掉” 的问题。
机构动向层主要用于跟踪主力资金的流向,让我们清楚地知道大资金在做什么。在这里,我们可以看到当日资金的买卖情况,了解主力资金是在买入还是卖出,以及主力是否在偷偷建仓。通过庄散对决模块,我们还能知晓主力和散户谁持有的股票更多。例如,当一只股票显示便宜,同时主力在买入且偷偷建仓时,这就形成了三重利好,是我们重点关注的对象。
在实际操作中,我们可以按照以下流程进行。首先是选股,重点关注那些估值便宜、安全级别高、主力成本低且机构在买入的股票。然后等待买入时机,当股票跌到支撑位,且市场情绪稳定时,果断买入。在持有过程中,密切关注股票的长期趋势是否发生改变,主力是否还在持仓,筹码是否稳定。最后,当股票涨到压力位时,及时止盈;如果市场出现恐慌情绪,股票走势恶化,则果断止损,确保我们的投资收益。

0
吴光慧学习笔记/11.3/test1.txt → 吴光慧学习笔记/11.3/test1.vue

0
吴光慧学习笔记/11.3/test2.txt → 吴光慧学习笔记/11.3/test2.vue

0
吴光慧学习笔记/11.3/test3.txt → 吴光慧学习笔记/11.3/test3.vue

0
吴光慧学习笔记/11.3/test4.txt → 吴光慧学习笔记/11.3/test4.vue

0
吴光慧学习笔记/11.4/props.txt → 吴光慧学习笔记/11.4/props.vue

0
吴光慧学习笔记/11.4/test1.txt → 吴光慧学习笔记/11.4/test1.vue

0
吴光慧学习笔记/11.4/test2.txt → 吴光慧学习笔记/11.4/test2.vue

BIN
吴光慧学习笔记/11.5/11.5学习总结-吴光慧.docx

70
吴光慧学习笔记/11.5/Count.txt

@ -0,0 +1,70 @@
<template>
<div class="count">
<h2>当前求和为:{{ countStore.sum }}</h2>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="add">加</button>
<button @click="minus">减</button>
</div>
</template>
<script setup lang="ts" name="Count">
import { ref,reactive } from "vue";
import {useCountStore} from '@/store/count'
const countStore = useCountStore()
// 以下两种方式都可以拿到state中的数据
// console.log('@@@',countStore.sum)
// console.log('@@@',countStore.$state.sum)
/* let obj = reactive({
a:1,
b:2,
c:ref(3)
})
let x = ref(9)
console.log(obj.a)
console.log(obj.b)
console.log(obj.c) */
// 数据
let n = ref(1) // 用户选择的数字
// 方法
function add(){
//第一种修改方式
// countStore.sum += 1
//第二种修改方式
// countStore.$patch({
// sum:999,
// school:'xxx',
// address:'yyy'
// })
//第三种修改方式
countStore.increment(n.value)
}
function minus(){
countStore.decrement(n.value)
}
</script>
<style scoped>
.count {
background-color: skyblue;
padding: 10px;
border-radius: 10px;
box-shadow: 0 0 10px;
}
select,button {
margin: 0 5px;
height: 25px;
}
</style>

38
吴光慧学习笔记/11.5/LoveTalk.txt

@ -0,0 +1,38 @@
<template>
<div class="talk">
<button @click="getLoveTalk">获取一句土味情话</button>
<ul>
<li v-for="talk in talkList" :key="talk.id">{{talk.title}}</li>
</ul>
</div>
</template>
<script setup lang="ts" name="LoveTalk">
import {reactive} from 'vue'
import axios from "axios";
import {nanoid} from 'nanoid'
// 数据
let talkList = reactive([
{id:'ftrfasdf01',title:'今天你有点怪,哪里怪?怪好看的!'},
{id:'ftrfasdf02',title:'草莓、蓝莓、蔓越莓,今天想我了没?'},
{id:'ftrfasdf03',title:'心里给你留了一块地,我的死心塌地'}
])
// 方法
async function getLoveTalk(){
// 发请求,下面这行的写法是:连续解构赋值+重命名
let {data:{content:title}} = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')
// 把请求回来的字符串,包装成一个对象
let obj = {id:nanoid(),title}
// 放到数组中
talkList.unshift(obj)
}
</script>
<style scoped>
.talk {
background-color: orange;
padding: 10px;
border-radius: 10px;
box-shadow: 0 0 10px;
}
</style>

30
吴光慧学习笔记/11.5/query.txt

@ -0,0 +1,30 @@
Detail
<template>
<ul class="news-list">
<li>编号:{{route.query.id}}</li>
<li>标题:{{route.query.title}}</li>
<li>内容:{{route.query.content}}</li>
</ul>
</template>
<script lang="ts" setup name="Detail">
import {useRoute} from 'vue-router'
const route = useRoute()
const {query} = route
// 这样上面就可以写 <li>内容:{{query.content}}</li>
// 打印query参数
console.log(route.query)
</script>
<style scoped>
.news-list{
list-style: none;
padding-left: 10px;
}
.news-list>li{
line-height: 30px;
}
</style>

2
吴光慧学习笔记/hello_vue3/src/components/About.vue → 吴光慧学习笔记/11.5/备份/About.vue

@ -18,7 +18,7 @@ onUnmounted(()=>{
</script> </script>
<style>
<style scoped>
.about{ .about{
display: flex; display: flex;
justify-content: center; justify-content: center;

12
吴光慧学习笔记/11.5/备份/App.txt

@ -0,0 +1,12 @@
<template>
<Count/>
<br>
<LoveTalk/>
</template>
<script setup lang="ts" name="App">
import Count from './components/Count.vue'
import LoveTalk from './components/LoveTalk.vue'
</script>
<style scoped>
</style>

30
吴光慧学习笔记/11.5/备份/Detail.vue

@ -0,0 +1,30 @@
<template>
<ul class="news-list">
<li>编号:{{id}}</li>
<li>标题:{{title}}</li>
<li>内容:{{content}}</li>
</ul>
</template>
<script lang="ts" setup name="Detail">
// import {useRoute} from 'vue-router'
// const route = useRoute()
// const {query} = route
// // <li>:{{query.content}}</li>
// // query
// console.log(route.query)
defineProps(['id','title','content'])
</script>
<style scoped>
.news-list{
list-style: none;
padding-left: 10px;
}
.news-list>li{
line-height: 30px;
}
</style>

10
吴光慧学习笔记/hello_vue3/src/components/Home.vue → 吴光慧学习笔记/11.5/备份/Home.vue

@ -5,6 +5,16 @@
</template> </template>
<script lang="ts" setup name="Home"> <script lang="ts" setup name="Home">
import { onMounted } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter()
onMounted(()=>{
setTimeout(()=>{
router.push('/news')
},3000)
}
)
</script> </script>

61
吴光慧学习笔记/11.5/备份/News.txt

@ -0,0 +1,61 @@
<template>
<div class="news">
<!--导航区-->
<ul>
<li v-for="news in newsList" :key="news.id">
<!--第一种写法-->
<!-- <RouterLink :to="`/news/detail?id=${news.id}
&title=${news.title}
&content=${news.content}`">{{news.title}}</RouterLink> -->
<!-- 第二种写法 -->
<RouterLink
:to="{
path: '/news/detail',
query: {
id: news.id,
title: news.title,
content: news.content}}">
{{news.title}}
</RouterLink>
</li>
</ul>
<!--内容区-->
<div class="news-content">
<RouterView></RouterView>
</div>
</div>
</template>
<script lang="ts" setup name="News">
import { reactive } from 'vue';
import { RouterLink, RouterView } from 'vue-router';
const newsList = reactive([
{id: 1, title: '新闻1',content: '新闻1的内容'},
{id: 2, title: '新闻2',content: '新闻2的内容'},
{id: 3, title: '新闻3',content: '新闻3的内容'},
{id: 4, title: '新闻4',content: '新闻4的内容'},
])
</script>
<style scoped>
.news {
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
height: 100px;
}
.news ul {
margin-top: 30px;
/* list-style: none; */
padding-left: 10px;
}
.news li>a{
text-decoration: none;
color: #000;
}
</style>

0
吴光慧学习笔记/hello_vue3/src/components/hooks.vue → 吴光慧学习笔记/11.5/备份/hooks.vue

21
吴光慧学习笔记/hello_vue3/src/router/index.ts → 吴光慧学习笔记/11.5/备份/index.ts

@ -2,21 +2,40 @@ import {createRouter,createWebHistory} from 'vue-router'
import Home from '@/components/Home.vue' import Home from '@/components/Home.vue'
import News from '@/components/News.vue' import News from '@/components/News.vue'
import About from '@/components/About.vue' import About from '@/components/About.vue'
import Detail from '@/components/Detail.vue'
const router = createRouter({ const router = createRouter({
history:createWebHistory(), history:createWebHistory(),
routes:[ routes:[
{ {
name:'zhuye',
path:'/home', path:'/home',
component:Home component:Home
}, },
{ {
name:'xinwen',
path:'/news', path:'/news',
component:News
component:News,
children:[
{
name:'xiangqing',
path:'detail/:id/:title/:content',
component:Detail,
props(route){
return route.query
}
}
]
}, },
{ {
name:'guanyu',
path:'/about', path:'/about',
component:About component:About
},
{
path:'/',
redirect:'/home'
} }
] ]
}) })

42
吴光慧学习笔记/11.5/备份/router/index.ts

@ -0,0 +1,42 @@
import {createRouter,createWebHistory} from 'vue-router'
import Home from '@/components/Home.vue'
import News from '@/components/News.vue'
import About from '@/components/About.vue'
import Detail from '@/components/Detail.vue'
const router = createRouter({
history:createWebHistory(),
routes:[
{
name:'zhuye',
path:'/home',
component:Home
},
{
name:'xinwen',
path:'/news',
component:News,
children:[
{
name:'xiangqing',
path:'detail/:id/:title/:content',
component:Detail,
props(route){
return route.query
}
}
]
},
{
name:'guanyu',
path:'/about',
component:About
},
{
path:'/',
redirect:'/home'
}
]
})
export default router

BIN
吴光慧学习笔记/11.5/道氏理论定义及基本观点.docx

4
吴光慧学习笔记/hello_vue3/node_modules/.bin/nanoid

@ -10,7 +10,7 @@ case `uname` in
esac esac
if [ -x "$basedir/node" ]; then if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../nanoid/bin/nanoid.cjs" "$@"
exec "$basedir/node" "$basedir/../nanoid/bin/nanoid.js" "$@"
else else
exec node "$basedir/../nanoid/bin/nanoid.cjs" "$@"
exec node "$basedir/../nanoid/bin/nanoid.js" "$@"
fi fi

2
吴光慧学习笔记/hello_vue3/node_modules/.bin/nanoid.cmd

@ -14,4 +14,4 @@ IF EXIST "%dp0%\node.exe" (
SET PATHEXT=%PATHEXT:;.JS;=;% SET PATHEXT=%PATHEXT:;.JS;=;%
) )
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\nanoid\bin\nanoid.cjs" %*
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\nanoid\bin\nanoid.js" %*

8
吴光慧学习笔记/hello_vue3/node_modules/.bin/nanoid.ps1

@ -11,17 +11,17 @@ $ret=0
if (Test-Path "$basedir/node$exe") { if (Test-Path "$basedir/node$exe") {
# Support pipeline input # Support pipeline input
if ($MyInvocation.ExpectingInput) { if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args
$input | & "$basedir/node$exe" "$basedir/../nanoid/bin/nanoid.js" $args
} else { } else {
& "$basedir/node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args
& "$basedir/node$exe" "$basedir/../nanoid/bin/nanoid.js" $args
} }
$ret=$LASTEXITCODE $ret=$LASTEXITCODE
} else { } else {
# Support pipeline input # Support pipeline input
if ($MyInvocation.ExpectingInput) { if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args
$input | & "node$exe" "$basedir/../nanoid/bin/nanoid.js" $args
} else { } else {
& "node$exe" "$basedir/../nanoid/bin/nanoid.cjs" $args
& "node$exe" "$basedir/../nanoid/bin/nanoid.js" $args
} }
$ret=$LASTEXITCODE $ret=$LASTEXITCODE
} }

121
吴光慧学习笔记/hello_vue3/node_modules/.package-lock.json

@ -764,25 +764,6 @@
"vue": "^3.0.0" "vue": "^3.0.0"
} }
}, },
"node_modules/@vue/devtools-core/node_modules/nanoid": {
"version": "5.1.6",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-5.1.6.tgz",
"integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.js"
},
"engines": {
"node": "^18 || >=20"
}
},
"node_modules/@vue/devtools-kit": { "node_modules/@vue/devtools-kit": {
"version": "8.0.3", "version": "8.0.3",
"resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-8.0.3.tgz", "resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-8.0.3.tgz",
@ -939,9 +920,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.1.tgz",
"integrity": "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
"integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
@ -963,7 +944,6 @@
"version": "2.6.1", "version": "2.6.1",
"resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.6.1.tgz", "resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.6.1.tgz",
"integrity": "sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==", "integrity": "sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"url": "https://github.com/sponsors/antfu" "url": "https://github.com/sponsors/antfu"
@ -1076,7 +1056,6 @@
"version": "4.0.5", "version": "4.0.5",
"resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-4.0.5.tgz", "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-4.0.5.tgz",
"integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"is-what": "^5.2.0" "is-what": "^5.2.0"
@ -1513,7 +1492,6 @@
"version": "5.5.3", "version": "5.5.3",
"resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz", "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/is-docker": { "node_modules/is-docker": {
@ -1555,7 +1533,6 @@
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmmirror.com/is-what/-/is-what-5.5.0.tgz", "resolved": "https://registry.npmmirror.com/is-what/-/is-what-5.5.0.tgz",
"integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18" "node": ">=18"
@ -1702,7 +1679,6 @@
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz", "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/mrmime": { "node_modules/mrmime": {
@ -1730,9 +1706,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz",
"integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@ -1741,10 +1717,10 @@
], ],
"license": "MIT", "license": "MIT",
"bin": { "bin": {
"nanoid": "bin/nanoid.cjs"
"nanoid": "bin/nanoid.js"
}, },
"engines": { "engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
"node": "^18 || >=20"
} }
}, },
"node_modules/node-releases": { "node_modules/node-releases": {
@ -1880,6 +1856,66 @@
"node": ">=0.10" "node": ">=0.10"
} }
}, },
"node_modules/pinia": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.3.tgz",
"integrity": "sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==",
"license": "MIT",
"dependencies": {
"@vue/devtools-api": "^7.7.2"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"typescript": ">=4.4.4",
"vue": "^2.7.0 || ^3.5.11"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/pinia/node_modules/@vue/devtools-api": {
"version": "7.7.7",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.7.tgz",
"integrity": "sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==",
"license": "MIT",
"dependencies": {
"@vue/devtools-kit": "^7.7.7"
}
},
"node_modules/pinia/node_modules/@vue/devtools-kit": {
"version": "7.7.7",
"resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.7.tgz",
"integrity": "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==",
"license": "MIT",
"dependencies": {
"@vue/devtools-shared": "^7.7.7",
"birpc": "^2.3.0",
"hookable": "^5.5.3",
"mitt": "^3.0.1",
"perfect-debounce": "^1.0.0",
"speakingurl": "^14.0.1",
"superjson": "^2.2.2"
}
},
"node_modules/pinia/node_modules/@vue/devtools-shared": {
"version": "7.7.7",
"resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.7.tgz",
"integrity": "sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==",
"license": "MIT",
"dependencies": {
"rfdc": "^1.4.1"
}
},
"node_modules/pinia/node_modules/perfect-debounce": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
"license": "MIT"
},
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.5.6", "version": "8.5.6",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz", "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz",
@ -1908,6 +1944,24 @@
"node": "^10 || ^12 || >=14" "node": "^10 || ^12 || >=14"
} }
}, },
"node_modules/postcss/node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/proxy-from-env": { "node_modules/proxy-from-env": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@ -1932,7 +1986,6 @@
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/rollup": { "node_modules/rollup": {
@ -2072,7 +2125,6 @@
"version": "14.0.1", "version": "14.0.1",
"resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz", "resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz",
"integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
"dev": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
@ -2082,7 +2134,6 @@
"version": "2.2.5", "version": "2.2.5",
"resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.5.tgz", "resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.5.tgz",
"integrity": "sha512-zWPTX96LVsA/eVYnqOM2+ofcdPqdS1dAF1LN4TS2/MWuUpfitd9ctTa87wt4xrYnZnkLtS69xpBdSxVBP5Rm6w==", "integrity": "sha512-zWPTX96LVsA/eVYnqOM2+ofcdPqdS1dAF1LN4TS2/MWuUpfitd9ctTa87wt4xrYnZnkLtS69xpBdSxVBP5Rm6w==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"copy-anything": "^4" "copy-anything": "^4"

31
吴光慧学习笔记/hello_vue3/node_modules/.vite/deps/_metadata.json

@ -1,25 +1,46 @@
{ {
"hash": "547bafd9",
"hash": "39b4f1a2",
"configHash": "e5b55508", "configHash": "e5b55508",
"lockfileHash": "0d539b07",
"browserHash": "2bc9fe4f",
"lockfileHash": "22fdfde4",
"browserHash": "b44b993f",
"optimized": { "optimized": {
"pinia": {
"src": "../../pinia/dist/pinia.mjs",
"file": "pinia.js",
"fileHash": "a97780a2",
"needsInterop": false
},
"vue": { "vue": {
"src": "../../vue/dist/vue.runtime.esm-bundler.js", "src": "../../vue/dist/vue.runtime.esm-bundler.js",
"file": "vue.js", "file": "vue.js",
"fileHash": "5b2b4475",
"fileHash": "1e96b106",
"needsInterop": false "needsInterop": false
}, },
"vue-router": { "vue-router": {
"src": "../../vue-router/dist/vue-router.mjs", "src": "../../vue-router/dist/vue-router.mjs",
"file": "vue-router.js", "file": "vue-router.js",
"fileHash": "832988d5",
"fileHash": "0eced000",
"needsInterop": false
},
"axios": {
"src": "../../axios/index.js",
"file": "axios.js",
"fileHash": "0965a06b",
"needsInterop": false
},
"nanoid": {
"src": "../../nanoid/index.browser.js",
"file": "nanoid.js",
"fileHash": "39507410",
"needsInterop": false "needsInterop": false
} }
}, },
"chunks": { "chunks": {
"chunk-SFGEOVP2": { "chunk-SFGEOVP2": {
"file": "chunk-SFGEOVP2.js" "file": "chunk-SFGEOVP2.js"
},
"chunk-PZ5AY32C": {
"file": "chunk-PZ5AY32C.js"
} }
} }
} }

1
吴光慧学习笔记/hello_vue3/node_modules/.vite/deps/vue.js

@ -169,6 +169,7 @@ import {
withModifiers, withModifiers,
withScopeId withScopeId
} from "./chunk-SFGEOVP2.js"; } from "./chunk-SFGEOVP2.js";
import "./chunk-PZ5AY32C.js";
export { export {
BaseTransition, BaseTransition,
BaseTransitionPropsValidators, BaseTransitionPropsValidators,

16
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/.bin/nanoid

@ -1,16 +0,0 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../nanoid/bin/nanoid.js" "$@"
else
exec node "$basedir/../nanoid/bin/nanoid.js" "$@"
fi

17
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/.bin/nanoid.cmd

@ -1,17 +0,0 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\nanoid\bin\nanoid.js" %*

28
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/.bin/nanoid.ps1

@ -1,28 +0,0 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../nanoid/bin/nanoid.js" $args
} else {
& "$basedir/node$exe" "$basedir/../nanoid/bin/nanoid.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../nanoid/bin/nanoid.js" $args
} else {
& "node$exe" "$basedir/../nanoid/bin/nanoid.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret

20
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/LICENSE

@ -1,20 +0,0 @@
The MIT License (MIT)
Copyright 2017 Andrey Sitnik <andrey@sitnik.ru>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

38
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/README.md

@ -1,38 +0,0 @@
# Nano ID
<img src="https://ai.github.io/nanoid/logo.svg" align="right"
alt="Nano ID logo by Anton Lovchikov" width="180" height="94">
**English** | [日本語](./README.ja.md) | [Русский](./README.ru.md) | [简体中文](./README.zh-CN.md) | [Bahasa Indonesia](./README.id-ID.md) | [한국어](./README.ko.md)
A tiny, secure, URL-friendly, unique string ID generator for JavaScript.
> “An amazing level of senseless perfectionism,
> which is simply impossible not to respect.”
* **Small.** 118 bytes (minified and brotlied). No dependencies.
[Size Limit] controls the size.
* **Safe.** It uses hardware random generator. Can be used in clusters.
* **Short IDs.** It uses a larger alphabet than UUID (`A-Za-z0-9_-`).
So ID size was reduced from 36 to 21 symbols.
* **Portable.** Nano ID was ported
to over [20 programming languages](./README.md#other-programming-languages).
```js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"
```
---
<img src="https://cdn.evilmartians.com/badges/logo-no-label.svg" alt="" width="22" height="16" />  Made at <b><a href="https://evilmartians.com/devtools?utm_source=nanoid&utm_campaign=devtools-button&utm_medium=github">Evil Martians</a></b>, product consulting for <b>developer tools</b>.
---
[online tool]: https://gitpod.io/#https://github.com/ai/nanoid/
[with Babel]: https://developer.epages.com/blog/coding/how-to-transpile-node-modules-with-babel-and-webpack-in-a-monorepo/
[Size Limit]: https://github.com/ai/size-limit
## Docs
Read full docs **[here](https://github.com/ai/nanoid#readme)**.

45
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/bin/nanoid.js

@ -1,45 +0,0 @@
#!/usr/bin/env node
import { customAlphabet, nanoid } from '../index.js'
function print(msg) {
process.stdout.write(msg + '\n')
}
function error(msg) {
process.stderr.write(msg + '\n')
process.exit(1)
}
if (process.argv.includes('--help') || process.argv.includes('-h')) {
print(`Usage
$ nanoid [options]
Options
-s, --size Generated ID size
-a, --alphabet Alphabet to use
-h, --help Show this help
Examples
$ nanoid -s 15
S9sBF77U6sDB8Yg
$ nanoid --size 10 --alphabet abc
bcabababca`)
process.exit()
}
let alphabet, size
for (let i = 2; i < process.argv.length; i++) {
let arg = process.argv[i]
if (arg === '--size' || arg === '-s') {
size = Number(process.argv[i + 1])
i += 1
if (Number.isNaN(size) || size <= 0) {
error('Size must be positive integer')
}
} else if (arg === '--alphabet' || arg === '-a') {
alphabet = process.argv[i + 1]
i += 1
} else {
error('Unknown argument ' + arg)
}
}
if (alphabet) {
let customNanoid = customAlphabet(alphabet, size)
print(customNanoid())
} else {
print(nanoid(size))
}

29
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/index.browser.js

@ -1,29 +0,0 @@
/* @ts-self-types="./index.d.ts" */
import { urlAlphabet as scopedUrlAlphabet } from './url-alphabet/index.js'
export { urlAlphabet } from './url-alphabet/index.js'
export let random = bytes => crypto.getRandomValues(new Uint8Array(bytes))
export let customRandom = (alphabet, defaultSize, getRandom) => {
let mask = (2 << Math.log2(alphabet.length - 1)) - 1
let step = -~((1.6 * mask * defaultSize) / alphabet.length)
return (size = defaultSize) => {
let id = ''
while (true) {
let bytes = getRandom(step)
let j = step | 0
while (j--) {
id += alphabet[bytes[j] & mask] || ''
if (id.length >= size) return id
}
}
}
}
export let customAlphabet = (alphabet, size = 21) =>
customRandom(alphabet, size | 0, random)
export let nanoid = (size = 21) => {
let id = ''
let bytes = crypto.getRandomValues(new Uint8Array((size |= 0)))
while (size--) {
id += scopedUrlAlphabet[bytes[size] & 63]
}
return id
}

106
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/index.d.ts

@ -1,106 +0,0 @@
/**
* A tiny, secure, URL-friendly, unique string ID generator for JavaScript
* with hardware random generator.
*
* ```js
* import { nanoid } from 'nanoid'
* model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"
* ```
*
* @module
*/
/**
* Generate secure URL-friendly unique ID.
*
* By default, the ID will have 21 symbols to have a collision probability
* similar to UUID v4.
*
* ```js
* import { nanoid } from 'nanoid'
* model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
* ```
*
* @param size Size of the ID. The default size is 21.
* @typeparam Type The ID type to replace `string` with some opaque type.
* @returns A random string.
*/
export function nanoid<Type extends string>(size?: number): Type
/**
* Generate secure unique ID with custom alphabet.
*
* Alphabet must contain 256 symbols or less. Otherwise, the generator
* will not be secure.
*
* @param alphabet Alphabet used to generate the ID.
* @param defaultSize Size of the ID. The default size is 21.
* @typeparam Type The ID type to replace `string` with some opaque type.
* @returns A random string generator.
*
* ```js
* const { customAlphabet } = require('nanoid')
* const nanoid = customAlphabet('0123456789абвгдеё', 5)
* nanoid() //=> "8ё56а"
* ```
*/
export function customAlphabet<Type extends string>(
alphabet: string,
defaultSize?: number
): (size?: number) => Type
/**
* Generate unique ID with custom random generator and alphabet.
*
* Alphabet must contain 256 symbols or less. Otherwise, the generator
* will not be secure.
*
* ```js
* import { customRandom } from 'nanoid/format'
*
* const nanoid = customRandom('abcdef', 5, size => {
* const random = []
* for (let i = 0; i < size; i++) {
* random.push(randomByte())
* }
* return random
* })
*
* nanoid() //=> "fbaef"
* ```
*
* @param alphabet Alphabet used to generate a random string.
* @param size Size of the random string.
* @param random A random bytes generator.
* @typeparam Type The ID type to replace `string` with some opaque type.
* @returns A random string generator.
*/
export function customRandom<Type extends string>(
alphabet: string,
size: number,
random: (bytes: number) => Uint8Array
): () => Type
/**
* URL safe symbols.
*
* ```js
* import { urlAlphabet } from 'nanoid'
* const nanoid = customAlphabet(urlAlphabet, 10)
* nanoid() //=> "Uakgb_J5m9"
* ```
*/
export const urlAlphabet: string
/**
* Generate an array of random bytes collected from hardware noise.
*
* ```js
* import { customRandom, random } from 'nanoid'
* const nanoid = customRandom("abcdef", 5, random)
* ```
*
* @param bytes Size of the array.
* @returns An array of random bytes.
*/
export function random(bytes: number): Uint8Array

47
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/index.js

@ -1,47 +0,0 @@
import { webcrypto as crypto } from 'node:crypto'
import { urlAlphabet as scopedUrlAlphabet } from './url-alphabet/index.js'
export { urlAlphabet } from './url-alphabet/index.js'
const POOL_SIZE_MULTIPLIER = 128
let pool, poolOffset
function fillPool(bytes) {
if (!pool || pool.length < bytes) {
pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)
crypto.getRandomValues(pool)
poolOffset = 0
} else if (poolOffset + bytes > pool.length) {
crypto.getRandomValues(pool)
poolOffset = 0
}
poolOffset += bytes
}
export function random(bytes) {
fillPool((bytes |= 0))
return pool.subarray(poolOffset - bytes, poolOffset)
}
export function customRandom(alphabet, defaultSize, getRandom) {
let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)
return (size = defaultSize) => {
if (!size) return ''
let id = ''
while (true) {
let bytes = getRandom(step)
let i = step
while (i--) {
id += alphabet[bytes[i] & mask] || ''
if (id.length >= size) return id
}
}
}
}
export function customAlphabet(alphabet, size = 21) {
return customRandom(alphabet, size, random)
}
export function nanoid(size = 21) {
fillPool((size |= 0))
let id = ''
for (let i = poolOffset - size; i < poolOffset; i++) {
id += scopedUrlAlphabet[pool[i] & 63]
}
return id
}

1
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/nanoid.js

@ -1 +0,0 @@
let a="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";export let nanoid=(e=21)=>{let t="",r=crypto.getRandomValues(new Uint8Array(e));for(let n=0;n<e;n++)t+=a[63&r[n]];return t};

48
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/non-secure/index.d.ts

@ -1,48 +0,0 @@
/**
* By default, Nano ID uses hardware random bytes generation for security
* and low collision probability. If you are not so concerned with security,
* you can use it for environments without hardware random generators.
*
* ```js
* import { nanoid } from 'nanoid/non-secure'
* const id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ"
* ```
*
* @module
*/
/**
* Generate URL-friendly unique ID. This method uses the non-secure
* predictable random generator with bigger collision probability.
*
* ```js
* import { nanoid } from 'nanoid/non-secure'
* model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
* ```
*
* @param size Size of the ID. The default size is 21.
* @typeparam Type The ID type to replace `string` with some opaque type.
* @returns A random string.
*/
export function nanoid<Type extends string>(size?: number): Type
/**
* Generate a unique ID based on a custom alphabet.
* This method uses the non-secure predictable random generator
* with bigger collision probability.
*
* @param alphabet Alphabet used to generate the ID.
* @param defaultSize Size of the ID. The default size is 21.
* @typeparam Type The ID type to replace `string` with some opaque type.
* @returns A random string generator.
*
* ```js
* import { customAlphabet } from 'nanoid/non-secure'
* const nanoid = customAlphabet('0123456789абвгдеё', 5)
* model.id = nanoid() //=> "8ё56а"
* ```
*/
export function customAlphabet<Type extends string>(
alphabet: string,
defaultSize?: number
): (size?: number) => Type

21
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/non-secure/index.js

@ -1,21 +0,0 @@
/* @ts-self-types="./index.d.ts" */
let urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
export let customAlphabet = (alphabet, defaultSize = 21) => {
return (size = defaultSize) => {
let id = ''
let i = size | 0
while (i--) {
id += alphabet[(Math.random() * alphabet.length) | 0]
}
return id
}
}
export let nanoid = (size = 21) => {
let id = ''
let i = size | 0
while (i--) {
id += urlAlphabet[(Math.random() * 64) | 0]
}
return id
}

43
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/package.json

@ -1,43 +0,0 @@
{
"name": "nanoid",
"version": "5.1.6",
"description": "A tiny (118 bytes), secure URL-friendly unique string ID generator",
"keywords": [
"uuid",
"random",
"id",
"url"
],
"type": "module",
"engines": {
"node": "^18 || >=20"
},
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"author": "Andrey Sitnik <andrey@sitnik.ru>",
"license": "MIT",
"repository": "ai/nanoid",
"exports": {
".": {
"types": "./index.d.ts",
"browser": "./index.browser.js",
"react-native": "./index.browser.js",
"default": "./index.js"
},
"./non-secure": "./non-secure/index.js",
"./package.json": "./package.json"
},
"browser": {
"./index.js": "./index.browser.js"
},
"react-native": {
"./index.js": "./index.browser.js"
},
"bin": "./bin/nanoid.js",
"sideEffects": false,
"types": "./index.d.ts"
}

2
吴光慧学习笔记/hello_vue3/node_modules/@vue/devtools-core/node_modules/nanoid/url-alphabet/index.js

@ -1,2 +0,0 @@
export const urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'

17
吴光慧学习笔记/hello_vue3/node_modules/nanoid/README.md

@ -3,37 +3,36 @@
<img src="https://ai.github.io/nanoid/logo.svg" align="right" <img src="https://ai.github.io/nanoid/logo.svg" align="right"
alt="Nano ID logo by Anton Lovchikov" width="180" height="94"> alt="Nano ID logo by Anton Lovchikov" width="180" height="94">
**English** | [Русский](./README.ru.md) | [简体中文](./README.zh-CN.md) | [Bahasa Indonesia](./README.id-ID.md)
**English** | [日本語](./README.ja.md) | [Русский](./README.ru.md) | [简体中文](./README.zh-CN.md) | [Bahasa Indonesia](./README.id-ID.md) | [한국어](./README.ko.md)
A tiny, secure, URL-friendly, unique string ID generator for JavaScript. A tiny, secure, URL-friendly, unique string ID generator for JavaScript.
> “An amazing level of senseless perfectionism, > “An amazing level of senseless perfectionism,
> which is simply impossible not to respect.” > which is simply impossible not to respect.”
* **Small.** 130 bytes (minified and gzipped). No dependencies.
* **Small.** 118 bytes (minified and brotlied). No dependencies.
[Size Limit] controls the size. [Size Limit] controls the size.
* **Fast.** It is 2 times faster than UUID.
* **Safe.** It uses hardware random generator. Can be used in clusters. * **Safe.** It uses hardware random generator. Can be used in clusters.
* **Short IDs.** It uses a larger alphabet than UUID (`A-Za-z0-9_-`). * **Short IDs.** It uses a larger alphabet than UUID (`A-Za-z0-9_-`).
So ID size was reduced from 36 to 21 symbols. So ID size was reduced from 36 to 21 symbols.
* **Portable.** Nano ID was ported * **Portable.** Nano ID was ported
to [20 programming languages](#other-programming-languages).
to over [20 programming languages](./README.md#other-programming-languages).
```js ```js
import { nanoid } from 'nanoid' import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT" model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"
``` ```
Supports modern browsers, IE [with Babel], Node.js and React Native.
---
<img src="https://cdn.evilmartians.com/badges/logo-no-label.svg" alt="" width="22" height="16" />  Made at <b><a href="https://evilmartians.com/devtools?utm_source=nanoid&utm_campaign=devtools-button&utm_medium=github">Evil Martians</a></b>, product consulting for <b>developer tools</b>.
---
[online tool]: https://gitpod.io/#https://github.com/ai/nanoid/ [online tool]: https://gitpod.io/#https://github.com/ai/nanoid/
[with Babel]: https://developer.epages.com/blog/coding/how-to-transpile-node-modules-with-babel-and-webpack-in-a-monorepo/ [with Babel]: https://developer.epages.com/blog/coding/how-to-transpile-node-modules-with-babel-and-webpack-in-a-monorepo/
[Size Limit]: https://github.com/ai/size-limit [Size Limit]: https://github.com/ai/size-limit
<a href="https://evilmartians.com/?utm_source=nanoid">
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg"
alt="Sponsored by Evil Martians" width="236" height="54">
</a>
## Docs ## Docs
Read full docs **[here](https://github.com/ai/nanoid#readme)**. Read full docs **[here](https://github.com/ai/nanoid#readme)**.

69
吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/index.browser.cjs

@ -1,69 +0,0 @@
let random = async bytes => crypto.getRandomValues(new Uint8Array(bytes))
let customAlphabet = (alphabet, defaultSize = 21) => {
// First, a bitmask is necessary to generate the ID. The bitmask makes bytes
// values closer to the alphabet size. The bitmask calculates the closest
// `2^31 - 1` number, which exceeds the alphabet size.
// For example, the bitmask for the alphabet size 30 is 31 (00011111).
// `Math.clz32` is not used, because it is not available in browsers.
let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1
// Though, the bitmask solution is not perfect since the bytes exceeding
// the alphabet size are refused. Therefore, to reliably generate the ID,
// the random bytes redundancy has to be satisfied.
// Note: every hardware random generator call is performance expensive,
// because the system call for entropy collection takes a lot of time.
// So, to avoid additional system calls, extra bytes are requested in advance.
// Next, a step determines how many random bytes to generate.
// The number of random bytes gets decided upon the ID size, mask,
// alphabet size, and magic number 1.6 (using 1.6 peaks at performance
// according to benchmarks).
// `-~f => Math.ceil(f)` if f is a float
// `-~i => i + 1` if i is an integer
let step = -~((1.6 * mask * defaultSize) / alphabet.length)
return async (size = defaultSize) => {
let id = ''
while (true) {
let bytes = crypto.getRandomValues(new Uint8Array(step))
// A compact alternative for `for (var i = 0; i < step; i++)`.
let i = step | 0
while (i--) {
// Adding `|| ''` refuses a random byte that exceeds the alphabet size.
id += alphabet[bytes[i] & mask] || ''
if (id.length === size) return id
}
}
}
}
let nanoid = async (size = 21) => {
let id = ''
let bytes = crypto.getRandomValues(new Uint8Array((size |= 0)))
// A compact alternative for `for (var i = 0; i < step; i++)`.
while (size--) {
// It is incorrect to use bytes exceeding the alphabet size.
// The following mask reduces the random byte in the 0-255 value
// range to the 0-63 value range. Therefore, adding hacks, such
// as empty string fallback or magic numbers, is unneccessary because
// the bitmask trims bytes down to the alphabet size.
let byte = bytes[size] & 63
if (byte < 36) {
// `0-9a-z`
id += byte.toString(36)
} else if (byte < 62) {
// `A-Z`
id += (byte - 26).toString(36).toUpperCase()
} else if (byte < 63) {
id += '_'
} else {
id += '-'
}
}
return id
}
module.exports = { nanoid, customAlphabet, random }

34
吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/index.browser.js

@ -1,34 +0,0 @@
let random = async bytes => crypto.getRandomValues(new Uint8Array(bytes))
let customAlphabet = (alphabet, defaultSize = 21) => {
let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1
let step = -~((1.6 * mask * defaultSize) / alphabet.length)
return async (size = defaultSize) => {
let id = ''
while (true) {
let bytes = crypto.getRandomValues(new Uint8Array(step))
let i = step | 0
while (i--) {
id += alphabet[bytes[i] & mask] || ''
if (id.length === size) return id
}
}
}
}
let nanoid = async (size = 21) => {
let id = ''
let bytes = crypto.getRandomValues(new Uint8Array((size |= 0)))
while (size--) {
let byte = bytes[size] & 63
if (byte < 36) {
id += byte.toString(36)
} else if (byte < 62) {
id += (byte - 26).toString(36).toUpperCase()
} else if (byte < 63) {
id += '_'
} else {
id += '-'
}
}
return id
}
export { nanoid, customAlphabet, random }

71
吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/index.cjs

@ -1,71 +0,0 @@
let crypto = require('crypto')
let { urlAlphabet } = require('../url-alphabet/index.cjs')
// `crypto.randomFill()` is a little faster than `crypto.randomBytes()`,
// because it is possible to use in combination with `Buffer.allocUnsafe()`.
let random = bytes =>
new Promise((resolve, reject) => {
// `Buffer.allocUnsafe()` is faster because it doesn’t flush the memory.
// Memory flushing is unnecessary since the buffer allocation itself resets
// the memory with the new bytes.
crypto.randomFill(Buffer.allocUnsafe(bytes), (err, buf) => {
if (err) {
reject(err)
} else {
resolve(buf)
}
})
})
let customAlphabet = (alphabet, defaultSize = 21) => {
// First, a bitmask is necessary to generate the ID. The bitmask makes bytes
// values closer to the alphabet size. The bitmask calculates the closest
// `2^31 - 1` number, which exceeds the alphabet size.
// For example, the bitmask for the alphabet size 30 is 31 (00011111).
let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
// Though, the bitmask solution is not perfect since the bytes exceeding
// the alphabet size are refused. Therefore, to reliably generate the ID,
// the random bytes redundancy has to be satisfied.
// Note: every hardware random generator call is performance expensive,
// because the system call for entropy collection takes a lot of time.
// So, to avoid additional system calls, extra bytes are requested in advance.
// Next, a step determines how many random bytes to generate.
// The number of random bytes gets decided upon the ID size, mask,
// alphabet size, and magic number 1.6 (using 1.6 peaks at performance
// according to benchmarks).
let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)
let tick = (id, size = defaultSize) =>
random(step).then(bytes => {
// A compact alternative for `for (var i = 0; i < step; i++)`.
let i = step
while (i--) {
// Adding `|| ''` refuses a random byte that exceeds the alphabet size.
id += alphabet[bytes[i] & mask] || ''
if (id.length >= size) return id
}
return tick(id, size)
})
return size => tick('', size)
}
let nanoid = (size = 21) =>
random((size |= 0)).then(bytes => {
let id = ''
// A compact alternative for `for (var i = 0; i < step; i++)`.
while (size--) {
// It is incorrect to use bytes exceeding the alphabet size.
// The following mask reduces the random byte in the 0-255 value
// range to the 0-63 value range. Therefore, adding hacks, such
// as empty string fallback or magic numbers, is unneccessary because
// the bitmask trims bytes down to the alphabet size.
id += urlAlphabet[bytes[size] & 63]
}
return id
})
module.exports = { nanoid, customAlphabet, random }

56
吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/index.d.ts

@ -1,56 +0,0 @@
/**
* Generate secure URL-friendly unique ID. The non-blocking version.
*
* By default, the ID will have 21 symbols to have a collision probability
* similar to UUID v4.
*
* ```js
* import { nanoid } from 'nanoid/async'
* nanoid().then(id => {
* model.id = id
* })
* ```
*
* @param size Size of the ID. The default size is 21.
* @returns A promise with a random string.
*/
export function nanoid(size?: number): Promise<string>
/**
* A low-level function.
* Generate secure unique ID with custom alphabet. The non-blocking version.
*
* Alphabet must contain 256 symbols or less. Otherwise, the generator
* will not be secure.
*
* @param alphabet Alphabet used to generate the ID.
* @param defaultSize Size of the ID. The default size is 21.
* @returns A function that returns a promise with a random string.
*
* ```js
* import { customAlphabet } from 'nanoid/async'
* const nanoid = customAlphabet('0123456789абвгдеё', 5)
* nanoid().then(id => {
* model.id = id //=> "8ё56а"
* })
* ```
*/
export function customAlphabet(
alphabet: string,
defaultSize?: number
): (size?: number) => Promise<string>
/**
* Generate an array of random bytes collected from hardware noise.
*
* ```js
* import { random } from 'nanoid/async'
* random(5).then(bytes => {
* bytes //=> [10, 67, 212, 67, 89]
* })
* ```
*
* @param bytes Size of the array.
* @returns A promise with a random bytes array.
*/
export function random(bytes: number): Promise<Uint8Array>

35
吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/index.js

@ -1,35 +0,0 @@
import crypto from 'crypto'
import { urlAlphabet } from '../url-alphabet/index.js'
let random = bytes =>
new Promise((resolve, reject) => {
crypto.randomFill(Buffer.allocUnsafe(bytes), (err, buf) => {
if (err) {
reject(err)
} else {
resolve(buf)
}
})
})
let customAlphabet = (alphabet, defaultSize = 21) => {
let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)
let tick = (id, size = defaultSize) =>
random(step).then(bytes => {
let i = step
while (i--) {
id += alphabet[bytes[i] & mask] || ''
if (id.length >= size) return id
}
return tick(id, size)
})
return size => tick('', size)
}
let nanoid = (size = 21) =>
random((size |= 0)).then(bytes => {
let id = ''
while (size--) {
id += urlAlphabet[bytes[size] & 63]
}
return id
})
export { nanoid, customAlphabet, random }

26
吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/index.native.js

@ -1,26 +0,0 @@
import { getRandomBytesAsync } from 'expo-random'
import { urlAlphabet } from '../url-alphabet/index.js'
let random = getRandomBytesAsync
let customAlphabet = (alphabet, defaultSize = 21) => {
let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)
let tick = (id, size = defaultSize) =>
random(step).then(bytes => {
let i = step
while (i--) {
id += alphabet[bytes[i] & mask] || ''
if (id.length >= size) return id
}
return tick(id, size)
})
return size => tick('', size)
}
let nanoid = (size = 21) =>
random((size |= 0)).then(bytes => {
let id = ''
while (size--) {
id += urlAlphabet[bytes[size] & 63]
}
return id
})
export { nanoid, customAlphabet, random }

12
吴光慧学习笔记/hello_vue3/node_modules/nanoid/async/package.json

@ -1,12 +0,0 @@
{
"type": "module",
"main": "index.cjs",
"module": "index.js",
"react-native": {
"./index.js": "./index.native.js"
},
"browser": {
"./index.js": "./index.browser.js",
"./index.cjs": "./index.browser.cjs"
}
}

55
吴光慧学习笔记/hello_vue3/node_modules/nanoid/bin/nanoid.cjs

@ -1,55 +0,0 @@
#!/usr/bin/env node
let { nanoid, customAlphabet } = require('..')
function print(msg) {
process.stdout.write(msg + '\n')
}
function error(msg) {
process.stderr.write(msg + '\n')
process.exit(1)
}
if (process.argv.includes('--help') || process.argv.includes('-h')) {
print(`
Usage
$ nanoid [options]
Options
-s, --size Generated ID size
-a, --alphabet Alphabet to use
-h, --help Show this help
Examples
$ nanoid --s 15
S9sBF77U6sDB8Yg
$ nanoid --size 10 --alphabet abc
bcabababca`)
process.exit()
}
let alphabet, size
for (let i = 2; i < process.argv.length; i++) {
let arg = process.argv[i]
if (arg === '--size' || arg === '-s') {
size = Number(process.argv[i + 1])
i += 1
if (Number.isNaN(size) || size <= 0) {
error('Size must be positive integer')
}
} else if (arg === '--alphabet' || arg === '-a') {
alphabet = process.argv[i + 1]
i += 1
} else {
error('Unknown argument ' + arg)
}
}
if (alphabet) {
let customNanoid = customAlphabet(alphabet, size)
print(customNanoid())
} else {
print(nanoid(size))
}

72
吴光慧学习笔记/hello_vue3/node_modules/nanoid/index.browser.cjs

@ -1,72 +0,0 @@
// This file replaces `index.js` in bundlers like webpack or Rollup,
// according to `browser` config in `package.json`.
let { urlAlphabet } = require('./url-alphabet/index.cjs')
let random = bytes => crypto.getRandomValues(new Uint8Array(bytes))
let customRandom = (alphabet, defaultSize, getRandom) => {
// First, a bitmask is necessary to generate the ID. The bitmask makes bytes
// values closer to the alphabet size. The bitmask calculates the closest
// `2^31 - 1` number, which exceeds the alphabet size.
// For example, the bitmask for the alphabet size 30 is 31 (00011111).
// `Math.clz32` is not used, because it is not available in browsers.
let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1
// Though, the bitmask solution is not perfect since the bytes exceeding
// the alphabet size are refused. Therefore, to reliably generate the ID,
// the random bytes redundancy has to be satisfied.
// Note: every hardware random generator call is performance expensive,
// because the system call for entropy collection takes a lot of time.
// So, to avoid additional system calls, extra bytes are requested in advance.
// Next, a step determines how many random bytes to generate.
// The number of random bytes gets decided upon the ID size, mask,
// alphabet size, and magic number 1.6 (using 1.6 peaks at performance
// according to benchmarks).
// `-~f => Math.ceil(f)` if f is a float
// `-~i => i + 1` if i is an integer
let step = -~((1.6 * mask * defaultSize) / alphabet.length)
return (size = defaultSize) => {
let id = ''
while (true) {
let bytes = getRandom(step)
// A compact alternative for `for (var i = 0; i < step; i++)`.
let j = step | 0
while (j--) {
// Adding `|| ''` refuses a random byte that exceeds the alphabet size.
id += alphabet[bytes[j] & mask] || ''
if (id.length === size) return id
}
}
}
}
let customAlphabet = (alphabet, size = 21) =>
customRandom(alphabet, size, random)
let nanoid = (size = 21) =>
crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
// It is incorrect to use bytes exceeding the alphabet size.
// The following mask reduces the random byte in the 0-255 value
// range to the 0-63 value range. Therefore, adding hacks, such
// as empty string fallback or magic numbers, is unneccessary because
// the bitmask trims bytes down to the alphabet size.
byte &= 63
if (byte < 36) {
// `0-9a-z`
id += byte.toString(36)
} else if (byte < 62) {
// `A-Z`
id += (byte - 26).toString(36).toUpperCase()
} else if (byte > 62) {
id += '-'
} else {
id += '_'
}
return id
}, '')
module.exports = { nanoid, customAlphabet, customRandom, urlAlphabet, random }

35
吴光慧学习笔记/hello_vue3/node_modules/nanoid/index.browser.js

@ -1,7 +1,9 @@
import { urlAlphabet } from './url-alphabet/index.js'
let random = bytes => crypto.getRandomValues(new Uint8Array(bytes))
let customRandom = (alphabet, defaultSize, getRandom) => {
let mask = (2 << (Math.log(alphabet.length - 1) / Math.LN2)) - 1
/* @ts-self-types="./index.d.ts" */
import { urlAlphabet as scopedUrlAlphabet } from './url-alphabet/index.js'
export { urlAlphabet } from './url-alphabet/index.js'
export let random = bytes => crypto.getRandomValues(new Uint8Array(bytes))
export let customRandom = (alphabet, defaultSize, getRandom) => {
let mask = (2 << Math.log2(alphabet.length - 1)) - 1
let step = -~((1.6 * mask * defaultSize) / alphabet.length) let step = -~((1.6 * mask * defaultSize) / alphabet.length)
return (size = defaultSize) => { return (size = defaultSize) => {
let id = '' let id = ''
@ -10,25 +12,18 @@ let customRandom = (alphabet, defaultSize, getRandom) => {
let j = step | 0 let j = step | 0
while (j--) { while (j--) {
id += alphabet[bytes[j] & mask] || '' id += alphabet[bytes[j] & mask] || ''
if (id.length === size) return id
if (id.length >= size) return id
} }
} }
} }
} }
let customAlphabet = (alphabet, size = 21) =>
customRandom(alphabet, size, random)
let nanoid = (size = 21) =>
crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
byte &= 63
if (byte < 36) {
id += byte.toString(36)
} else if (byte < 62) {
id += (byte - 26).toString(36).toUpperCase()
} else if (byte > 62) {
id += '-'
} else {
id += '_'
export let customAlphabet = (alphabet, size = 21) =>
customRandom(alphabet, size | 0, random)
export let nanoid = (size = 21) => {
let id = ''
let bytes = crypto.getRandomValues(new Uint8Array((size |= 0)))
while (size--) {
id += scopedUrlAlphabet[bytes[size] & 63]
} }
return id return id
}, '')
export { nanoid, customAlphabet, customRandom, urlAlphabet, random }
}

85
吴光慧学习笔记/hello_vue3/node_modules/nanoid/index.cjs

@ -1,85 +0,0 @@
let crypto = require('crypto')
let { urlAlphabet } = require('./url-alphabet/index.cjs')
// It is best to make fewer, larger requests to the crypto module to
// avoid system call overhead. So, random numbers are generated in a
// pool. The pool is a Buffer that is larger than the initial random
// request size by this multiplier. The pool is enlarged if subsequent
// requests exceed the maximum buffer size.
const POOL_SIZE_MULTIPLIER = 128
let pool, poolOffset
let fillPool = bytes => {
if (!pool || pool.length < bytes) {
pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)
crypto.randomFillSync(pool)
poolOffset = 0
} else if (poolOffset + bytes > pool.length) {
crypto.randomFillSync(pool)
poolOffset = 0
}
poolOffset += bytes
}
let random = bytes => {
// `|=` convert `bytes` to number to prevent `valueOf` abusing and pool pollution
fillPool((bytes |= 0))
return pool.subarray(poolOffset - bytes, poolOffset)
}
let customRandom = (alphabet, defaultSize, getRandom) => {
// First, a bitmask is necessary to generate the ID. The bitmask makes bytes
// values closer to the alphabet size. The bitmask calculates the closest
// `2^31 - 1` number, which exceeds the alphabet size.
// For example, the bitmask for the alphabet size 30 is 31 (00011111).
let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
// Though, the bitmask solution is not perfect since the bytes exceeding
// the alphabet size are refused. Therefore, to reliably generate the ID,
// the random bytes redundancy has to be satisfied.
// Note: every hardware random generator call is performance expensive,
// because the system call for entropy collection takes a lot of time.
// So, to avoid additional system calls, extra bytes are requested in advance.
// Next, a step determines how many random bytes to generate.
// The number of random bytes gets decided upon the ID size, mask,
// alphabet size, and magic number 1.6 (using 1.6 peaks at performance
// according to benchmarks).
let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)
return (size = defaultSize) => {
let id = ''
while (true) {
let bytes = getRandom(step)
// A compact alternative for `for (let i = 0; i < step; i++)`.
let i = step
while (i--) {
// Adding `|| ''` refuses a random byte that exceeds the alphabet size.
id += alphabet[bytes[i] & mask] || ''
if (id.length === size) return id
}
}
}
}
let customAlphabet = (alphabet, size = 21) =>
customRandom(alphabet, size, random)
let nanoid = (size = 21) => {
// `|=` convert `size` to number to prevent `valueOf` abusing and pool pollution
fillPool((size |= 0))
let id = ''
// We are reading directly from the random pool to avoid creating new array
for (let i = poolOffset - size; i < poolOffset; i++) {
// It is incorrect to use bytes exceeding the alphabet size.
// The following mask reduces the random byte in the 0-255 value
// range to the 0-63 value range. Therefore, adding hacks, such
// as empty string fallback or magic numbers, is unneccessary because
// the bitmask trims bytes down to the alphabet size.
id += urlAlphabet[pool[i] & 63]
}
return id
}
module.exports = { nanoid, customAlphabet, customRandom, urlAlphabet, random }

91
吴光慧学习笔记/hello_vue3/node_modules/nanoid/index.d.cts

@ -1,91 +0,0 @@
/**
* Generate secure URL-friendly unique ID.
*
* By default, the ID will have 21 symbols to have a collision probability
* similar to UUID v4.
*
* ```js
* import { nanoid } from 'nanoid'
* model.id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqL"
* ```
*
* @param size Size of the ID. The default size is 21.
* @returns A random string.
*/
export function nanoid(size?: number): string
/**
* Generate secure unique ID with custom alphabet.
*
* Alphabet must contain 256 symbols or less. Otherwise, the generator
* will not be secure.
*
* @param alphabet Alphabet used to generate the ID.
* @param defaultSize Size of the ID. The default size is 21.
* @returns A random string generator.
*
* ```js
* const { customAlphabet } = require('nanoid')
* const nanoid = customAlphabet('0123456789абвгдеё', 5)
* nanoid() //=> "8ё56а"
* ```
*/
export function customAlphabet(
alphabet: string,
defaultSize?: number
): (size?: number) => string
/**
* Generate unique ID with custom random generator and alphabet.
*
* Alphabet must contain 256 symbols or less. Otherwise, the generator
* will not be secure.
*
* ```js
* import { customRandom } from 'nanoid/format'
*
* const nanoid = customRandom('abcdef', 5, size => {
* const random = []
* for (let i = 0; i < size; i++) {
* random.push(randomByte())
* }
* return random
* })
*
* nanoid() //=> "fbaef"
* ```
*
* @param alphabet Alphabet used to generate a random string.
* @param size Size of the random string.
* @param random A random bytes generator.
* @returns A random string generator.
*/
export function customRandom(
alphabet: string,
size: number,
random: (bytes: number) => Uint8Array
): () => string
/**
* URL safe symbols.
*
* ```js
* import { urlAlphabet } from 'nanoid'
* const nanoid = customAlphabet(urlAlphabet, 10)
* nanoid() //=> "Uakgb_J5m9"
* ```
*/
export const urlAlphabet: string
/**
* Generate an array of random bytes collected from hardware noise.
*
* ```js
* import { customRandom, random } from 'nanoid'
* const nanoid = customRandom("abcdef", 5, random)
* ```
*
* @param bytes Size of the array.
* @returns An array of random bytes.
*/
export function random(bytes: number): Uint8Array

25
吴光慧学习笔记/hello_vue3/node_modules/nanoid/index.d.ts

@ -1,4 +1,16 @@
/** /**
* A tiny, secure, URL-friendly, unique string ID generator for JavaScript
* with hardware random generator.
*
* ```js
* import { nanoid } from 'nanoid'
* model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"
* ```
*
* @module
*/
/**
* Generate secure URL-friendly unique ID. * Generate secure URL-friendly unique ID.
* *
* By default, the ID will have 21 symbols to have a collision probability * By default, the ID will have 21 symbols to have a collision probability
@ -10,9 +22,10 @@
* ``` * ```
* *
* @param size Size of the ID. The default size is 21. * @param size Size of the ID. The default size is 21.
* @typeparam Type The ID type to replace `string` with some opaque type.
* @returns A random string. * @returns A random string.
*/ */
export function nanoid(size?: number): string
export function nanoid<Type extends string>(size?: number): Type
/** /**
* Generate secure unique ID with custom alphabet. * Generate secure unique ID with custom alphabet.
@ -22,6 +35,7 @@ export function nanoid(size?: number): string
* *
* @param alphabet Alphabet used to generate the ID. * @param alphabet Alphabet used to generate the ID.
* @param defaultSize Size of the ID. The default size is 21. * @param defaultSize Size of the ID. The default size is 21.
* @typeparam Type The ID type to replace `string` with some opaque type.
* @returns A random string generator. * @returns A random string generator.
* *
* ```js * ```js
@ -30,10 +44,10 @@ export function nanoid(size?: number): string
* nanoid() //=> "8ё56а" * nanoid() //=> "8ё56а"
* ``` * ```
*/ */
export function customAlphabet(
export function customAlphabet<Type extends string>(
alphabet: string, alphabet: string,
defaultSize?: number defaultSize?: number
): (size?: number) => string
): (size?: number) => Type
/** /**
* Generate unique ID with custom random generator and alphabet. * Generate unique ID with custom random generator and alphabet.
@ -58,13 +72,14 @@ export function customAlphabet(
* @param alphabet Alphabet used to generate a random string. * @param alphabet Alphabet used to generate a random string.
* @param size Size of the random string. * @param size Size of the random string.
* @param random A random bytes generator. * @param random A random bytes generator.
* @typeparam Type The ID type to replace `string` with some opaque type.
* @returns A random string generator. * @returns A random string generator.
*/ */
export function customRandom(
export function customRandom<Type extends string>(
alphabet: string, alphabet: string,
size: number, size: number,
random: (bytes: number) => Uint8Array random: (bytes: number) => Uint8Array
): () => string
): () => Type
/** /**
* URL safe symbols. * URL safe symbols.

28
吴光慧学习笔记/hello_vue3/node_modules/nanoid/index.js

@ -1,45 +1,47 @@
import crypto from 'crypto'
import { urlAlphabet } from './url-alphabet/index.js'
import { webcrypto as crypto } from 'node:crypto'
import { urlAlphabet as scopedUrlAlphabet } from './url-alphabet/index.js'
export { urlAlphabet } from './url-alphabet/index.js'
const POOL_SIZE_MULTIPLIER = 128 const POOL_SIZE_MULTIPLIER = 128
let pool, poolOffset let pool, poolOffset
let fillPool = bytes => {
function fillPool(bytes) {
if (!pool || pool.length < bytes) { if (!pool || pool.length < bytes) {
pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER) pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)
crypto.randomFillSync(pool)
crypto.getRandomValues(pool)
poolOffset = 0 poolOffset = 0
} else if (poolOffset + bytes > pool.length) { } else if (poolOffset + bytes > pool.length) {
crypto.randomFillSync(pool)
crypto.getRandomValues(pool)
poolOffset = 0 poolOffset = 0
} }
poolOffset += bytes poolOffset += bytes
} }
let random = bytes => {
export function random(bytes) {
fillPool((bytes |= 0)) fillPool((bytes |= 0))
return pool.subarray(poolOffset - bytes, poolOffset) return pool.subarray(poolOffset - bytes, poolOffset)
} }
let customRandom = (alphabet, defaultSize, getRandom) => {
export function customRandom(alphabet, defaultSize, getRandom) {
let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1 let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length) let step = Math.ceil((1.6 * mask * defaultSize) / alphabet.length)
return (size = defaultSize) => { return (size = defaultSize) => {
if (!size) return ''
let id = '' let id = ''
while (true) { while (true) {
let bytes = getRandom(step) let bytes = getRandom(step)
let i = step let i = step
while (i--) { while (i--) {
id += alphabet[bytes[i] & mask] || '' id += alphabet[bytes[i] & mask] || ''
if (id.length === size) return id
if (id.length >= size) return id
} }
} }
} }
} }
let customAlphabet = (alphabet, size = 21) =>
customRandom(alphabet, size, random)
let nanoid = (size = 21) => {
export function customAlphabet(alphabet, size = 21) {
return customRandom(alphabet, size, random)
}
export function nanoid(size = 21) {
fillPool((size |= 0)) fillPool((size |= 0))
let id = '' let id = ''
for (let i = poolOffset - size; i < poolOffset; i++) { for (let i = poolOffset - size; i < poolOffset; i++) {
id += urlAlphabet[pool[i] & 63]
id += scopedUrlAlphabet[pool[i] & 63]
} }
return id return id
} }
export { nanoid, customAlphabet, customRandom, urlAlphabet, random }

2
吴光慧学习笔记/hello_vue3/node_modules/nanoid/nanoid.js

@ -1 +1 @@
export let nanoid=(t=21)=>crypto.getRandomValues(new Uint8Array(t)).reduce(((t,e)=>t+=(e&=63)<36?e.toString(36):e<62?(e-26).toString(36).toUpperCase():e<63?"_":"-"),"");
let a="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";export let nanoid=(e=21)=>{let t="",r=crypto.getRandomValues(new Uint8Array(e));for(let n=0;n<e;n++)t+=a[63&r[n]];return t};

34
吴光慧学习笔记/hello_vue3/node_modules/nanoid/non-secure/index.cjs

@ -1,34 +0,0 @@
// This alphabet uses `A-Za-z0-9_-` symbols.
// The order of characters is optimized for better gzip and brotli compression.
// References to the same file (works both for gzip and brotli):
// `'use`, `andom`, and `rict'`
// References to the brotli default dictionary:
// `-26T`, `1983`, `40px`, `75px`, `bush`, `jack`, `mind`, `very`, and `wolf`
let urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
let customAlphabet = (alphabet, defaultSize = 21) => {
return (size = defaultSize) => {
let id = ''
// A compact alternative for `for (var i = 0; i < step; i++)`.
let i = size | 0
while (i--) {
// `| 0` is more compact and faster than `Math.floor()`.
id += alphabet[(Math.random() * alphabet.length) | 0]
}
return id
}
}
let nanoid = (size = 21) => {
let id = ''
// A compact alternative for `for (var i = 0; i < step; i++)`.
let i = size | 0
while (i--) {
// `| 0` is more compact and faster than `Math.floor()`.
id += urlAlphabet[(Math.random() * 64) | 0]
}
return id
}
module.exports = { nanoid, customAlphabet }

23
吴光慧学习笔记/hello_vue3/node_modules/nanoid/non-secure/index.d.ts

@ -1,4 +1,17 @@
/** /**
* By default, Nano ID uses hardware random bytes generation for security
* and low collision probability. If you are not so concerned with security,
* you can use it for environments without hardware random generators.
*
* ```js
* import { nanoid } from 'nanoid/non-secure'
* const id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ"
* ```
*
* @module
*/
/**
* Generate URL-friendly unique ID. This method uses the non-secure * Generate URL-friendly unique ID. This method uses the non-secure
* predictable random generator with bigger collision probability. * predictable random generator with bigger collision probability.
* *
@ -8,9 +21,10 @@
* ``` * ```
* *
* @param size Size of the ID. The default size is 21. * @param size Size of the ID. The default size is 21.
* @typeparam Type The ID type to replace `string` with some opaque type.
* @returns A random string. * @returns A random string.
*/ */
export function nanoid(size?: number): string
export function nanoid<Type extends string>(size?: number): Type
/** /**
* Generate a unique ID based on a custom alphabet. * Generate a unique ID based on a custom alphabet.
@ -19,15 +33,16 @@ export function nanoid(size?: number): string
* *
* @param alphabet Alphabet used to generate the ID. * @param alphabet Alphabet used to generate the ID.
* @param defaultSize Size of the ID. The default size is 21. * @param defaultSize Size of the ID. The default size is 21.
* @typeparam Type The ID type to replace `string` with some opaque type.
* @returns A random string generator. * @returns A random string generator.
* *
* ```js * ```js
* import { customAlphabet } from 'nanoid/non-secure' * import { customAlphabet } from 'nanoid/non-secure'
* const nanoid = customAlphabet('0123456789абвгдеё', 5) * const nanoid = customAlphabet('0123456789абвгдеё', 5)
* model.id = //=> "8ё56а"
* model.id = nanoid() //=> "8ё56а"
* ``` * ```
*/ */
export function customAlphabet(
export function customAlphabet<Type extends string>(
alphabet: string, alphabet: string,
defaultSize?: number defaultSize?: number
): (size?: number) => string
): (size?: number) => Type

6
吴光慧学习笔记/hello_vue3/node_modules/nanoid/non-secure/index.js

@ -1,6 +1,7 @@
/* @ts-self-types="./index.d.ts" */
let urlAlphabet = let urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict' 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
let customAlphabet = (alphabet, defaultSize = 21) => {
export let customAlphabet = (alphabet, defaultSize = 21) => {
return (size = defaultSize) => { return (size = defaultSize) => {
let id = '' let id = ''
let i = size | 0 let i = size | 0
@ -10,7 +11,7 @@ let customAlphabet = (alphabet, defaultSize = 21) => {
return id return id
} }
} }
let nanoid = (size = 21) => {
export let nanoid = (size = 21) => {
let id = '' let id = ''
let i = size | 0 let i = size | 0
while (i--) { while (i--) {
@ -18,4 +19,3 @@ let nanoid = (size = 21) => {
} }
return id return id
} }
export { nanoid, customAlphabet }

6
吴光慧学习笔记/hello_vue3/node_modules/nanoid/non-secure/package.json

@ -1,6 +0,0 @@
{
"type": "module",
"main": "index.cjs",
"module": "index.js",
"react-native": "index.js"
}

76
吴光慧学习笔记/hello_vue3/node_modules/nanoid/package.json

@ -1,15 +1,16 @@
{ {
"name": "nanoid", "name": "nanoid",
"version": "3.3.11",
"description": "A tiny (116 bytes), secure URL-friendly unique string ID generator",
"version": "5.1.6",
"description": "A tiny (118 bytes), secure URL-friendly unique string ID generator",
"keywords": [ "keywords": [
"uuid", "uuid",
"random", "random",
"id", "id",
"url" "url"
], ],
"type": "module",
"engines": { "engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
"node": "^18 || >=20"
}, },
"funding": [ "funding": [
{ {
@ -20,70 +21,23 @@
"author": "Andrey Sitnik <andrey@sitnik.ru>", "author": "Andrey Sitnik <andrey@sitnik.ru>",
"license": "MIT", "license": "MIT",
"repository": "ai/nanoid", "repository": "ai/nanoid",
"browser": {
"./index.js": "./index.browser.js",
"./async/index.js": "./async/index.browser.js",
"./async/index.cjs": "./async/index.browser.cjs",
"./index.cjs": "./index.browser.cjs"
},
"react-native": "index.js",
"bin": "./bin/nanoid.cjs",
"sideEffects": false,
"types": "./index.d.ts",
"type": "module",
"main": "index.cjs",
"module": "index.js",
"exports": { "exports": {
".": { ".": {
"react-native": "./index.browser.js",
"browser": "./index.browser.js",
"require": {
"types": "./index.d.cts",
"default": "./index.cjs"
},
"import": {
"types": "./index.d.ts", "types": "./index.d.ts",
"browser": "./index.browser.js",
"react-native": "./index.browser.js",
"default": "./index.js" "default": "./index.js"
}, },
"default": "./index.js"
},
"./package.json": "./package.json",
"./async/package.json": "./async/package.json",
"./async": {
"browser": "./async/index.browser.js",
"require": {
"types": "./index.d.cts",
"default": "./async/index.cjs"
"./non-secure": "./non-secure/index.js",
"./package.json": "./package.json"
}, },
"import": {
"types": "./index.d.ts",
"default": "./async/index.js"
},
"default": "./async/index.js"
},
"./non-secure/package.json": "./non-secure/package.json",
"./non-secure": {
"require": {
"types": "./index.d.cts",
"default": "./non-secure/index.cjs"
},
"import": {
"types": "./index.d.ts",
"default": "./non-secure/index.js"
},
"default": "./non-secure/index.js"
},
"./url-alphabet/package.json": "./url-alphabet/package.json",
"./url-alphabet": {
"require": {
"types": "./index.d.cts",
"default": "./url-alphabet/index.cjs"
"browser": {
"./index.js": "./index.browser.js"
}, },
"import": {
"types": "./index.d.ts",
"default": "./url-alphabet/index.js"
"react-native": {
"./index.js": "./index.browser.js"
}, },
"default": "./url-alphabet/index.js"
}
}
"bin": "./bin/nanoid.js",
"sideEffects": false,
"types": "./index.d.ts"
} }

7
吴光慧学习笔记/hello_vue3/node_modules/nanoid/url-alphabet/index.cjs

@ -1,7 +0,0 @@
// This alphabet uses `A-Za-z0-9_-` symbols.
// The order of characters is optimized for better gzip and brotli compression.
// Same as in non-secure/index.js
let urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
module.exports = { urlAlphabet }

3
吴光慧学习笔记/hello_vue3/node_modules/nanoid/url-alphabet/index.js

@ -1,3 +1,2 @@
let urlAlphabet =
export const urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict' 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
export { urlAlphabet }

6
吴光慧学习笔记/hello_vue3/node_modules/nanoid/url-alphabet/package.json

@ -1,6 +0,0 @@
{
"type": "module",
"main": "index.cjs",
"module": "index.js",
"react-native": "index.js"
}

125
吴光慧学习笔记/hello_vue3/package-lock.json

@ -8,7 +8,9 @@
"name": "hello_vue3", "name": "hello_vue3",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"axios": "^1.13.1",
"axios": "^1.13.2",
"nanoid": "^5.1.6",
"pinia": "^3.0.3",
"vue": "^3.5.22", "vue": "^3.5.22",
"vue-router": "^4.6.3" "vue-router": "^4.6.3"
}, },
@ -1493,25 +1495,6 @@
"vue": "^3.0.0" "vue": "^3.0.0"
} }
}, },
"node_modules/@vue/devtools-core/node_modules/nanoid": {
"version": "5.1.6",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-5.1.6.tgz",
"integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.js"
},
"engines": {
"node": "^18 || >=20"
}
},
"node_modules/@vue/devtools-kit": { "node_modules/@vue/devtools-kit": {
"version": "8.0.3", "version": "8.0.3",
"resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-8.0.3.tgz", "resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-8.0.3.tgz",
@ -1668,9 +1651,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.1.tgz",
"integrity": "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==",
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
"integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
@ -1692,7 +1675,6 @@
"version": "2.6.1", "version": "2.6.1",
"resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.6.1.tgz", "resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.6.1.tgz",
"integrity": "sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==", "integrity": "sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"url": "https://github.com/sponsors/antfu" "url": "https://github.com/sponsors/antfu"
@ -1805,7 +1787,6 @@
"version": "4.0.5", "version": "4.0.5",
"resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-4.0.5.tgz", "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-4.0.5.tgz",
"integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"is-what": "^5.2.0" "is-what": "^5.2.0"
@ -2257,7 +2238,6 @@
"version": "5.5.3", "version": "5.5.3",
"resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz", "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz",
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/is-docker": { "node_modules/is-docker": {
@ -2299,7 +2279,6 @@
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmmirror.com/is-what/-/is-what-5.5.0.tgz", "resolved": "https://registry.npmmirror.com/is-what/-/is-what-5.5.0.tgz",
"integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18" "node": ">=18"
@ -2446,7 +2425,6 @@
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz", "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/mrmime": { "node_modules/mrmime": {
@ -2474,9 +2452,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz",
"integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@ -2485,10 +2463,10 @@
], ],
"license": "MIT", "license": "MIT",
"bin": { "bin": {
"nanoid": "bin/nanoid.cjs"
"nanoid": "bin/nanoid.js"
}, },
"engines": { "engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
"node": "^18 || >=20"
} }
}, },
"node_modules/node-releases": { "node_modules/node-releases": {
@ -2624,6 +2602,66 @@
"node": ">=0.10" "node": ">=0.10"
} }
}, },
"node_modules/pinia": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.3.tgz",
"integrity": "sha512-ttXO/InUULUXkMHpTdp9Fj4hLpD/2AoJdmAbAeW2yu1iy1k+pkFekQXw5VpC0/5p51IOR/jDaDRfRWRnMMsGOA==",
"license": "MIT",
"dependencies": {
"@vue/devtools-api": "^7.7.2"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"typescript": ">=4.4.4",
"vue": "^2.7.0 || ^3.5.11"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/pinia/node_modules/@vue/devtools-api": {
"version": "7.7.7",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.7.tgz",
"integrity": "sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==",
"license": "MIT",
"dependencies": {
"@vue/devtools-kit": "^7.7.7"
}
},
"node_modules/pinia/node_modules/@vue/devtools-kit": {
"version": "7.7.7",
"resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.7.tgz",
"integrity": "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==",
"license": "MIT",
"dependencies": {
"@vue/devtools-shared": "^7.7.7",
"birpc": "^2.3.0",
"hookable": "^5.5.3",
"mitt": "^3.0.1",
"perfect-debounce": "^1.0.0",
"speakingurl": "^14.0.1",
"superjson": "^2.2.2"
}
},
"node_modules/pinia/node_modules/@vue/devtools-shared": {
"version": "7.7.7",
"resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.7.tgz",
"integrity": "sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==",
"license": "MIT",
"dependencies": {
"rfdc": "^1.4.1"
}
},
"node_modules/pinia/node_modules/perfect-debounce": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
"license": "MIT"
},
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.5.6", "version": "8.5.6",
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz", "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz",
@ -2652,6 +2690,24 @@
"node": "^10 || ^12 || >=14" "node": "^10 || ^12 || >=14"
} }
}, },
"node_modules/postcss/node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/proxy-from-env": { "node_modules/proxy-from-env": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@ -2676,7 +2732,6 @@
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz",
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/rollup": { "node_modules/rollup": {
@ -2816,7 +2871,6 @@
"version": "14.0.1", "version": "14.0.1",
"resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz", "resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz",
"integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
"dev": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
@ -2826,7 +2880,6 @@
"version": "2.2.5", "version": "2.2.5",
"resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.5.tgz", "resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.5.tgz",
"integrity": "sha512-zWPTX96LVsA/eVYnqOM2+ofcdPqdS1dAF1LN4TS2/MWuUpfitd9ctTa87wt4xrYnZnkLtS69xpBdSxVBP5Rm6w==", "integrity": "sha512-zWPTX96LVsA/eVYnqOM2+ofcdPqdS1dAF1LN4TS2/MWuUpfitd9ctTa87wt4xrYnZnkLtS69xpBdSxVBP5Rm6w==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"copy-anything": "^4" "copy-anything": "^4"

4
吴光慧学习笔记/hello_vue3/package.json

@ -14,7 +14,9 @@
"type-check": "vue-tsc --build" "type-check": "vue-tsc --build"
}, },
"dependencies": { "dependencies": {
"axios": "^1.13.1",
"axios": "^1.13.2",
"nanoid": "^5.1.6",
"pinia": "^3.0.3",
"vue": "^3.5.22", "vue": "^3.5.22",
"vue-router": "^4.6.3" "vue-router": "^4.6.3"
}, },

71
吴光慧学习笔记/hello_vue3/src/App.vue

@ -1,69 +1,10 @@
<template> <template>
<div class="app">
<h2 class="title">Vue路由测试</h2>
<!-- 导航区 -->
<div class="navigate">
<RouterLink to="/home" active-class="active">首页</RouterLink>
<RouterLink to="/news" active-class="active">新闻</RouterLink>
<RouterLink to="/about" active-class="active">关于</RouterLink>
</div>
<!-- 展示区 -->
<div class="main-content">
<RouterView></RouterView>
</div>
</div>
<Count/>
<br>
<LoveTalk/>
</template> </template>
<script lang="ts" setup name="App">
import { RouterLink, RouterView } from 'vue-router'
<script setup lang="ts" name="App">
import Count from './components/Count.vue'
import LoveTalk from './components/LoveTalk.vue'
</script> </script>
<style>
/* 全局样式重置(可选) */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 页面容器 */
.app {
width: 800px;
margin: 0 auto;
}
/* 标题样式 */
.title {
background-color: #888;
color: #fff;
padding: 10px 0;
text-align: center;
}
/* 导航区样式 */
.navigate {
display: flex;
margin: 20px 0;
}
.navigate a {
padding: 6px 12px;
border-radius: 4px;
text-decoration: none;
margin-right: 10px;
color: #333;
}
/* 激活态样式 */
.navigate a.active {
background-color: #6a994e;
color: #fff;
}
/* 内容展示区样式 */
.main-content {
border: 1px solid #ccc;
min-height: 300px;
padding: 10px;
}
</style>

47
吴光慧学习笔记/hello_vue3/src/components/Count.vue

@ -0,0 +1,47 @@
<template>
<div class="count">
<h2>当前求和为{{ sum }},放大10倍后:{{ bigSum }}</h2>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="add"></button>
<button @click="minus"></button>
</div>
</template>
<script setup lang="ts" name="Count">
import { ref,reactive,toRefs } from "vue";
import {storeToRefs} from 'pinia'
// useCountStore
import {useCountStore} from '@/store/count'
// 使useCountStorecountstore
const countStore = useCountStore()
// storeToRefssotreref
const {sum,bigSum} = storeToRefs(countStore)
// console.log('!!!!!',storeToRefs(countStore))
//
let n = ref(1) //
//
function add(){
countStore.increment(n.value)
}
function minus(){
countStore.sum -= n.value
}
</script>
<style scoped>
.count {
background-color: skyblue;
padding: 10px;
border-radius: 10px;
box-shadow: 0 0 10px;
}
select,button {
margin: 0 5px;
height: 25px;
}
</style>

45
吴光慧学习笔记/hello_vue3/src/components/LoveTalk.vue

@ -0,0 +1,45 @@
<template>
<div class="talk">
<button @click="getLoveTalk">获取一句土味情话</button>
<ul>
<li v-for="talk in talkStore.talkList" :key="talk.id">{{talk.title}}</li>
</ul>
</div>
</template>
<script setup lang="ts" name="LoveTalk">
import {reactive} from 'vue'
import axios from "axios";
import {nanoid} from 'nanoid'
import {useTalkStore} from '@/store/loveTalk'
import { storeToRefs } from "pinia";
const talkStore = useTalkStore()
const {talkList} = storeToRefs(talkStore)
talkStore.$subscribe((mutate,state) => {
console.log('talkStore里面保存的数据发生了变化',mutate,state)
localStorage.setItem('talkList',JSON.stringify(state.talkList))
})
//
async function getLoveTalk(){
talkStore.getATalk()
// +
// let {data:{content:title}} = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')
//
// let obj = {id:nanoid(),title}
//
// talkList.unshift(obj)
}
</script>
<style scoped>
.talk {
background-color: orange;
padding: 10px;
border-radius: 10px;
box-shadow: 0 0 10px;
}
</style>

34
吴光慧学习笔记/hello_vue3/src/components/News.vue

@ -1,34 +0,0 @@
<template>
<div class="news">
<ul>
<li><a href="#">新闻1</a></li>
<li><a href="#">新闻2</a></li>
<li><a href="#">新闻3</a></li>
<li><a href="#">新闻4</a></li>
</ul>
</div>
</template>
<script lang="ts" setup name="News">
</script>
<style>
.news {
padding: 0 20px;
display: flex;
justify-content: space-between;
align-items: center;
height: 100px;
}
.news ul {
margin-top: 30px;
list-style: none;
padding-left: 10px;
}
.news li>a{
text-decoration: none;
color: #000;
}
</style>

48
吴光慧学习笔记/hello_vue3/src/components/Person.vue

@ -1,48 +0,0 @@
<template>
<div class="person">
<h2>当前求和为{{sum}}</h2>
<button @click="add">点我sum+1</button>
<br>
<img v-for="(dog,index) in dogList" :src="dog" :key="index" >
<button @click="getDog">再来一只狗</button>
</div>
</template>
<script lang="ts" setup name="Person">
import { ref,reactive } from 'vue';
import axios from 'axios';
//
let sum = ref(0)
let dogList = reactive([
'https://images.dog.ceo/breeds/pembroke/n02113023_4269.jpg'
])
//
function add(){
sum.value+=1
}
async function getDog(){
try{
let result = await axios.get('https://dog.ceo/api/breeds/image/random')
dogList.push(result.data.message)
}catch(error){
alert(error)
}
}
</script>
<style scoped>
.person{
width: 200px;
height: 200px;
background-color: palegoldenrod;
}
img{
width: 100%;
height: auto;
}
</style>

13
吴光慧学习笔记/hello_vue3/src/main.ts

@ -3,10 +3,17 @@ import './assets/main.css'
import { createApp } from 'vue' import { createApp } from 'vue'
//引入App组件 //引入App组件
import App from './App.vue' import App from './App.vue'
//引入router
import router from './router'
// //引入router
// import router from './router'
/* 引入createPinia,用于创建pinia */
import { createPinia } from 'pinia'
/* 创建pinia */
const pinia = createPinia()
const app = createApp(App) const app = createApp(App)
app.use(router)
//app.use(router)
/* 使用插件 */{}
app.use(pinia)
app.mount('#app') app.mount('#app')

29
吴光慧学习笔记/hello_vue3/src/store/count.ts

@ -0,0 +1,29 @@
import {defineStore} from 'pinia'
export const useCountStore = defineStore('count',{
actions:{
// 定义方法,可以修改state中的数据,响应组件中的“动作”
increment(value: number){
console.log('increment被调用了',value)
//修改数据,响应组件
//this是当前store实例
this.sum += value
},
//减
decrement(value: number){
this.sum -= value
}
},
// 真正存储数据的地方
state(){
return {
sum:6
}
},
getters:{
bigSum(state){
return state.sum * 10
}
}
})

22
吴光慧学习笔记/hello_vue3/src/store/loveTalk.ts

@ -0,0 +1,22 @@
import {defineStore} from 'pinia'
import axios from 'axios'
import {nanoid} from 'nanoid'
export const useTalkStore = defineStore('talk',{
actions:{
async getATalk(){
// 发请求,下面这行的写法是:连续解构赋值+重命名
let {data:{content:title}} = await axios.get('https://api.uomg.com/api/rand.qinghua?format=json')
// 把请求回来的字符串,包装成一个对象
let obj = {id:nanoid(),title}
// 放到数组中
this.talkList.unshift(obj)
}
},
// 真正存储数据的地方
state(){
return {
talkList:JSON.parse(localStorage.getItem('talkList') as string) || []
}
}
})

BIN
尹顺宇学习笔记/尹顺宇11.05作业/尹顺宇11.05AI探牛深入学习.docx

BIN
尹顺宇学习笔记/尹顺宇11.05作业/尹顺宇11.05学习总结.docx

387
尹顺宇学习笔记/尹顺宇11.05作业/尹顺宇11.05学习笔记.md

@ -0,0 +1,387 @@
# SpringBoot+Redis
前瞻:
Reids的Java客户端有
1.Jedis
2.Lettuce
3.Spring Data Redis
我们主要使用Spring Data Redis
## 1.操作步骤:
### 1.1 导入Spring Data Redis 的maven坐标
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
```
### 1.2 配置redis数据源
```
spring:
redis:
host: ${sky.redis.host}
port: ${sky.redis.port}
password: ${sky.redis.password}
database: ${sky.redis.database}
```
```yaml
sky:
redis:
host: localhost
port: 6379
password:
database: 10
```
### 1.3 编写配置类,创建RedisTemplete对象
```java
@Configuration
@Slf4j
public class RedisConfiguration {
@Bean
public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){
log.info("创建RedisTemplate对象...");
RedisTemplate redisTemplate = new RedisTemplate();
//设置redis连接工厂对象
redisTemplate.setConnectionFactory(redisConnectionFactory);
//设置redis的key的序列化器
redisTemplate.setKeySerializer(new StringRedisSerializer());
return redisTemplate;
}
}
```
![1762315033093](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1762315033093.png)
加redis的key的序列化器之前:
![1762315212677](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1762315212677.png)
加redis的key的序列化器之后:
![1762315247579](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1762315247579.png)
### 1.4 通过Redis Template对象操作Redis
```java
@SpringBootTest
public class SpringDataRedisTest {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testRedisTemplate(){
System.out.println(redisTemplate);
//操作字符串类型
ValueOperations valueOperations = redisTemplate.opsForValue();
HashOperations hashOperations = redisTemplate.opsForHash();
ListOperations listOperations = redisTemplate.opsForList();
SetOperations setOperations = redisTemplate.opsForSet();
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
}
//String类型
@Test
public void testString(){
//set get setex setnx
redisTemplate.opsForValue().set("name","小明");
String city = (String) redisTemplate.opsForValue().get("name");
System.out.println(city);
redisTemplate.opsForValue().set("code","1234",3, TimeUnit.MINUTES);
//setIfAbsent就是setnx
redisTemplate.opsForValue().setIfAbsent("lock","1");
redisTemplate.opsForValue().setIfAbsent("lock","2");
}
//Hash类型
@Test
public void testHash(){
//hset hget hdel hkeys hvals
HashOperations hashOperations = redisTemplate.opsForHash();
//hset
hashOperations.put("100","name","yinshunyu");
hashOperations.put("100","age","20");
//get
String name = (String) hashOperations.get("100", "name");
System.out.println(name);
//hkeys
Set keys = hashOperations.keys("100");
System.out.println(keys);
//hvals
List values = hashOperations.values("100");
System.out.println(values);
//hdel
hashOperations.delete("100","age");
}
//List类型
@Test
public void testList(){
//lpush lrange rpop llen
ListOperations listOperations = redisTemplate.opsForList();
listOperations.leftPushAll("mylist","a","b","c");
listOperations.leftPush("mylist","d");
List mylist = listOperations.range("mylist", 0, -1);
System.out.println(mylist);
listOperations.rightPop("mylist");
Long size = listOperations.size("mylist");
System.out.println(size);
}
//Set类型
@Test
public void testSet(){
//sadd smembers scard sinter sunion srem
SetOperations setOperations = redisTemplate.opsForSet();
setOperations.add("set1","a","b","c","d");
setOperations.add("set2","a","b","x","y");
//smembers 获取元素
Set members = setOperations.members("set1");
System.out.println(members);
//scard 元素个数
Long size = setOperations.size("set1");
System.out.println(size);
//sinter 交集
Set intersect = setOperations.intersect("set1", "set2");
System.out.println(intersect);
//sunion 并集
Set union = setOperations.union("set1", "set2");
System.out.println( union);
setOperations.remove("set1","a","b");
}
//ZSet类型
@Test
public void testZset(){
//zadd zrange zincrby zrem
ZSetOperations zSetOperations = redisTemplate.opsForZSet();
zSetOperations.add("zset1","a",10);
zSetOperations.add("zset1","b",12);
zSetOperations.add("zset1","c",9);
Set zset1 = zSetOperations.range("zset1", 0, -1);
System.out.println(zset1);
//zincrby 修改分数
zSetOperations.incrementScore("zset1","c",10);
zSetOperations.remove("zset1","a","b");
}
}
```
![1762315160999](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1762315160999.png)
## 2.缓存菜品模拟
**修改用户端接口 DishController 的 list 方法,加入缓存处理逻辑:**
```java
@Autowired
private RedisTemplate redisTemplate;
/**
* 根据分类id查询菜品
*
* @param categoryId
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result<List<DishVO>> list(Long categoryId) {
//构造redis中的key,规则:dish_分类id
String key = "dish_" + categoryId;
//查询redis中是否存在菜品数据
List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);
if(list != null && list.size() > 0){
//如果存在,直接返回,无须查询数据库
return Result.success(list);
}
////////////////////////////////////////////////////////
Dish dish = new Dish();
dish.setCategoryId(categoryId);
dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品
//如果不存在,查询数据库,将查询到的数据放入redis中
list = dishService.listWithFlavor(dish);
////////////////////////////////////////////////////////
redisTemplate.opsForValue().set(key, list);
return Result.success(list);
}
```
**抽取清理缓存的方法:**
在管理端DishController中添加
```java
@Autowired
private RedisTemplate redisTemplate;
/**
* 清理缓存数据
* @param pattern
*/
private void cleanCache(String pattern){
Set keys = redisTemplate.keys(pattern);
redisTemplate.delete(keys);
}
```
**调用清理缓存的方法,保证数据一致性:**
**1). 新增菜品优化**
```java
/**
* 新增菜品
*
* @param dishDTO
* @return
*/
@PostMapping
@ApiOperation("新增菜品")
public Result save(@RequestBody DishDTO dishDTO) {
log.info("新增菜品:{}", dishDTO);
dishService.saveWithFlavor(dishDTO);
//清理缓存数据
String key = "dish_" + dishDTO.getCategoryId();
cleanCache(key);
return Result.success();
}
```
# EasyExcel初步理解
## 依赖导入
```
<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
```
### 创建与表格对应的实体类
```
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
@ExcelProperty(value = "学生id")
private Integer id;
@ExcelProperty(value = "学生姓名")
private String name;
@ExcelProperty(value = "学生年龄")
private Integer age;
}
```
## 写操作
```
public class WriteExcel {
public static void main(String[] args) {
//准备文件路径
String fileName="D:/destory/test/easyexcel.xls";
//写出文件
EasyExcel.write(fileName, Student.class).sheet("easyexcel")
.doWrite(data());
}
private static List<Student> data(){
ArrayList<Student> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Student student = new Student(i, "董德" + 1, 22 + i);
list.add(student);
}
return list;
}
}
```
## 读操作
### 改造实体类
```
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
@ExcelProperty(value = "学生id",index = 0)
private Integer id;
@ExcelProperty(value = "学生姓名",index = 1)
private String name;
@ExcelProperty(value = "学生年龄",index = 2)
private Integer age;
}
```
### 创建监听器
```
public class EasyExcelLinster extends AnalysisEventListener<Student> {
List<Student> list= new ArrayList<Student>();
//一行一行的去读取里面的数据
@Override
public void invoke(Student student, AnalysisContext analysisContext) {
System.out.println(student);
list.add(student);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
```
### 读取
```
public class ReadExcel {
public static void main(String[] args) {
//准备文件路径
String fileName="D:/destory/test/easyexcel.xls";
EasyExcel.read(fileName, Student.class, new ExcelListener()).sheet().doRead();
}
}
```

BIN
尹顺宇学习笔记/尹顺宇11.05作业/尹顺宇11.05学习笔记.pdf

434
股票知识评测系统.vue

@ -0,0 +1,434 @@
<template>
<div class="exam-system">
<!-- 头部标题 -->
<header class="header">
<div class="logo">
<span class="icon">📋</span>
<span class="title">股票知识评测系统</span>
</div>
<div class="subtitle">全方面评估您股票知识水平还能个性化学习建议</div>
</header>
<div class="main-content">
<!-- 左侧题目区域 -->
<div class="left-panel">
<!-- 题目显示区 -->
<div class="question-area">
<div class="question-header">
<input type="text" v-model="searchText" placeholder="搜索题目..." class="search-input" />
</div>
<div class="question-content">
<h3 class="question-title">{{ currentQuestion.title }}</h3>
<div class="options">
<div
v-for="option in currentQuestion.options"
:key="option.key"
class="option-item"
:class="{ 'selected': selectedAnswer === option.key }"
@click="selectAnswer(option.key)"
>
<span class="radio-btn" :class="{ 'checked': selectedAnswer === option.key }"></span>
<span class="option-label">{{ option.key }}. {{ option.text }}</span>
</div>
</div>
</div>
</div>
<!-- 答题卡预览区 -->
<div class="answer-preview">
<div class="preview-content">
<!-- 可以显示答题进度或其他信息 -->
</div>
</div>
<!-- 底部按钮 -->
<div class="bottom-actions">
<button class="btn btn-secondary" @click="submitExam">提交</button>
<button class="btn btn-primary" @click="previousQuestion"> 上一题</button>
<button class="btn btn-primary" @click="nextQuestion">下一题 </button>
</div>
</div>
<!-- 右侧答题卡 -->
<div class="right-panel">
<div class="answer-card">
<div class="card-header">
<span class="folder-icon">📁</span>
<span class="card-title">试题导航</span>
</div>
<div class="card-grid">
<div
v-for="(item, index) in totalQuestions"
:key="index"
class="grid-item"
:class="getQuestionStatus(index)"
@click="jumpToQuestion(index)"
>
{{ index + 1 }}
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
//
const searchText = ref('')
//
const currentQuestionIndex = ref(0)
//
const userAnswers = ref({})
//
const selectedAnswer = ref('')
//
const totalQuestions = ref(25)
//
const questions = ref([
{
id: 1,
title: '以下哪个不属于股票的基本特征?',
options: [
{ key: 'A', text: '收益性' },
{ key: 'B', text: '风险性' },
{ key: 'C', text: '流动性' },
{ key: 'D', text: '确定性' }
]
},
{
id: 2,
title: '股票市场的主要功能是什么?',
options: [
{ key: 'A', text: '资金融通' },
{ key: 'B', text: '价格发现' },
{ key: 'C', text: '资源配置' },
{ key: 'D', text: '以上都是' }
]
}
// ...
])
//
const currentQuestion = computed(() => {
return questions.value[currentQuestionIndex.value] || questions.value[0]
})
//
const selectAnswer = (answer) => {
selectedAnswer.value = answer
userAnswers.value[currentQuestionIndex.value] = answer
}
//
const previousQuestion = () => {
if (currentQuestionIndex.value > 0) {
currentQuestionIndex.value--
selectedAnswer.value = userAnswers.value[currentQuestionIndex.value] || ''
}
}
//
const nextQuestion = () => {
if (currentQuestionIndex.value < questions.value.length - 1) {
currentQuestionIndex.value++
selectedAnswer.value = userAnswers.value[currentQuestionIndex.value] || ''
}
}
//
const jumpToQuestion = (index) => {
currentQuestionIndex.value = index
selectedAnswer.value = userAnswers.value[index] || ''
}
//
const getQuestionStatus = (index) => {
if (index === currentQuestionIndex.value) {
return 'current'
}
if (userAnswers.value[index]) {
return 'answered'
}
return ''
}
//
const submitExam = () => {
const answeredCount = Object.keys(userAnswers.value).length
if (answeredCount < questions.value.length) {
if (confirm(`您还有 ${questions.value.length - answeredCount} 道题未作答,确定要提交吗?`)) {
//
console.log('提交答案:', userAnswers.value)
}
} else {
//
console.log('提交答案:', userAnswers.value)
}
}
</script>
<style scoped>
.exam-system {
min-height: 100vh;
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
color: #fff;
font-family: 'Microsoft YaHei', Arial, sans-serif;
}
.header {
padding: 20px 40px;
background: rgba(0, 0, 0, 0.2);
}
.logo {
display: flex;
align-items: center;
gap: 10px;
font-size: 24px;
font-weight: bold;
margin-bottom: 8px;
}
.icon {
font-size: 28px;
}
.subtitle {
color: rgba(255, 255, 255, 0.8);
font-size: 14px;
margin-left: 38px;
}
.main-content {
display: flex;
gap: 20px;
padding: 20px 40px;
max-width: 1400px;
margin: 0 auto;
}
.left-panel {
flex: 1;
display: flex;
flex-direction: column;
gap: 20px;
}
.question-area {
background: rgba(20, 40, 80, 0.6);
border: 1px solid rgba(100, 150, 200, 0.3);
border-radius: 8px;
padding: 20px;
}
.question-header {
margin-bottom: 20px;
}
.search-input {
width: 100%;
padding: 10px 15px;
background: rgba(0, 0, 0, 0.3);
border: 1px solid rgba(100, 150, 200, 0.3);
border-radius: 4px;
color: #fff;
font-size: 14px;
}
.search-input::placeholder {
color: rgba(255, 255, 255, 0.4);
}
.question-content {
padding: 20px 0;
}
.question-title {
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
margin-bottom: 20px;
font-weight: normal;
}
.options {
display: flex;
flex-direction: column;
gap: 15px;
}
.option-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 15px;
background: rgba(0, 0, 0, 0.2);
border: 1px solid rgba(100, 150, 200, 0.3);
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
}
.option-item:hover {
background: rgba(100, 150, 200, 0.2);
border-color: rgba(100, 150, 200, 0.5);
}
.option-item.selected {
background: rgba(220, 80, 80, 0.3);
border-color: rgba(220, 80, 80, 0.6);
}
.radio-btn {
width: 18px;
height: 18px;
border: 2px solid rgba(255, 255, 255, 0.5);
border-radius: 50%;
display: inline-block;
position: relative;
flex-shrink: 0;
}
.radio-btn.checked {
border-color: #e74c3c;
background: #e74c3c;
}
.radio-btn.checked::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 8px;
height: 8px;
background: #fff;
border-radius: 50%;
}
.option-label {
font-size: 15px;
}
.answer-preview {
background: rgba(20, 40, 80, 0.6);
border: 1px solid rgba(100, 150, 200, 0.3);
border-radius: 8px;
padding: 20px;
min-height: 150px;
}
.bottom-actions {
display: flex;
gap: 15px;
justify-content: flex-start;
}
.btn {
padding: 12px 30px;
border: none;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
transition: all 0.3s;
font-weight: 500;
}
.btn-primary {
background: rgba(60, 120, 180, 0.8);
color: #fff;
}
.btn-primary:hover {
background: rgba(60, 120, 180, 1);
}
.btn-secondary {
background: rgba(60, 120, 180, 0.8);
color: #fff;
}
.btn-secondary:hover {
background: rgba(70, 130, 190, 1);
}
.right-panel {
width: 280px;
flex-shrink: 0;
}
.answer-card {
background: rgba(20, 40, 80, 0.6);
border: 1px solid rgba(100, 150, 200, 0.3);
border-radius: 8px;
padding: 20px;
}
.card-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 20px;
padding-bottom: 15px;
border-bottom: 1px solid rgba(100, 150, 200, 0.2);
}
.folder-icon {
font-size: 20px;
}
.card-title {
color: #6db3f2;
font-size: 16px;
}
.card-grid {
display: grid;
grid-template-columns: repeat(5, 1fr);
gap: 10px;
}
.grid-item {
aspect-ratio: 1;
display: flex;
align-items: center;
justify-content: center;
background: rgba(60, 120, 180, 0.6);
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
font-size: 14px;
}
.grid-item:hover {
background: rgba(60, 120, 180, 0.8);
transform: scale(1.05);
}
.grid-item.current {
background: #3498db;
box-shadow: 0 0 10px rgba(52, 152, 219, 0.5);
}
.grid-item.answered {
background: rgba(60, 120, 180, 0.8);
}
.grid-item:nth-child(1) {
background: #e74c3c;
}
.grid-item:nth-child(2) {
background: #27ae60;
}
</style>
Loading…
Cancel
Save