---
theme: seriph
background: https://source.unsplash.com/collection/94734566/1920x1080
highlighter: shiki
lineNumbers: true
transition: slide-left
mdc: true
---

# Fast Iot Web

工业互联网前端开源平台模版介绍

---
layout: center
---

# 1. 模版基础

---
layout: image-right
image: /vben.png
backgroundSize: contain
---

# 模版介绍

<a href='https://gitee.com/yudaocode/yudao-ui-admin-vben'>yudao-ui-admin-vben</a> <carbon-direction-straight-right /> <a href='https://github.com/vbenjs/vue-vben-admin'>vue-vben-admin</a>

Vue Vben Admin 是一个免费开源的中后台模版。使用了最新的 vue3、vite4、TypeScript 等主流技术开发,开箱即用的中后台前端解决方案,也可用于学习参考。

- 最新技术栈: 使用 Vue3/vite2 等前端前沿技术开发
- TypeScript: 应用程序级 JavaScript 的语言
- 主题: 可配置的主题
- 国际化: 内置完善的国际化方案
- 权限: 内置完善的动态路由权限生成方案
- 组件: 二次封装了多个常用的组件

<!--
  1. Vben 在 Vue3 刚推出时就出现了,一直迭代至今,目前最新版本是 v2.10.0, 而 yudao-ui-admin-vben fork 了 Vben, 大约是在 v.2.7.0 版本之前,所以目前的模版是基于 Vben 的,但是有一定的差距,其次 Vben 原维护者已经停止维护,目前由社区人员维护,目前有点过重了
-->

---
layout: image-right
image: /fast-iot-web.png
backgroundSize: contain
---

# 模版技术栈

<div><a href='http://223.99.228.240:33000/liukai/fast-iot-web'><carbon:logo-github /> Fast iot web</a></div>

<br/>

- vue@3.3.8 -> 最新 vue@3.4.19
- vite@4.5.1 -> 最新 vite@5.1.4
- ant-design-vue@4.0.8 -> 最新 ant-design-vue@4.1.2
- typescript@5.3.3
- unocss@0.58.3
- @antfu/eslint-config@2.6.2
- node>=18.12.0
- pnpm>=8.10.0

<!--
  1. 目前仓库在 gitea,还没有放在 git 或 gitee 上
  2. vite 为什么不用最新版?后面会提及,这里暂时不介绍,vue、ant-design-vue 不用最新版的原因是 Slot 插槽 TS 类型有问题
  3. 强制 TS 类型安全,在提交时会执行 type:check
  4. 没有 prettier,只需用 Eslint(因为个人原因,antfu 生态)
  5. 这里主要列举了一些核心包,其他包看下 package.json
  6. 目前仓库 git 提交比较混乱,因为改动较大,最后会整合一下 git 提交记录
  7. 强制使用 pnpm,基于 npx only-allow pnpm 这个命令
-->

---
layout: image-right
image: /command.png
backgroundSize: contain
---

# 项目命令

<br />

- dev -> 开发环境
- build -> 构建生产环境
- type:check -> 执行 TS 检查
- lint -> 执行 Eslint 检查
- changelog -> 生成版本日志
- release -> 版本发布

<!-- 
  1. changelog: 基于约定式提交规范生成版本日志 (git 提交记录要更细)
  2. release: 集成了一个第三方库 bumpp ,自动发布版本,包含:修改版本号、执行 changelog 命令、创建版本提交记录、创建 Tag、推送提交记录和 Tag 到 Git 仓库,一般来说发版时直接执行 release 就可以了
  3. 后面有文章介绍这两个命令的集成
  4. 顺便讨论一个 Git 工作流的应用,git rebase + marge(fast forward) 与 git rebase + git merge --squash (/skwɒʃ/)
-->

---
layout: image-right
image: /dir.png
backgroundSize: contain
---

# 项目目录

- /build -> 构建项目代码,例如:vite config、plugin
- /api   -> 后端请求交互

```plain
|-- user
  -- index.ts
  -- types.ts
```

- /views -> 页面

```plain{1,2,3,4}
|-- user
  -- index.vue
  -- data.ts
  -- UserFormModal.vue
  -- ?form.vue
```

<!-- 
  1. 多语言支持,但是没有怎么去使用
  2. css 使用 unocss
  3. 下面的 types 目录是公共的类型
  4. data.ts 用法后面介绍
  5. components 目录下存放的是公共组件(与业务无关),如果是与业务有关的公共组件,可以新建 /views/components
  6. 如果新建、编辑、详情是页面的话,可以增加 form.vue / detail.vue 小写开头的 .vue 文件(或者有更好的命名方式?)
-->

---

# 菜单路由

路由使用的 `BACK` (后端路由模式),移除了 `ROLE` (角色权限) 和 `ROUTE_MAPPING` (路由映射) 两种模式。

新增路由在 系统管理 -> 菜单管理 页面动态增加:

<div flex='~ gap-10px items-center' class='gap-[10px]'>
  <img src='/menu-1.png' class='flex-1 w-0 shadow-lg'/>
  <img src='/menu-2.png' class='flex-1 w-0 shadow-lg'/>
  <img src='/menu-3.png' class='flex-1 w-0 shadow-lg'/>
</div>

<!--
  1. 路由路径和组件路径一般是相同的
  2. 当开启 keep-alive 时,组件名称是必须且唯一
  3. 是否在菜单栏显示,用于添加不再菜单栏展示的页面(如:新增、编辑、详情或其他)
  4. 路由遵从嵌套路由规则
  5. 所有子路由默认都会转为二级路由,所以不能存在二层以上的内嵌路由
-->

---

# 按钮权限

项目中存在三种权限判断方式,分别为:
1. 函数
2. 组件
3. 指令

```ts{1|3-5|7}
<button v-if="hasPermission(codes)">Create</button>

<Authority :value="codes">
  <button>Create</button>
</Authority>

<button v-auth="codes">Create</button>
```

推荐使用函数方式

---
layout: center
---

# 2. 常用组件介绍

---

# BasicTable

```ts{2|3|4,7-11|12-14|5,19-23}
<script setup lang='ts'>
  import { BasicTable, TableAction, useTable } from '@/components/Table'
  import { columns, searchFormSchema } from './data'
  import { getUserList } from '@/api/user'
  import type { SystemUser } from '@/api/user/types'

  const [registerTable, { reload }] = useTable({
    api(params) {
      return getUserList({ ...params, deptId: selectionDept.value })
    },
    columns,
    formConfig: {
      schemas: searchFormSchema,
    },
  })
</script>

<template>
  <BasicTable :api="async () => ([] as SystemUser[])" @register="registerTable">
    <template #bodyCell="{ record }">
      ...
    </template>
  </BasicTable>
</template>
```
<!--
  1. 使用 hooks 方式
  2. useTable 支持泛型,但不用手动传递,会根据 api 的返回值自动推断
  3. Vue 泛型组件不能传递泛型,只能通过 Props 推断,但是我们使用 useTable 时,使用 register 传递的 props,所以就无法推断出来了 (这样可以获取到 slot 泛型支持)
  4. 更多的使用,参考 Vben 和 ant-design Table 文档
-->

---

# BasicForm

```ts{2-3|5-11|15}
<script setup lang='ts'>
  import { BasicForm, useForm } from '@/components/Form'
  import { formSchema } from './data'

  const [registerForm, { setFieldsValue, validate }] = useForm({
    labelWidth: 120,
    baseColProps: { span: 24 },
    schemas: formSchema,
    showActionButtonGroup: false,
    actionColOptions: { span: 23 },
  })
</script>

<template>
 <BasicForm @register="registerForm" />
</template>
```

<!--
  1. 使用 hooks 方式
  2. 目前 useForm 不支持泛型 (之前没加,但是加上最好,谁有兴趣的话可以做一下)
-->

---

# BasicModal

BasicModal 用法使用两个 `Hook` 实现,`useModal` 和 `useModalInner`

useModal

```ts{2,3|5,9|none}
<script setup lang='ts'>
  import { useModal } from '@/components/Modal'
  import UserFormModal from './UserFormModal.vue'

  const [registerModal, { openModal }] = useModal<string>()
</script>

<template>
  <UserFormModal @register="registerModal" />
</template>
```

<!--
  1. useModal 在父组件中使用 (如:user.vue)
  2. useModal 支持泛型,可以约束 openModal 函数调用参数类型
-->

---

# BasicModal

useInnerModal

```ts{2|4-6|10}
<script setup lang='ts'>
  import { BasicModal, useModalInner } from '@/components/Modal'

  const [registerModal] = useModalInner(async (id: string) => {
    ...
  })
</script>

<template>
  <BasicModal v-bind="$attrs" @register="registerModal" />
</template>
```

<br/>

<v-click>

```ts
const [ModalComponent, { openModal }] = useModal(Component)
const { openModal } = useModal(Component)

openModal(state)
```

</v-click>

<!--
  1. $attrs 是必须的,它会将父组件的 register 传递下去
  2. 这种用法怎么样(探讨 Modal 新形势)
-->

---

# Icon
移除了之前的 `<Icon />` 组件,使用 unocss presetIcon 代替, 图标集:<a href='https://icones.js.org/' target='__blank'>Icones</a>

```html
<span class='i-ant-design:edit-outlined'></span>
```

项目集成了 Icones 中所有的图标集,但下面这些会更常用:

- Ant Design Icons
- IonIcons
- Material Design Icons
- Carbon

<br/>

VsCode Plugins:

- UnoCSS
- Iconify IntelliSense

<!--
  1. Icon 是按需引入的(除了 Ant Design Icons)
  2. 项目引入了 Ant Design Icons 所有的图标,用于 IconPicker 组件
  3. 其他的组件查看代码或者 Vben 文档
-->


---
layout: center
---

# 3. 其他

---

# 项目规范

项目使用 git hooks 强制约束代码规范与提交规范:

1. 使用 Eslint,不使用 Prettier

2. 项目用一个简单的正则来约束 CommitLint

```ts
const commitRE
  = /^(revert: )?(feat|fix|docs|style|refactor|perf|test|build|ci|chore|types|wip|release)(\(.+\))?: .{1,50}/
```

3. 移除了 Stylelint

4. 使用 `type:check` 校验 TS 类型正确性 (执行时间会稍微有点长)

---
layout: image-right
image: https://source.unsplash.com/collection/94734565/1920x1080
---

# 开源分享

- [ ] GitHub CICD 流程介绍
- [ ] Git 提交规范与 changelog 生成
- [ ] BasicForm TS 类型优化
- [ ] BasicTable 与 UseTable 泛型支持
- [ ] 更多

<br>
<br>
<br>

<a href='https://www.yuque.com/g/yuqueyonghurkd3lk/lfm6ik/collaborator/join?token=QlhaZiT6IAREiGWC&source=book_collaborator# 邀请你共同编辑知识库《开源知识点总结》' target='__blank'>
  语雀 - 开源知识点总结
</a>

---

# 下一步需要做的

1. 升级 Vue、Ant-design 版本 (等待 ant-design 更新)
2. 解决循序引用问题(复杂度较高)
3. 树形 Table 不支持异步加载
4. BasicTree 组件异步加载不生效(BUG)
5. 重复组件问题(BasicTree / ApiTree)
6. 完善系统管理、新增产品、设备、监控页面
7. 样式调整?

<!--
  1. 目前 Table 异步加载,依靠 onExpand 事件实现
  2. PR 提交,与 review
-->