|
@@ -0,0 +1,879 @@
|
|
|
|
+# 总:架构的结构
|
|
|
|
+
|
|
|
|
+1. [架构的定义和范围](#scope-%E6%9E%B6%E6%9E%84%E7%9A%84%E5%AE%9A%E4%B9%89%E5%92%8C%E8%8C%83%E5%9B%B4)
|
|
|
|
+1. [技术栈](#tech-stack-%E6%8A%80%E6%9C%AF%E6%A0%88)
|
|
|
|
+1. [数据结构](#data-structure-%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84)
|
|
|
|
+1. [服务的接口](#service-%E6%9C%8D%E5%8A%A1%E7%9A%84%E6%8E%A5%E5%8F%A3)
|
|
|
|
+1. [状态管理设计及数据流设计](#state-and-data-flow-%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E8%AE%BE%E8%AE%A1%E5%8F%8A%E6%95%B0%E6%8D%AE%E6%B5%81%E8%AE%BE%E8%AE%A1)
|
|
|
|
+1. [目录结构](#folder-structure-%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84)
|
|
|
|
+1. [核心工具接口](#core-utils-interface-%E6%A0%B8%E5%BF%83%E5%B7%A5%E5%85%B7%E6%8E%A5%E5%8F%A3)
|
|
|
|
+1. 开发规范(api/component/container/css)
|
|
|
|
+1. [前端 URL 规划](#page-urls-%E5%89%8D%E7%AB%AF-url-%E8%A7%84%E5%88%92)
|
|
|
|
+1. [路由、页面划分、子组件、常量](#router-%E8%B7%AF%E7%94%B1%E9%A1%B5%E9%9D%A2%E5%88%92%E5%88%86%E5%B8%B8%E9%87%8F)
|
|
|
|
+1. [环境变量设计](#environment-variables-%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E8%AE%BE%E8%AE%A1)
|
|
|
|
+1. [constants 设计](#constants-constants-%E8%AE%BE%E8%AE%A1)
|
|
|
|
+1. [开发环境设计](#dev-settings-%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E8%AE%BE%E8%AE%A1)
|
|
|
|
+1. [API 处理设计](#api-status-code-api-%E5%A4%84%E7%90%86%E8%AE%BE%E8%AE%A1)
|
|
|
|
+1. [network request: 网络请求设计](#network-request-%E7%BD%91%E7%BB%9C%E8%AF%B7%E6%B1%82%E8%AE%BE%E8%AE%A1)
|
|
|
|
+1. [消息提示处理设计](#notice-handle-%E6%B6%88%E6%81%AF%E6%8F%90%E7%A4%BA%E5%A4%84%E7%90%86%E8%A7%84%E8%8C%83)
|
|
|
|
+1. [错误处理设计](#error-handle-%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86%E8%AE%BE%E8%AE%A1)
|
|
|
|
+1. [样式管理设计](#styles-design-%E6%A0%B7%E5%BC%8F%E7%AE%A1%E7%90%86%E8%AE%BE%E8%AE%A1)
|
|
|
|
+1. 行为统计设计(百度统计)
|
|
|
|
+1. [日志设计(本地加密日志与线上日志)](#logging-%E6%97%A5%E5%BF%97%E8%AE%BE%E8%AE%A1%E6%9C%AC%E5%9C%B0%E5%8A%A0%E5%AF%86%E6%97%A5%E5%BF%97%E4%B8%8E%E7%BA%BF%E4%B8%8A%E6%97%A5%E5%BF%97)
|
|
|
|
+1. 故障诊断设计
|
|
|
|
+1. 弹出层设计
|
|
|
|
+1. 组件复用设计
|
|
|
|
+1. 定时器设计
|
|
|
|
+1. 人脸识别工具设计 (新加)
|
|
|
|
+1. [缓存和 PWA 设计](#cache-and-pwa-%E7%BC%93%E5%AD%98%E7%9A%84%E8%AE%BE%E8%AE%A1)
|
|
|
|
+1. [JS 代码混淆设计](#js-obfuscation-js-%E6%B7%B7%E6%B7%86%E8%AE%BE%E8%AE%A1)
|
|
|
|
+1. Electron / browser 检测与开发运行设计
|
|
|
|
+1. Electron 打包设计
|
|
|
|
+1. websocket 设计
|
|
|
|
+1. 摄像头处理设计
|
|
|
|
+1. 时间同步设计
|
|
|
|
+1. [Layout 设计](#layout-%E8%AE%BE%E8%AE%A1)
|
|
|
|
+1. 限流设计
|
|
|
|
+1. 编辑器设计
|
|
|
|
+1. 防作弊设计
|
|
|
|
+1. [局部技术难点](#tech-challenges-%E5%B1%80%E9%83%A8%E6%8A%80%E6%9C%AF%E9%9A%BE%E7%82%B9)
|
|
|
|
+1. [技术特性验证](#tech-verify-%E6%8A%80%E6%9C%AF%E7%89%B9%E6%80%A7%E9%AA%8C%E8%AF%81)
|
|
|
|
+1. [升级策略](#upgrade-strategy-%E5%8D%87%E7%BA%A7%E7%AD%96%E7%95%A5)
|
|
|
|
+1. [选做功能](#optional-feature-%E9%80%89%E5%81%9A%E5%8A%9F%E8%83%BD)
|
|
|
|
+1. [Others](#others)
|
|
|
|
+
|
|
|
|
+## Scope: 架构的定义和范围
|
|
|
|
+
|
|
|
|
+设计是为了将困难解决在设计阶段,同时为预估工期提高准确度。
|
|
|
|
+
|
|
|
|
+适合有点复杂度,追求高质量的项目。
|
|
|
|
+
|
|
|
|
+设计目标:
|
|
|
|
+
|
|
|
|
+1. 混淆。(可以增强,但是 2 周以后被破解了呢?)动态更新防破解,组合式的手段。
|
|
|
|
+2. 可维护性。变高。
|
|
|
|
+3. 遗留问题,得到处理。
|
|
|
|
+4. 体验优化。提升速度,消灭页面瑕疵。
|
|
|
|
+5. 扩展性增强。
|
|
|
|
+
|
|
|
|
+为保证设计不快速过时,设计文档仅记录不太变动的核心数据结构和流程,部分重要细节。
|
|
|
|
+某些部分记录下来,也仅仅是为了帮助初次开发,后期如果过时了,可以写明已过时不再维护了。
|
|
|
|
+
|
|
|
|
+组件设计;仅为辅助设计的脚手架,后续不维护?
|
|
|
|
+开发环境设计(基础设施、文件目录、readme):不是设计的核心内容,确实将设计实现的重要入口
|
|
|
|
+
|
|
|
|
+## Tech stack: 技术栈
|
|
|
|
+
|
|
|
|
+预计采用的技术栈和工具链如下
|
|
|
|
+
|
|
|
|
+1. Vue 3.2
|
|
|
|
+1. and-design-vue 3.x or naiveUI
|
|
|
|
+1. pinia 2
|
|
|
|
+1. vue router 4.x
|
|
|
|
+1. typescript 4.5
|
|
|
|
+1. eslint 8
|
|
|
|
+1. prettier 2
|
|
|
|
+1. vite 2.x
|
|
|
|
+1. javascript-obfuscator 2
|
|
|
|
+
|
|
|
|
+## Data structure: 数据结构
|
|
|
|
+
|
|
|
|
+```ts
|
|
|
|
+// 详见:student-client.d.ts
|
|
|
|
+type Store = {
|
|
|
|
+ /** 当前用户 */
|
|
|
|
+ user: {
|
|
|
|
+ id: number;
|
|
|
|
+ /** 身份证号 */
|
|
|
|
+ identityNumber: string;
|
|
|
|
+ /** 学号 */
|
|
|
|
+ studentCodeList: string[];
|
|
|
|
+ // ...
|
|
|
|
+ }
|
|
|
|
+ // ...
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/** 得到当前客户端版本 1.9.* */
|
|
|
|
+type GetCurrentClientVersion = () => string;
|
|
|
|
+type IsSupportedClientVersion = () => boolean;
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+## Service: 服务的接口
|
|
|
|
+
|
|
|
|
+写明层级的目标,设计层级的协调功能(接口)。
|
|
|
|
+
|
|
|
|
+tools layer: 工具类,可以脱离项目的函数
|
|
|
|
+api layer: 通信类,处理和服务端数据的交互
|
|
|
|
+service layer: 核心服务类,处理项目的生命周期
|
|
|
|
+data binding layer: 提供给 UI 展示的类
|
|
|
|
+user event handler layer: 提供处理用户触发事件的类
|
|
|
|
+
|
|
|
|
+## State and data flow: 状态管理设计及数据流设计
|
|
|
|
+
|
|
|
|
+单向数据流与复式记账法的比较。
|
|
|
|
+
|
|
|
|
+数据的处理原则要遵循以下原则:
|
|
|
|
+
|
|
|
|
+1. 集中统一
|
|
|
|
+1. 命名清晰
|
|
|
|
+1. 类型与内容一致
|
|
|
|
+1. 不包含重复数据
|
|
|
|
+1. 上层清理数据,比如网络获取 JSON,里面的数据类型不对,要清理以后交给下层
|
|
|
|
+
|
|
|
|
+组件的分类(适合复杂业务):
|
|
|
|
+
|
|
|
|
+1. container component: fetch data
|
|
|
|
+1. presentational component: display data
|
|
|
|
+
|
|
|
|
+### 以下待整理
|
|
|
|
+
|
|
|
|
+不涉及到 store 的状态,直接通过 api 请求,当做 component state 来使用。
|
|
|
|
+好处:减少状态共享。
|
|
|
|
+
|
|
|
|
+当一个状态被创建出,要明确它的 owner/scope/lifecycle,以及可能的值。
|
|
|
|
+当一个状态被使用时,要明确它可能的值,做好防御性编程。
|
|
|
|
+
|
|
|
|
+vue component wrapper. wrapper 里面放权限之类的异步获取数据。comp 里面放业务逻辑和同步的 props。
|
|
|
|
+或者用 vue router 的 before guard
|
|
|
|
+
|
|
|
|
+疑问:究竟是在 action 里面还是 container 里面请求数据?依据是什么?
|
|
|
|
+
|
|
|
|
+store actions -> state/storage -> page
|
|
|
|
+state: page refresh? => sessionStorage (退出登录后要清除部分字段)
|
|
|
|
+
|
|
|
|
+错误要直达页面元素呢?-> action return data
|
|
|
|
+好处:页面清爽;数据集中处理
|
|
|
|
+数据的共享与过期
|
|
|
|
+
|
|
|
|
+page 上的数据满足以下几点:
|
|
|
|
+1、对数据仅仅做展示
|
|
|
|
+2、数据输入来源为
|
|
|
|
+URL(path & query)
|
|
|
|
+上个页面传递过来的数据(为保证刷新可用,最好通过 URL 做简单的数据传递)
|
|
|
|
+本地存储的数据(一般不是和页面主动关联,是通过 URL 或其他事件导致要取本地存储)
|
|
|
|
+组件生命周期
|
|
|
|
+用户输入
|
|
|
|
+原生事件(网络)
|
|
|
|
+
|
|
|
|
+## Folder structure: 目录结构
|
|
|
|
+
|
|
|
|
+文件名/文件夹 组织模块用
|
|
|
|
+
|
|
|
|
+强联系的文件放在一起
|
|
|
|
+文件名有区分度,不要过分依赖文件路径名。否则会出现很多像是 index.js 这样的文件。
|
|
|
|
+文件影响范围:不超出文件夹最好,image 或 package private
|
|
|
|
+
|
|
|
|
+```sh
|
|
|
|
+.
|
|
|
|
+├── README.md
|
|
|
|
+├── index.html
|
|
|
|
+├── package.json
|
|
|
|
+├── postcss.config.js
|
|
|
|
+├── prebuild.mjs
|
|
|
|
+├── prettier.config.js
|
|
|
|
+├── public
|
|
|
|
+│ └── favicon.ico
|
|
|
|
+├── src
|
|
|
|
+│ ├── App.vue
|
|
|
|
+│ ├── api
|
|
|
|
+│ │ ├── loginPage.ts # api 请求
|
|
|
|
+│ ├── assets
|
|
|
|
+│ │ └── logo.png
|
|
|
|
+│ ├── components # 页面其中的组件,可能复用
|
|
|
|
+│ │ ├── PageError404.vue
|
|
|
|
+│ │ ├── QmButton.vue
|
|
|
|
+│ │ ├── QmDialog.vue
|
|
|
|
+│ ├── constants
|
|
|
|
+│ │ └── constants.ts # 项目中的常量。url, name, code,
|
|
|
|
+│ ├── devLogin.ts # 开发模式下自动登录
|
|
|
|
+│ ├── devLoginParams.ts
|
|
|
|
+│ ├── env.d.ts
|
|
|
|
+│ ├── features
|
|
|
|
+│ │ ├── Login
|
|
|
|
+│ │ │ ├── Login.vue
|
|
|
|
+│ │ │ ├── images
|
|
|
|
+│ │ │ │ └── bg.png
|
|
|
|
+│ │ │ └── use
|
|
|
|
+│ │ │ └── \*.ts # 抽象页面的业务逻辑
|
|
|
|
+│ ├── filters
|
|
|
|
+│ │ └── index.ts
|
|
|
|
+│ ├── main.ts
|
|
|
|
+│ ├── plugins
|
|
|
|
+│ │ ├── axiosApp.ts
|
|
|
|
+│ │ ├── axiosIndex.ts
|
|
|
|
+│ │ ├── axiosNoAuth.ts
|
|
|
|
+│ │ ├── axiosNotice.ts
|
|
|
|
+│ │ └── eventBus.ts
|
|
|
|
+│ ├── router
|
|
|
|
+│ │ └── index.ts
|
|
|
|
+│ ├── setups
|
|
|
|
+│ │ └── useTimers.ts
|
|
|
|
+│ ├── store
|
|
|
|
+│ │ └── store.ts
|
|
|
|
+│ ├── styles
|
|
|
|
+│ │ ├── cssvar.css
|
|
|
|
+│ │ ├── global.css
|
|
|
|
+│ │ ├── nprogress.css
|
|
|
|
+│ │ └── tailwind.css
|
|
|
|
+│ ├── types
|
|
|
|
+│ │ ├── 3rd.d.ts
|
|
|
|
+│ │ ├── global.d.ts
|
|
|
|
+│ │ ├── index.ts
|
|
|
|
+│ │ └── student-client.d.ts
|
|
|
|
+│ └── utils
|
|
|
|
+│ ├── renderJSON.ts
|
|
|
|
+│ ├── ua.ts
|
|
|
|
+│ └── utils.ts
|
|
|
|
+├── tailwind.config.js
|
|
|
|
+├── tsconfig.json
|
|
|
|
+└── vite.config.ts
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+## Environment Variables: 环境变量设计
|
|
|
|
+
|
|
|
|
+PORTABLE_EXECUTABLE_FILE:electron 添加,运行时获取可执行文件的路径
|
|
|
|
+
|
|
|
|
+VUE_APP_SKIP_CHECK_NATIVE:允许本地通过 web 来访问学生端服务
|
|
|
|
+
|
|
|
|
+VUE_APP_CORE_HOST_URL:本地开发时,后台服务器的地址
|
|
|
|
+
|
|
|
|
+VUE_APP_SLS_STORE_NAME:阿里云日志服务地址
|
|
|
|
+
|
|
|
|
+VUE_APP_CONFIG_FILE_SEVER_URL=https://ecs-static.qmth.com.cn
|
|
|
|
+
|
|
|
|
+VUE_APP_GIT_REPO_VERSION=TO_BE_OVERRIDED # 显示版本号
|
|
|
|
+
|
|
|
|
+## Constants: constants 设计
|
|
|
|
+
|
|
|
|
+```ts
|
|
|
|
+export const REMOTE_APPS = [
|
|
|
|
+ ["qq", "QQ"],
|
|
|
|
+ ["teamviewer", "TeamViewer"],
|
|
|
|
+ ["lookmypc", "LookMyPC"],
|
|
|
|
+ ["xt", "协通"],
|
|
|
|
+ ["winaw32", "Symantec PCAnywhere"],
|
|
|
|
+ ["pcaquickconnect", "Symantec PCAnywhere"],
|
|
|
|
+ ["sessioncontroller", "Symantec PCAnywhere"],
|
|
|
|
+ [/sunloginclient/gi, "向日葵"],
|
|
|
|
+ [/sunloginremote/gi, "向日葵"],
|
|
|
|
+ [/选择免安装运行,截图识别/gi, "向日葵"],
|
|
|
|
+ ["wemeetapp", "腾讯会议"],
|
|
|
|
+ ["wechat", "微信"],
|
|
|
|
+] as const;
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+## API status code: API 处理设计
|
|
|
|
+
|
|
|
|
+api 的 statusCode:
|
|
|
|
+
|
|
|
|
+1. 200:正常
|
|
|
|
+1. 401:无权限
|
|
|
|
+1. 403:无权限
|
|
|
|
+1. 503:后台限流,要求重试
|
|
|
|
+
|
|
|
|
+api 请求是否显示错误:
|
|
|
|
+
|
|
|
|
+noErrorMessage: boolean (某些情况下希望网络请求静默处理)
|
|
|
|
+
|
|
|
|
+当 statusCode 为非正常时,优先显示 desc 字段,如果没有,则显示“未定义异常:......”
|
|
|
|
+
|
|
|
|
+“websocket 重连失败” => "服务器连接失败(websocket)"
|
|
|
|
+
|
|
|
|
+## network request: 网络请求设计
|
|
|
|
+
|
|
|
|
+网络请求可以限流、重试、取消。
|
|
|
|
+
|
|
|
|
+### 给进行中的网络请求覆盖全局的遮罩层
|
|
|
|
+
|
|
|
|
+网络请求可设置遮罩层,防止请求过程中用户的误操作、重复操作等等。有 mask,拒绝键盘事件。
|
|
|
|
+
|
|
|
|
+```
|
|
|
|
+globalMaskCount === 0 ====> no mask
|
|
|
|
+log: inc/dec globalMaskCount, reason
|
|
|
|
+```
|
|
|
|
+
|
|
|
|
+loading / error 状态不进 store
|
|
|
|
+
|
|
|
|
+但是可以通过请求的状态机来处理?
|
|
|
|
+
|
|
|
|
+### network reactive design(待细化)
|
|
|
|
+
|
|
|
|
+const { data, isLoading, isFinished, error } = useAxios('/api/posts')
|
|
|
|
+好处/难处:
|
|
|
|
+
|
|
|
|
+1. v-loading="isLoading"
|
|
|
|
+2. data 模板中直接用?因为有 loading 开关
|
|
|
|
+3. 请求有依赖?不好搞?
|
|
|
|
+4. 错误处理不好搞?
|
|
|
|
+5. 重复请求?
|
|
|
|
+
|
|
|
|
+network loading state from api
|
|
|
|
+and reactive?
|
|
|
|
+
|
|
|
|
+get reactive network result?
|
|
|
|
+
|
|
|
|
+form inputs / confirm / throttle? / error => network params => res/loading => display result
|
|
|
|
+多个 loading 状态转换?
|
|
|
|
+
|
|
|
|
+## Error handle: 错误处理设计
|
|
|
|
+
|
|
|
|
+错误的边界是用户,无论怎么处理,错误的不可避免的,一定要通知到用户,或不给用户错误的结果(先成功后失败)。
|
|
|
|
+
|
|
|
|
+错误分为两种,一种是给用户看的错误,一种是给程序排错或恢复的错误。
|
|
|
|
+错误应该抛出 Error 对象,不能 throw 字符串等类型。
|
|
|
|
+
|
|
|
|
+### 用户查看类错误
|
|
|
|
+
|
|
|
|
+1. 错误以弹窗形式提醒用户。
|
|
|
|
+1. 错误信息应有识别度,方便用户反馈。
|
|
|
|
+1. 错误应隐藏敏感的技术信息,比如使用的技术种类。
|
|
|
|
+1. 重试时应该不报错,默默重试,但要记日志。
|
|
|
|
+
|
|
|
|
+### 程序排错类错误包括:
|
|
|
|
+
|
|
|
|
+1. JS 错误,需预警,保证及时处理
|
|
|
|
+1. 网络错误,记日志
|
|
|
|
+1. 环境错误,提示用户,记日志
|
|
|
|
+1. 兜底的错误记录
|
|
|
|
+
|
|
|
|
+### 网络的错误处理:
|
|
|
|
+
|
|
|
|
+1. 补充后台的错误码。如果后台没有统一的,则只能模糊处理。
|
|
|
|
+2. 未知错误(待讨论):a、显示错误的详细信息 b、错误监控 c、不显示详细信息(不能定位错误)
|
|
|
|
+
|
|
|
|
+### 潜在错误位置
|
|
|
|
+
|
|
|
|
+1. 在 vue 组件中,某些方法可能会在 vue 组件被销毁后执行。
|
|
|
|
+1. 错误内部处理被特殊压制?定制错误处理,axios config ?
|
|
|
|
+1. 发生错误后,流程逻辑是否正常。
|
|
|
|
+
|
|
|
|
+### Promise 的错误处理实践
|
|
|
|
+
|
|
|
|
+1. 将长串的流程拆解成多个 promise,利用 promise 来处理错误嵌套?
|
|
|
|
+1. 将 promise 嵌套超过两层的抽象出来变成 async 函数
|
|
|
|
+1. early return ?? 抽到流程的第一层;throw 不被处理从底层抛到高层;中间层一般不处理底层的错误,而且可能自己 throw guardError;
|
|
|
|
+1. 错误内部处理?顶层不知道用户友好的错误 => 如果追求这个体验,那么有大量的消息在中间层传递。大部分软件是不追求这个的。
|
|
|
|
+
|
|
|
|
+### reference
|
|
|
|
+
|
|
|
|
+1. [JavaScript 错误处理完全指南](https://mp.weixin.qq.com/s/I9ZrCsoNo7jrOHj8a9UW1A)
|
|
|
|
+
|
|
|
|
+## Logging: 日志设计(本地加密日志与线上日志)
|
|
|
|
+
|
|
|
|
+同时记录到本地日志,以及网络日志,网络日志部分可以做监控提醒。
|
|
|
|
+
|
|
|
|
+本地日志要采用加密算法,同时在系统处于登录界面时,将本地日志上传。
|
|
|
|
+
|
|
|
|
+日志的主要内容为:
|
|
|
|
+
|
|
|
|
+1. 可识别用户
|
|
|
|
+1. 环境信息(硬件、网络、OS、process)
|
|
|
|
+1. 核心流程的操作
|
|
|
|
+1. 错误信息
|
|
|
|
+
|
|
|
|
+### 日志分等级记录
|
|
|
|
+
|
|
|
|
+1. debug,收集个别考生的全日志信息?如何设置它?(ctrl 5 秒内连按 5 次,启动 debug 日志级别)
|
|
|
|
+1. log,全流程日志。
|
|
|
|
+1. warn,疑似错误信息。(low network speed)
|
|
|
|
+1. error,错误信息。(硬件错误,文件不存在)
|
|
|
|
+
|
|
|
|
+logger => (destination: baidu / console / file / aliyun) (type: error / warning / operation) (easy / format / single / conf)
|
|
|
|
+
|
|
|
|
+### 打印日志的注意事项
|
|
|
|
+
|
|
|
|
+1. 打印一个 JS error 对象? ===> new Error('err').stack (IE10+)
|
|
|
|
+2. Promise 的异常通过 Promise.reason 来获取
|
|
|
|
+
|
|
|
|
+## Page URLs: 前端 URL 规划
|
|
|
|
+
|
|
|
|
+[前端 URL 规划](https://doc.qmth.com.cn/pages/viewpage.action?pageId=23330835)
|
|
|
|
+
|
|
|
|
+1. https://ccnu.exam-cloud.cn/oe-web/index.html
|
|
|
|
+1. https://ccnu.exam-cloud.cn/oe-web/{js, css, img, fonts, service-worker.js}/\*
|
|
|
|
+1. https://ccnu.exam-cloud.cn/admin/index.html
|
|
|
|
+1. https://ccnu.exam-cloud.cn/admin/{js, css, img, fonts, service-worker.js}/\*
|
|
|
|
+1. https://ccnu.exam-cloud.cn/photo-upload/index.html
|
|
|
|
+1. https://ccnu.exam-cloud.cn/photo-upload/{js, css, img, fonts, service-worker.js}/\*
|
|
|
|
+1. https://ccnu.exam-cloud.cn/oe-wap/index.html
|
|
|
|
+1. https://ccnu.exam-cloud.cn/oe-wap/{js, css, img, fonts, service-worker.js}/\*
|
|
|
|
+1. https://ccnu.exam-cloud.cn/api/*
|
|
|
|
+
|
|
|
|
+## Router: 路由、页面划分、常量
|
|
|
|
+
|
|
|
|
+学生端是属于严格受控的页面跳转,既考虑刷新,也考虑缓存。
|
|
|
|
+要禁用链接的拖动或通过按 Ctrl 点击链接多开窗口。
|
|
|
|
+
|
|
|
|
+### 页面划分
|
|
|
|
+
|
|
|
|
+1. Login
|
|
|
|
+1. MainLayout
|
|
|
|
+1. OnlineExamContainer
|
|
|
|
+1. ....
|
|
|
|
+1. ModifyPassword
|
|
|
|
+1. ExamingHome
|
|
|
|
+1. ExamEnd
|
|
|
|
+
|
|
|
|
+## Core utils interface: 核心工具接口
|
|
|
|
+
|
|
|
|
+clientVersion.ts 管理可用客户端版本。
|
|
|
|
+api: getCurrentClientVersion isSupportedClientVersion
|
|
|
|
+
|
|
|
|
+updateManager.ts 应用(非客户端)是否应该更新了
|
|
|
|
+api: isNewWebAppAvailable isNewBackendAvailable getNewBackendDesc
|
|
|
|
+
|
|
|
|
+native.ts 管理原生及系统命令,详细说明 path 和相对 path
|
|
|
|
+api: isElectron execCmd readFile getRemoteApps getVirtualCams
|
|
|
|
+
|
|
|
|
+runtimeMonitor.ts 检测当前运行的环境是否合法
|
|
|
|
+检测是否打开了控制台;检测是否使用了高版本的 chrome(feature 检测)
|
|
|
|
+检测 onResize;截屏
|
|
|
|
+
|
|
|
|
+todolist:
|
|
|
|
+
|
|
|
|
+1. md5 文件校验工具方法
|
|
|
|
+1. auth 认证
|
|
|
|
+1. 工具类的测试
|
|
|
|
+
|
|
|
|
+### Layout 设计
|
|
|
|
+
|
|
|
|
+仅有一个 MainLayout 供复用,在 router 里面设置 layout。
|
|
|
|
+
|
|
|
|
+- MainLayout:
|
|
|
|
+- SideBar
|
|
|
|
+- Header
|
|
|
|
+ - MainContent
|
|
|
|
+ - MainContent 不包含统一的 margin,但为了方便,提供全局的 class 来设置 MainContent 的 margin.
|
|
|
|
+
|
|
|
|
+## Styles design: 样式管理设计
|
|
|
|
+
|
|
|
|
+全局的样式包含以下功能:
|
|
|
|
+
|
|
|
|
+1. reset style
|
|
|
|
+2. 引入组件库的 style(看能否按需引入)
|
|
|
|
+3. 全局的字体
|
|
|
|
+4. 全局的 css variables(颜色、字体大小)
|
|
|
|
+5. 全局的 class。title-text。primary-text。secondary-text。comment-text。
|
|
|
|
+
|
|
|
|
+组件内部的样式应采用 scoped,将样式限制在组件内起作用。
|
|
|
|
+
|
|
|
|
+## Notice handle: 消息提示处理设计
|
|
|
|
+
|
|
|
|
+提示的种类:成功、警告、失败、进度
|
|
|
|
+
|
|
|
|
+提示不能过于频繁,要对重复的消息提示做限流处理。
|
|
|
|
+
|
|
|
|
+部分流程性质的消息提示,可直接更新内容,延长显示时间。比如“正在上传文件”,“上传成功”。
|
|
|
|
+
|
|
|
|
+## Cache and PWA: 缓存的设计
|
|
|
|
+
|
|
|
|
+检查各个服务器资源的缓存设置:
|
|
|
|
+
|
|
|
|
+1. 后台服务器的 HTML/JS/CSS/image
|
|
|
|
+2. 阿里云上的 studentClient.json / backgroundImage.
|
|
|
|
+
|
|
|
|
+service worker cache html/js/css/image 保证首页快速可用。
|
|
|
|
+保证在运行过程中,可以更新到最新版本的 js。
|
|
|
|
+
|
|
|
|
+缓存分为应用层和网络层。
|
|
|
|
+应用层的缓存主要是将 store 缓存在 sessionStorage。
|
|
|
|
+
|
|
|
|
+都要注意缓存失效的问题,比如用户点击退出回到登录界面,通过权限获取的缓存就应该失效。
|
|
|
|
+
|
|
|
|
+PWA 最主要的功能是 cache
|
|
|
|
+cache 要判断:
|
|
|
|
+
|
|
|
|
+1. 对于更新不敏感的资源体验最好
|
|
|
|
+2. 注意缓存失效的策略
|
|
|
|
+3. 名字作为缓存的名称
|
|
|
|
+4. 页面 html 作为缓存的入口,这里是不确定的,但它包含的资源可以通过名称来跟随 html 是否缓存
|
|
|
|
+5. 网络请求的缓存。post 的不应该缓存。get 可以缓存,刷新并且网络是通畅的情况,请求新的网络请求来了,那么可以替换。
|
|
|
|
+6. 手动清缓存。做一个按钮,让用户手动点击,unregister service worker。
|
|
|
|
+
|
|
|
|
+service worker ; image cache; audio cache/prefetch
|
|
|
|
+
|
|
|
|
+## dev settings: 开发环境设计
|
|
|
|
+
|
|
|
|
+再使用了 vite 来作为开发服务器后,还有几个可以提升开发效率的功能需要研究。
|
|
|
|
+
|
|
|
|
+http/ws proxy
|
|
|
|
+开发模式下:
|
|
|
|
+设置一个服务器 ip 地址,即满足所有的 https/wss 转发。
|
|
|
|
+设置学校域名
|
|
|
|
+设置是否为测试环境。最好能 preval,减少代码信息泄露。参考 preval.marco / ts-transformer-preval
|
|
|
|
+
|
|
|
|
+## JS obfuscation: JS 混淆设计
|
|
|
|
+
|
|
|
|
+### tools
|
|
|
|
+
|
|
|
|
+1. rollup.js
|
|
|
|
+1. js-obfuscator
|
|
|
|
+
|
|
|
|
+### 消极影响:
|
|
|
|
+
|
|
|
|
+查错会很困难,会变慢。
|
|
|
|
+
|
|
|
|
+Todolist:
|
|
|
|
+
|
|
|
|
+// sessionStorage design
|
|
|
|
+// store 防破解?仅保存 user, QECSConfig 信息
|
|
|
|
+
|
|
|
|
+## tech challenges: 局部技术难点
|
|
|
|
+
|
|
|
|
+技术难题:
|
|
|
|
+
|
|
|
|
+1. iframe 的摄像头等数据共享和通信
|
|
|
|
+1. 学生作答编辑器
|
|
|
|
+1. 音频播放器
|
|
|
|
+1. 摄像头各种错误捕捉和提示
|
|
|
|
+1. webpack / babel 提前执行 js,减少代码长度。确认开发环境不检测 native 的代码。
|
|
|
|
+1. websocket as a library
|
|
|
|
+1. network with / without auth
|
|
|
|
+1. performance
|
|
|
|
+1. event design: 作为解耦核心流程的手段,用来反调试
|
|
|
|
+
|
|
|
|
+## Tech verify: 技术特性验证
|
|
|
|
+
|
|
|
|
+- [x] Electron 1.7.16 支持 Proxy / CSS var 等。
|
|
|
|
+- [ ] naive ui 核心组件在 Electron 的适配
|
|
|
|
+- [ ] 开考、交卷接口由于接口超时被重复调用,会发生什么?
|
|
|
|
+- [ ] query 的最佳实践?
|
|
|
|
+
|
|
|
|
+1. 如果有不需要链接被分享、收藏、日志或被直接跳转进来,prefer state。typed state?
|
|
|
|
+1. 传确定的简单数据。类型转换怎么做?
|
|
|
|
+
|
|
|
|
+- [ ] select 初始值类型的研究
|
|
|
|
+- form 字段 null/undefined 的最佳实践
|
|
|
|
+
|
|
|
|
+query params: 1. select,未选择,默认为 undefined? 默认为 undefined,则可不传递到后台. clearable => undefined 2. input,未填写,默认为 undefined,查询不传递。如果后台有需要,可以通过 watch 将‘’转 undefined 3. 在 axios paramsSerializer 中处理 query parameter,
|
|
|
|
+
|
|
|
|
+https://github.com/axios/axios/issues/1139
|
|
|
|
+https://www.npmjs.com/package/qs
|
|
|
|
+paramsSerializer QS defaults: null => '' ; undefined => omit ; change arrayFormat 'comma'
|
|
|
|
+
|
|
|
|
+## Upgrade strategy: 升级策略
|
|
|
|
+
|
|
|
|
+如果不改接口,仅增加接口,可以分学校升级。
|
|
|
|
+但此次是为了代码混淆和接口加密而升级的,如果存在多个版本,容易被对比。
|
|
|
|
+建议充分测试后,全量升级。
|
|
|
|
+
|
|
|
|
+## Optional feature: 选做功能
|
|
|
|
+
|
|
|
|
+1. electron crash 日志捕获及上传
|
|
|
|
+1. 不适用的宿主环境日志
|
|
|
|
+
|
|
|
|
+## 待整理
|
|
|
|
+
|
|
|
|
+======测试规范=====
|
|
|
|
+工具类充分测试
|
|
|
|
+服务类模拟测试
|
|
|
|
+前端单元测试:dom 是否如期变化,api 是否发出
|
|
|
|
+
|
|
|
|
+script 抽出来 business logic code? 不好抽取,因为大部分和 UI 相关。将 UI 相关的类抽取成不依赖 UI 的属性集合比如 ImageLike.
|
|
|
|
+
|
|
|
|
+======测试规范 end=====
|
|
|
|
+
|
|
|
|
+======校验规范=====
|
|
|
|
+校验字段的 UI 显示
|
|
|
|
+必须校验
|
|
|
|
+校验消息提示
|
|
|
|
+Form rules validator
|
|
|
|
+校验的问题在于:代码太多,重复太多,干扰正常逻辑
|
|
|
|
+======校验规范 end=====
|
|
|
|
+
|
|
|
|
+======Mock 的研究======
|
|
|
|
+api mock? 1. 基于 api 规范。 2. 随机生成数据。
|
|
|
|
+
|
|
|
|
+easy mock 线上版。
|
|
|
|
+easy mock 线下版。可以迁移。
|
|
|
|
+基本满足了需求。
|
|
|
|
+
|
|
|
|
+mock 的优缺点?
|
|
|
|
+缺点: 1. 内网更新比较麻烦 2. 有转换成本
|
|
|
|
+
|
|
|
|
+======Mock 的研究 end======
|
|
|
|
+
|
|
|
|
+## Others
|
|
|
|
+
|
|
|
|
+======设计的遗留问题和感悟=====
|
|
|
|
+
|
|
|
|
+前端架构的责任: 1. 架构是方向性的。提出目标和方向,无论底层技术和框架如何发展,目标和方向都不会变,甚至能更好的利用到变化。 2. 架构是管理变化的。当可能的变化点来临,架构能够处理。 3. 架构是划分权力和责任的。即不同的人员负责不同的模块和层级,互相有大致明确的依赖和边界。 4. 架构是负责增长的。 5. 架构是深刻理解了底层技术和业务需求,搭建出的架构既稳固又灵活。
|
|
|
|
+_. 方向性:易使用、易维护、高性能、高兼容、易调试、日志完善、安全性、文档、code review。。。前端工程化
|
|
|
|
+_. 日志完善
|
|
|
|
+_. 作用域可控
|
|
|
|
+_. 接口规范
|
|
|
|
+_. 数据类型 => IDE 编程
|
|
|
|
+_. 测试
|
|
|
|
+
|
|
|
|
+设计一个项目时:
|
|
|
|
+
|
|
|
|
+1. 先垂直切分,分为几层
|
|
|
|
+
|
|
|
|
+架构:关注生命周期,切割生命周期,关注模块,关注模块间的通信
|
|
|
|
+工具:将常用操作收敛在一起
|
|
|
|
+业务:具体细节
|
|
|
|
+
|
|
|
|
+几种设计方式:
|
|
|
|
+
|
|
|
|
+1. obj.method 耦合,同步
|
|
|
|
+2. postEvent & obj 松耦合,异步,但程序更抽象,必须把模块设计好
|
|
|
|
+3. store & emit 共享数据,模块耦合程度更低
|
|
|
|
+
|
|
|
|
+看得远,才能做设计。
|
|
|
|
+如何看得远?经验,想象力,推理能力。
|
|
|
|
+
|
|
|
|
+几种程序的架构方式:
|
|
|
|
+
|
|
|
|
+1. app start/register module
|
|
|
|
+2. plugin callback
|
|
|
|
+3. component nest
|
|
|
|
+
|
|
|
|
+前端架构:减少重复劳动。库、组件库、流程制定、高难度工具。
|
|
|
|
+
|
|
|
|
+先开发逻辑?还是同时开发样式?
|
|
|
|
+先设计通用组件?还是后面提取?
|
|
|
|
+
|
|
|
|
+程序设计能力和过程是估工期的重要因素。
|
|
|
|
+
|
|
|
|
+架构与收纳:
|
|
|
|
+方便获取(就近)
|
|
|
|
+方便记忆(分类摆放)
|
|
|
|
+容易还原(将获取模式固定,避免系统状态杂乱)
|
|
|
|
+流程抽象
|
|
|
|
+
|
|
|
|
+设计程序时: 1. 分解流程(操作人的责任范围即为一个流程) 2. 制定接口(接口即为双方开发、调试时查找问题的边界) 3. 保留日志(接收的输入,返回的输出) 4. 错误处理
|
|
|
|
+
|
|
|
|
+看源代码: 1. 模块关系 2. 模块加载 3. 模块初始化 4. 模块动态关系
|
|
|
|
+
|
|
|
|
+架构:
|
|
|
|
+
|
|
|
|
+1. 架构的核心工作是写出核心生命周期。由核心模块去实现核心生命周期。每个核心模块又有自己的生命周期。
|
|
|
|
+1. 如何分出模块?模块划分的标准:包含一段核心流程。可以独立更新。保持接口服务的稳定性。复用是附加好处。
|
|
|
|
+1. 如何一眼看出两个模块之间的关系。交互的数据量大小。
|
|
|
|
+
|
|
|
|
+框架的目的: 1. 整体可控,整体流程和接口 2. 给模块保证接口,内部可发挥,可 hack,不影响整体的质量
|
|
|
|
+
|
|
|
|
+结构良好的程序: 1. 总组件控制流程 2. 子组件控制细节 3. 总组件和子组件通过接口来沟通
|
|
|
|
+结构不好的程序: 1. 总组件只是个入口 2. 细节和跳转逻辑都在每一个子组件中
|
|
|
|
+
|
|
|
|
+有没有可能总组件无法控制流程?
|
|
|
|
+如果父子、子子组件耦合过高,那么很难梳理出清晰的总流程。
|
|
|
|
+
|
|
|
|
+MVC 分层与组织的树状图?
|
|
|
|
+组织结构
|
|
|
|
+CEO 下面总监。总监下面经理。经理下面员工。
|
|
|
|
+总监层?
|
|
|
|
+每一个层级的职责。目标、进度、指挥、协调。
|
|
|
|
+
|
|
|
|
+编程时脑袋里应该存放什么信息(超越本能,练习专业能力):
|
|
|
|
+
|
|
|
|
+1. 流程逻辑
|
|
|
|
+2. 当前打开的文件,之前打开的文件
|
|
|
|
+3. 预期结果是什么
|
|
|
|
+
|
|
|
|
+究竟是前端编织业务,还是后台自行沟通?
|
|
|
|
+
|
|
|
|
+组件:
|
|
|
|
+
|
|
|
|
+1. 组件本身的 scope,作为一个对象,需要注册。
|
|
|
|
+2. 组件的本身包含:模板、样式、逻辑。模板是内部的,也可以接受输入。由于 CSS 的特性,会受全局 CSS 的影响。JS 是内部的,接受外部传入的 props。
|
|
|
|
+3. 模板接受外部的为 slot。
|
|
|
|
+4. CSS 接受外部的 style 和 class。都是只接受当前层?其他改变样式的通过 props 传入。
|
|
|
|
+5. JS 通过外部传入。包括事件回调。接口包括变量和事件。
|
|
|
|
+6. 组件封装,主要是在业务层作用。以实现业务为主,根据业务特点来确定通用性,但不追求复用。
|
|
|
|
+7. 组件复用主要是框架层。
|
|
|
|
+8. 组件间通信。props 和 event。props 的耦合性更强,耦合并非坏处,逻辑上该紧耦合就紧耦合。
|
|
|
|
+9. vuex。全局状态的分发。状态的更新方法和传递。
|
|
|
|
+
|
|
|
|
+从需求推导框架的设计,最后到项目的架构:
|
|
|
|
+用户需求: 1. 更快的响应 2. 更细致的体验 3. 更好的使用机器的特性,如下 4. 屏幕大小的适配 5. GPS,摄像头,通知 6. 由于数据的物理距离的亲密性,在设备内计算是必须的
|
|
|
|
+环境变化: 1. 硬件更强,CPU 运算更快 2. 网络更好,带宽,延时都有进步 3. 需要考虑电池 4. 移动端的屏幕 5. 浏览器 API 更强大 6. 前端开发工具链更发达
|
|
|
|
+通用框架的需求: 1. 降低前端开发的复杂性,如下 2. 渲染 => 将数据变成 HTML。模板。DOM 性能 3. 将渲染的流程优化。
|
|
|
|
+a. 即模板不变,只是根据数据动态改变 HTML,和传递用户的输入。
|
|
|
|
+b. 将逻辑集中到数据操作。因为数据逻辑更加易于测试和推导。
|
|
|
|
+c. 如何监控数据?deep? native value? Array value? 4. 组件式开发。例子:UI 库,ant-design。可定制的部分?样式、行为。
|
|
|
|
+a. 如何支持组件?核心问题。查看 Vue 的源码。
|
|
|
|
+b. 从模板来的组件树。编译原理?? 5. 数据的流转。store,single source of truth. 数据的共享和隔离。不可变数据? 6. router。适合 web 的一种将应用模块化的方式。用来组织程序,分包,并给用户在程序中定位的能力。
|
|
|
|
+
|
|
|
|
+原理:假如自己来写一个前端框架应该怎么写?
|
|
|
|
+如何组织一个应用程序?分层。模块化。将应用程序模块化。
|
|
|
|
+
|
|
|
|
+项目开始编码前问几个问题: 1. 有几个 module? 2. 是否需要划分 module?划分 module 的原则是,项目足够大,需要划分 module 来降低复杂度。未来有可能划分吗? 3. 划分模块后,store/routes 和 modules 放在一起
|
|
|
|
+
|
|
|
|
+view 的具体划分
|
|
|
|
+components 纯视图组件,可共用。比如 view libs,iview 之类的。
|
|
|
|
+views 和 routes 相关的组件。带状态,最起码和 URL 相关。
|
|
|
|
+组件划分的需求(终极目标降低复杂度): 1. 可被复用。如果很通用,非业务组件,就追求这一点。业务组件很难被复用。 2. 业务组件的目标。利于维护,需求来自于业务划分。
|
|
|
|
+利于维护可细化为: 1. 分离相互可以独立的功能,每一个模块可以独立完成一个功能,即因为有了这个模块存在,项目的复杂度降低了。(树形划分功能,并将功能之间的关系连接) 2. 接口清晰。即功能之间的关系最小化。
|
|
|
|
+
|
|
|
|
+数据类型:
|
|
|
|
+全局公用一份,比如 user,privilege
|
|
|
|
+衍生数据,通过 computed 来拿?getter
|
|
|
|
+数据逻辑:
|
|
|
|
+不同 module 的数据不共享,由各自的 module 去维护更新。如果 module 之间的数据不一致,可以设置全局标志位,或由页面刷新来保证一致性。
|
|
|
|
+Modal 的数据有包含它的组件(Main)提供,Main 提供数据处理完的回调。
|
|
|
|
+在 Modal 里完成对数据的校验和提交。
|
|
|
|
+增加和修改的功能抽离为一个组件:所属的代码较多,和主功能牵扯较少。
|
|
|
|
+组件与 store 数据之间的关系: 1. 尽可能减少使用 store 数据。优先使用 props 传递,这样组件更加独立。 2. 数据集中使用 3. 尽量少修改数据 4. 做好事件回调,将组件内发生的事情传递出去。
|
|
|
|
+
|
|
|
|
+设计的原则(主要从人的大脑理解能力出发):
|
|
|
|
+
|
|
|
|
+1. 顺序。一个系统切分为多个流程。流程又切分为子流程。流程主要是顺序执行的,较少判断跳转和循环,杜绝随意的流程间的连接。
|
|
|
|
+2. 集中。具有相同性质的事务,应该集中处理。
|
|
|
|
+
|
|
|
|
+设计一个系统就好像给一个团队分工,系统分工不必关心具体人的能力和性格,但是需要知道底层工具组件的能力。
|
|
|
|
+甚至一个系统最终是给不同的人使用的,那么这些角色的操作流程、效率、配合和权限也要考虑在系统中。
|
|
|
|
+
|
|
|
|
+系统的演化:
|
|
|
|
+
|
|
|
|
+1. 混为一团。
|
|
|
|
+2. 识别出主要模块,模块间连接没有规范,物理上还在一起。
|
|
|
|
+3. 模块间通信规范,物理上没分离。
|
|
|
|
+4. 模块物理分离。
|
|
|
|
+
|
|
|
|
+https://www.infoq.cn/article/AJ0S3IDEHyusNms0bTf1
|
|
|
|
+深度解读当代前端架构演进与趋势
|
|
|
|
+MVC: 将 view 和 model 分开,这两个都是比较复杂的部分,且可以独立变化,并且各自的细粒度组件可以复用。controller 是粘合剂。
|
|
|
|
+经典 MVC 时代,视图没有标准(图形操作系统还没有诞生),视图的输入输出比较底层,比如接收键盘输入,这个时候 controller 就做了大量非本质性工作。
|
|
|
|
+controller update model.
|
|
|
|
+controller update view.
|
|
|
|
+event & reference 都被使用了。
|
|
|
|
+
|
|
|
|
+Application Model: 某些状态是属于 view 的,但又不能放 view 里面,因为会影响 view 的通用性,同时这些状态又是 model 派生出来的,但理论上 model 与 view 是无关的,所以 model 来维护这些状态很奇怪。
|
|
|
|
+比如超过某个数字,把 label 变成红色。
|
|
|
|
+这时就创造出 AM 这个概念了。AM 来维护 view 的状态。
|
|
|
|
+
|
|
|
|
+以上 MVC,
|
|
|
|
+
|
|
|
|
+现代个人操作系统大大简化了输入输出,PC OS 一开始就为个人设计,所以 GUI 是重中之重,view 的功能强大了,却同时简化了,大部分 controller 要做的底层部分被简化掉了,变成了 view 内置的逻辑。
|
|
|
|
+
|
|
|
|
+MVVM: data-binding
|
|
|
|
+Model 在哪里?
|
|
|
|
+view 是 template & style?
|
|
|
|
+
|
|
|
|
+MVVM => 重点在于 VM 是 data binding view,data 改变则 view 自动改变
|
|
|
|
+
|
|
|
|
+MVVM => data(model) -> transform(view model) -> view
|
|
|
|
+MVP
|
|
|
|
+MVC (UI no auto update)
|
|
|
|
+
|
|
|
|
+前端的变化:业务流程优化!以往 web 前端弱小的时候,流程是在服务端控制的多页面(业务窗口)完成的,现在前端强大了,虽然可能还是多页面,但已经是由前端控制的流程。
|
|
|
|
+即由多业务窗口多次提交,变成统一业务窗口了。
|
|
|
|
+
|
|
|
|
+改变开发的思维模式:
|
|
|
|
+首先设想页面要展现什么数据(暂时不考虑组件)
|
|
|
|
+假设数据已得到(并且要设计数据模型)
|
|
|
|
+数据会如何变化
|
|
|
|
+
|
|
|
|
+总是在第一次采用最直觉的写法完成任务,之后再优化性能和体验
|
|
|
|
+比如对于易过期的数据,总是获取而不考虑缓存
|
|
|
|
+
|
|
|
|
+关于 null 的思考
|
|
|
|
+boolean select with null? and filter null?
|
|
|
|
+component:
|
|
|
|
+state: null; // default
|
|
|
|
+api pass state null/false/true?
|
|
|
|
+api:
|
|
|
|
+if pass null to api 是可以考虑的
|
|
|
|
+search is null? search 时 null 的话,不传。
|
|
|
|
+edit 时,null 必须要传到后台 (将 enabled 修改为 null)
|
|
|
|
+component prop forSearch? no
|
|
|
|
+search { enabled} 当传递到 api 时,去掉 null
|
|
|
|
+
|
|
|
|
+前端开发的几大主题:
|
|
|
|
+
|
|
|
|
+1. 校验
|
|
|
|
+2. 异常处理
|
|
|
|
+3. 数据流
|
|
|
|
+4. 安全
|
|
|
|
+5. 图形化
|
|
|
|
+6. 数据模型
|
|
|
|
+
|
|
|
|
+一个应用如果只考虑正确情况,那它的架构和状态应该是怎么样?
|
|
|
|
+此为一个简化版本,应用的是第一性原理。
|
|
|
|
+然后考虑一个应用如果考虑网络请求,网络错误,日志,性能,动画,复用,错误提示,校验?
|
|
|
|
+
|
|
|
|
+======设计的遗留问题和感悟=====
|
|
|
|
+
|
|
|
|
+======脚手架设计======
|
|
|
|
+Vue 框架 avue 评估
|
|
|
|
+
|
|
|
|
+混用 avue?
|
|
|
|
+theme?
|
|
|
|
+样式覆盖
|
|
|
|
+网络调用
|
|
|
|
+vuex
|
|
|
|
+avue 的 vue 使用的是过时版本,它的长期发展不明确,还是自己维护组件比较靠谱。
|
|
|
|
+q-crud: 增删改查
|
|
|
|
+q-table:
|
|
|
|
+q-page:
|
|
|
|
+脚手架快速启动:
|
|
|
|
+login page
|
|
|
|
+4xx/500 page
|
|
|
|
+router
|
|
|
|
+store
|
|
|
|
+权限/角色
|
|
|
|
+
|
|
|
|
+只使用 avue 的 表单+表格+新增,分页,网络请求,错误处理
|
|
|
|
+
|
|
|
|
+脚手架初始化公共功能
|
|
|
|
+前端公共模块
|
|
|
|
+提炼公共接口标准
|
|
|
|
+提炼公共设计模式
|
|
|
|
+
|
|
|
|
+vue 权限管理: 加入脚手架
|
|
|
|
+scrollbar; visible/hide/width restore
|
|
|
|
+compatibility
|
|
|
|
+document.title
|
|
|
|
+i18n
|
|
|
|
+
|
|
|
|
+CRUD: paging, save page state? 最低要求,一个丰富的 sample 页面,增删改查分页上传。最高要求:配置化(自动生成 route, page,被集成,但不进 git);或者通用页面,接收参数。
|
|
|
|
+
|
|
|
|
+======componet 设计=====
|
|
|
|
+一个设计良好的组件:
|
|
|
|
+
|
|
|
|
+1. 能简单的完成基本任务。
|
|
|
|
+2. API 符合直觉。名称。
|
|
|
|
+3. 不影响外部状态(样式)。
|
|
|
|
+4. 错误要抛出,出错至少要对开发友好。
|
|
|
|
+5. 清晰完整的使用文档。
|
|
|
|
+6. 可平滑升级。
|
|
|
|
+7. 如果是组件库,那么组件要有相似性,api、样式。
|
|
|
|
+8. 样式 scoped 很难被外部覆盖,所以最好基于 class 的。
|
|
|
|
+
|
|
|
|
+component 的接口:
|
|
|
|
+
|
|
|
|
+1. 外部传进的 props,包含数据和 callback
|
|
|
|
+2. component globals, $store, $http, window
|
|
|
|
+3. 内部状态?只是影响组件内部逻辑是最好的。
|
|
|
|
+4. 内部状态由网络获取的部分?与整体的 store 没有关系。
|
|
|
|
+5. 直接发起请求影响服务器?可能影响 store 的数据一致性,那么应该有 store 去统一操作。
|
|
|
|
+6. mapstate from store. component 的依赖是个多重来源的,并不由 parent component 完全控制。
|
|
|
|
+7. 与 graphql 的关系
|
|
|
|
+
|
|
|
|
+根据项目的大小划分 component 的责任:
|
|
|
|
+责任列表:
|
|
|
|
+
|
|
|
|
+1. 显示数据
|
|
|
|
+2. 监听用户操作
|
|
|
|
+3. 获取数据
|
|
|
|
+4. 处理数据
|
|
|
|
+
|
|
|
|
+中小项目可以将以上合在一起。大型项目中的 component 会很大很复杂。
|
|
|
|
+需要将 component 的功能简化,变成只 render。
|
|
|
|
+但 component 需要有办法声明数据依赖,并将对数据的影响传递出去。
|
|
|
|
+
|
|
|
|
+container component: fetch data
|
|
|
|
+presentational component: display data
|
|
|
|
+
|
|
|
|
+controlled component: 由上层获取数据,数据有变化,也通过 onchange 事件通知上层去处理,或者上层传递 props 函数去处理。
|
|
|
|
+
|
|
|
|
+container component 的子组件层级里面再包含 container component 也是允许的,只要子组件是自己管理它获取的状态就可以。
|
|
|
|
+
|
|
|
|
+css 共享和隔离? global css, component css
|
|
|
|
+
|
|
|
|
+component 的职责:有无网络请求?有。
|
|
|
|
+
|
|
|
|
+======componet 设计 end=====
|
|
|
|
+
|
|
|
|
+======脚手架设计 end======
|