# dsat-ovsap-web **Repository Path**: nida/dsat-ovsap-web ## Basic Information - **Project Name**: dsat-ovsap-web - **Description**: 123 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-06-04 - **Last Updated**: 2024-06-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # dsat-ovsap-web ## 本地启动调试 ### 1. 启动项目 连接 sit 环境: ```bash npm run start:sit ``` 连接 uat 环境: ```bash npm run start:pre ``` ### 2. 屏蔽鉴权 - 适用于浏览器调试 (若非通过 App 容器打开,则需要此步) 文件: src/layouts/index.tsx - line25 ```tsx // let globleSign = false; // 修改为 let globleSign = true; ``` ### 3. 从线上环境获取 Token 从线上已部署的页面的 Ajax 请求中拷贝 Request Header 中的 Authorization; 如: ``` Authorization: eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDE5MjkwMjQsInRva2VuIjoiZWU0YzhhMGYxZDk3NmM5ZDg5MWU2YmZlNDRlY2UyM2QyMDc0NjIwNjRlODc0NzMxOTMzMzFhZjZmZWQ4ZGEwYWE2ZGVmYjhmOGQwMDRlOTIyNzBhYmUyN2Q0ZDVlNjAzNDk3YjI2YmQwYmJlNGI2ZjE0N2UxNTZiMWNiOTk3YjhjYWQ0Nzc5ZjMwYzNiNWYwYzU0ZGFmYzU5OGJmMjRiZTQwMGU2NjljMmJiZTU1NjQwOGQ4MzlhMjJkNGI5MDEzZWMzZTc4OGZlYjkwYzQ2MDFiMTQwYzdjMWFiY2E4YWEzODZhMDE0NGI1MDRiNTlmYTY1ZmMzOTk2ZDcyZTczMDY3MGYwYzUxNzcxOWRkODAxODZjZDNmNzY3NmU3ODJlNjM3Yzc1YzZjZTAxZGViNGY0ZDlkMWUzMzFmNDRjMzAwNWNmNWY0YjA2OWU4ZmYzIn0.n15WcRYDwCWu60fSp82xCoC_Vacmk204rjdT9wygYCE ``` 将其复制到文件: /src/utils/fetch.ts - line 23 extend 方法中 ```js const request = extend({ // 为每个请求添加前缀 prefix: API_HOST, errorHandler, headers: { 'Accept-Language': transform2HantFormat(getLocale()), Authorization: 'eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NDE5MjkwMjQsInRva2VuIjoiZWU0YzhhMGYxZDk3NmM5ZDg5MWU2YmZlNDRlY2UyM2QyMDc0NjIwNjRlODc0NzMxOTMzMzFhZjZmZWQ4ZGEwYWE2ZGVmYjhmOGQwMDRlOTIyNzBhYmUyN2Q0ZDVlNjAzNDk3YjI2YmQwYmJlNGI2ZjE0N2UxNTZiMWNiOTk3YjhjYWQ0Nzc5ZjMwYzNiNWYwYzU0ZGFmYzU5OGJmMjRiZTQwMGU2NjljMmJiZTU1NjQwOGQ4MzlhMjJkNGI5MDEzZWMzZTc4OGZlYjkwYzQ2MDFiMTQwYzdjMWFiY2E4YWEzODZhMDE0NGI1MDRiNTlmYTY1ZmMzOTk2ZDcyZTczMDY3MGYwYzUxNzcxOWRkODAxODZjZDNmNzY3NmU3ODJlNjM3Yzc1YzZjZTAxZGViNGY0ZDlkMWUzMzFmNDRjMzAwNWNmNWY0YjA2OWU4ZmYzIn0.n15WcRYDwCWu60fSp82xCoC_Vacmk204rjdT9wygYCE', }, getResponse: true, }); ``` ### 3. 屏蔽通过 AlipayJSBridge 获取用户信息 # 澳門政務 react 腳手架 - [澳門政務 react 腳手架](#澳門政務-react-腳手架) - [一、設置澳門政務私有 npm 倉庫](#一-設置澳門政務私有-npm-倉庫) - [二、從模板創建工程](#二-從模板創建工程) - [創建工程](#創建工程) - [啟動工程](#啟動工程) - [项目打包](#项目打包) - [项目结构](#项目结构) - [開發工具等準備工作](#開發工具等準備工作) - [UI 組件參考文檔](#ui-組件參考文檔) - [路由、打包框架介紹](#路由-打包框架介紹) - [數據流框架介紹](#數據流框架介紹) - [前端開發規範](#前端開發規範) - [文件結構/命名](#文件結構命名) - [組件文件命名](#組件文件命名) - [頁面&組件](#頁面組件) - [頁面資源的作用域](#頁面資源的作用域) - [使用 on 作為事件名稱的前綴](#使用-on-作為事件名稱的前綴) - [正確拼寫單詞](#正確拼寫單詞) - [代碼結構](#代碼結構) - [單個文件行數](#單個文件行數) - [明確的註釋](#明確的註釋) - [禁止無意義的容器包裹](#禁止無意義的容器包裹) - [不要在邏輯體中編寫過長的代碼](#不要在邏輯體中編寫過長的代碼) - [遍歷對象時,Item 組件應明確標記字段內容](#遍歷對象時item-組件應明確標記字段內容) - [防止組件造成內存泄漏](#防止組件造成內存泄漏) - [不要在 src 中引入大文件](#不要在-src-中引入大文件) - [僅必要的屬性作為必選(2020-01-28 更新)](#僅必要的屬性作為必選2020-01-28-更新) - [函數組件](#函數組件) - [不要邏輯體中使用 hooks](#不要邏輯體中使用-hooks) - [使用默認值或 defaultProps 為屬性賦初始值](#使用默認值或-defaultprops-為屬性賦初始值) - [確保妳的引用類型是不可變的(immutable)](#確保妳的引用類型是不可變的immutable) - [dva](#dva) - [namespace 規範](#namespace-規範) - [dva-model 的作用是共享狀態/共享業務邏輯](#dva-model-的作用是共享狀態共享業務邏輯) - [統壹的 reducers](#統壹的-reducers) - [不在基礎組件中使用](#不在基礎組件中使用) - [不使用 payload 作為參數名稱](#不使用-payload-作為參數名稱) - [兼容性](#兼容性) - [文本內容](#文本內容) - [移動端橫屏布局](#移動端橫屏布局) - [video 的註意事項](#video-的註意事項) - [交互](#交互) - [生產環境不得出現非業務提示](#生產環境不得出現非業務提示) - [其他](#其他) - [禁止隨意使用 eslint-disable](#禁止隨意使用-eslint-disable) - [禁止使用 --no-verify 提交代碼](#禁止使用-no-verify-提交代碼) - [禁止遺留 React Warnning](#禁止遺留-react-warnning) - [壹切以生產環境優先](#壹切以生產環境優先) - [禁止發布時手動幹預配置](#禁止發布時手動幹預配置) ## 一、設置澳門政務私有 npm 倉庫 澳門政務使用私有`npm`倉庫對`node.js`包進行存儲,所以要獲取澳門政務(包括一戶通)相關的`npm`包必須使用這個私有倉庫。設置方法如下(方法 1 和方法 2 選擇其一即可): 1. 使用`nrm`進行倉庫管理 ```bash # 安裝 nrm npm install -g nrm # 添加私庫到 nrm 列表 nrm add dayu https://registry-cnpm.dayu.work/ # 使用私庫 nrm use dayu ``` 2. 使用`npm`進行設置 ```bash npm config set registry https://registry-cnpm.dayu.work/ ``` ## 二、從模板創建工程 我們提供了一戶通前端開發腳手架,此腳手架有眾多優點: - 🌈 UI 样式高度可配置,拓展性更强,轻松适应各类产品风格。 - 📦 开箱即用的高质量 React 组件。 - 🛡 使用 TypeScript 开发,提供完整的类型定义文件。 - ⚙️ 全链路开发和设计工具体系。 - 🌍 数十个国际化语言支持。 - 🎨 深入每个细节的主题定制能力。 - 提供 "组件按需加载" / "Web 页面高清显示" / "SVG Icon" 等优化方案,一体式开发 - 全面兼容 react / preact ### 創建工程 ```bash # 其中 demo 是創建的工程名稱 npx create-react-app demo --scripts-version @gov-mo/cra-react-scripts --template @gov-mo/cra-template-react-boilerplate ``` ### 啟動工程 ```bash # 啟動本地開發服務 npm start ``` ### 项目打包 ```bash # 打包工程生成產物到dist目錄 npm run build ``` ## 项目结构
config                  // 配置文件目錄
  |-- config.ts         // umi 配置文件
public                  // 公共文件 這個目錄中的內容會被打包到項目根目錄下
mock                    // 服務器接口 mock
src
  |-- components        // 公共組件目錄,存放多個頁面用到的組件。
  |-- models            // 公共model目錄,存放公共模型數據。
  |-- services          // 公共service目錄,存放公共業務邏輯。
  |-- pages             // 約定式路由的頁面根目錄
    |-- home            // 頁面目錄 會自動生成路由地址/home 不可以有任何大写字母
      |-- index.tsx     // 頁面入口 入口文件默認識別index.tsx
      |-- HomePage.tsx  // 頁面文件本身
      |-- HomePage.less // 頁面文件樣式
      |-- models        // 頁面model目录
      |-- services      // 頁面api及邏輯代碼目录
  |-- utils             // 工具
  |-- global.js         // 全局生效的JS
  |-- global.less       // 全局生效的樣式
.eslintignore           // eslint過濾文件清單
.eslintrc.js            // eslint配置
.gitignore
package.json  
README.md  
## 開發工具等準備工作 1. 推薦 vscode 作為開發此項目的 IDE 2. 推薦安裝 ESLint Prettier 插件 提示:請善用 eslint-fix 修復簡單的 eslint 錯誤 ## UI 組件參考文檔 根據統計數據,澳門一戶通有 70%的用戶通過移動 App 程式使用,所以服務事項的開發推薦移動優先原則,PC 做部分 UI 組件適配。所以基礎組件推薦使用`antd-mobile`開源`React`UI 庫。 [antd-mobile 控件使用文檔](https://mobile.ant.design/docs/react/introduce-cn) 如果某個服務事項不需要在 App 中呈現,可以使用`Ant Design`開源`React`UI 庫。 [antd.design 控件使用文檔](https://ant.design/docs/react/introduce-cn) > 本腳手架模板創建工程已經進行了優化,同時支持`antd`和`antd-mobile`組件的混用,但不推薦。 ## 路由、打包框架介紹 本腳手架使用`Umi`作為工程化的基礎框架,`Umi`是一个可插拔的企业级 react 应用框架。umi 以路由为基础的,支持类`next.js`的约定式路由,以及各种进阶的路由功能,并以此进行功能扩展,比如支持路由级的按需加载。然后配以完善的插件体系,覆盖从源码到构建产物的每个生命周期,支持各种功能扩展和业务需求。 [Umi 使用文檔](https://umijs.org/zh-CN/docs) ## 數據流框架介紹 本腳手架使用`DvaJs`作為數據流方案,`dva`首先是壹個基於`redux`和`redux-saga`的數據流方案,採用約定大於配置的原則簡化了`redux`的使用方式,並且分離了`View`層和`Model`層,使邏輯和視圖分離。 [DavJs 使用文檔](https://dvajs.com/guide/concepts.html) ## 前端開發規範 ### 文件結構/命名 #### 組件文件命名 - class 組件或函數組件的文件名,應當使用 Pascal 命名規範,如:`HomePage.js`,`MyTestComponent.tsx`。 - 其他普通文件(入口文件,配置,工具)的文件名,使用駝峰命名規範,如:`index.ts`,`treeUtils.ts`,`headMenuConfig.ts`。 #### 頁面&組件 - 頁面應該寫在`src/pages`目錄下,所有頁面必須以`index.js`為入口。頁面的路徑不可以包含大寫字母,如目錄包含多個單詞,請使用"-"分隔,如`pages/user-manage/index.js` - 頁面應當包含三要素(`index.js`入口,`NamePage.js`頁面本身,`NamePage.less`頁面的樣式) #### 頁面資源的作用域 - 頁面中引入(組件/服務/models/工具等)資源時,必須遵循規則:禁止依賴子頁面或兄弟頁面的相關資源,只可以引入當前目錄的相關資源,或祖先目錄的相關資源。如果某頁面需要引用兄弟頁面的資源,請進行重構,將該資源提升至他們的共同祖先目錄。【簡單來說:在 `pages` 中隨意刪除某個頁面目錄,其他內容不得出現依賴報錯】 #### 使用 on 作為事件名稱的前綴 - 組件上的事件,以 on 開頭,推薦(on + [名詞] + 動詞)的方式命名,如 onTitleClick,onSubTitleChange。 - 允許壹些特殊情況,如表達將要發生的事情,是以 `before` 作為事件名前綴 - 上述事件的響應函數,應該使用`handle`作為前綴,如 handleTitleClick #### 正確拼寫單詞 - 禁止出現英文單詞拼寫錯誤,禁止直接使用拼音作為變量名稱(專有名詞除外,但需要寫清楚註釋)。 ### 代碼結構 #### 單個文件行數 - 單個頁面/組件文件,代碼量請控制在`300`行以內,超過該數目,請適當對業務內容進行拆分。 #### 明確的註釋 - 接口層 services,組件的 `propTypes` 等,復雜的業務邏輯,工具代碼等,請編寫足夠的可讀性強的註釋,以便於代碼維護。 - 非頁面組件,必須明確地編寫 `propTypes` 或 `interface`(`typescript`),並標記註釋。非必填屬性,必須給予默認值 `defaultProps` #### 禁止無意義的容器包裹 - 禁止無意義的容器包裹,如:`
` #### 不要在邏輯體中編寫過長的代碼 - 在 if/else switch 語句 body 中,大量的代碼只會造成邏輯易讀性查。邏輯塊中應該只存放關鍵內容,其他內容可以提前定義或抽離成方法。 #### 遍歷對象時,Item 組件應明確標記字段內容 - 當需要遍歷時,作為 Item 的組件,應該更清晰地標記出來每壹項屬性,而不是壹個 object 帶過。對於後續維護將增加難度: ```jsx // bad { data.map((item) => { return // 直接把對象丟進去,難以被理解 }) } // good { data.map((item) => { const { name, age, phone, address } = item; // 這樣 Item 組件需要哪些字段,都比較清晰 return ( ); }) } ``` #### 防止組件造成內存泄漏 - 禁止在組件中,直接使用產生外部影響的方法,如 addEventListener,setInterval 等。函數組件中,使用 Hooks 進行封裝。class 組件中,可再基於 Hooks 封裝為空組件。 - 在函數組件中,推薦大家使用`ahooks`的以下鉤子: - useEventListener 事件監聽 - useInterval/useTimeout 計時器 - useDebounceFn/useThrottleFn 防抖/截留函數 - 在 class 組件中,推薦大家單獨封裝組件,通過組件的回調觸發事件。有壹個很簡單的操作,直接用函數組件+hooks 做壹層封裝即可。 #### 不要在 src 中引入大文件 - 如果妳想使用壹些第三方的 umd 包,或者引入壹些超大文件,請不要直接作為源碼引入,這將導致初始包過於龐大。請合理使用異步加載的手段引入。 #### 僅必要的屬性作為必選(2020-01-28 更新) - 編寫組件時,除非嚴重影響組件功能邏輯,否則屬性都應該是`可選`的。 - 使用`typescript`書寫代碼時,必選屬性會要求開發者的必須傳值,如果是不重要的屬性,必選會造成體驗較差,所以只要不影響功能邏輯,都應該使用`可選`。 - 壹般,默認屬性(如`defaultValue`),事件(如`onClick`)都應該是`可選`的。屬性是否必選,請根據組件功能邏輯自行定奪。 ### 函數組件 #### 不要邏輯體中使用 hooks - hooks 的使用前提是,必須保證每次執行函數時,調用 hooks 的順序不變。所以壹旦妳將 hooks 寫在 if/while/for 等條件語句中,hooks 將出現異常。 #### 使用默認值或 defaultProps 為屬性賦初始值 - 如下所示,二選壹即可,推薦在解構時賦值 ```jsx export Comp = (props) => { // 在解構時賦初始值 const { className = '' } = props; return (
xxx
) } // 通過 defaultProps 賦初始值 Comp.defaultProps = { className: '', } ``` #### 確保妳的引用類型是不可變的(immutable) - 不要直接在函數體中,創建引用類型,並將它們用於`useEffect`/`useCallback`/`useMemo` ```jsx // bad export Comp = (props) => { const { a = '', b = 0 } = props; // 每次渲染時,都將生成新的 param 實例 const param = { a, b }; // 導致每次渲染時 useEffect 都會被觸發 useEffect(() => { getUserInfo(param); }, [param]); return (
xxx
) } // bad 默認值使用引用類型也會導致同樣的問題 export Comp = (props) => { // 如果 a 的值為空,則每次都會獲得新的對象,導致 useEffect 每次都觸發 const { a = {} } = props; useEffect(() => { getUserInfo(a); }, [a]); return (
xxx
) } ``` - 在`useEffect`/`useCallback`/`useMemo`中,只使用非引用類型判斷 - 如果壹定要使用引用類型,請確保它的不可變性 ```jsx // good // 在函數體外部定義默認值(或使用defaultProps的方式設置默認值也可以) const defaultValue = {}; export Comp = (props) => { const { value = defaultValue, a, b } = props; // 使用 useMemo 的方式,確保 a/b 不變的情況下,不會生成新的 param 實例 const param = useMemo(() => ({ a, b }), [a, b]); useEffect(() => { getUserInfo(value, param); }, [value, param]); return (
xxx
) } ``` ### dva #### namespace 規範 - `model`中`namespace`應該與文件名保持壹致,以便排查。(當然,妳可以不寫,`dva`會自動使用`model`的文件名作為`namespace`。 #### dva-model 的作用是共享狀態/共享業務邏輯 - 簡單的頁面,請盡量少使用`dva-model`。當兄弟頁面/父子頁面之間存在復雜的狀態共享時,我們才考慮使用`model`的`state`。當兄弟頁面/父子頁面之間存在業務邏輯復用時,我們才考慮使用`model`的`effect` #### 統壹的 reducers - 使用`dva-model`時,請盡量少新建`reducers`,大部分的內容都可通過壹個統壹的`update`方法來完成 #### 不在基礎組件中使用 - `components` 下的基礎組件,禁止與 `dva-model` 關聯,組件的邏輯應該是相對獨立的,不應該與 `redux` 耦合 - 頁面拆分的子業務模塊可以關聯 `model`。 #### 不使用 payload 作為參數名稱 - payload 和 foo/bar 壹樣是用於代碼演示的占位符,並沒有實質的意義,不如根據妳的業務起壹個有意義的名字。 ### 兼容性 #### 文本內容 - 不要在設置了 `overflow:hidden` 且不支持換行的文本容器上設置固定寬度,設置了`text-overflow`實現溢出省略的除外。 - 不同設備可能存在字體表現不壹致的情況,不同字體實際占據的像素值可能略有差距,可能在妳的開發設備上調整合適的寬度,在其他設備就不合適,導致字體展示不全。 - 不要通過設置 `height` 調整文本容器的高度。 - 請查看是否容器上有 `line-height` 屬性導致高度展示不正確。 - 與寬度同理,如果在妳的開發設備強行設置文本高度為壹行,在其他設備因字體不同,可能導致部分英文字母(如`j`,`q`,`p`,`g`)底部展示不全。 - 可以考慮 `flex` + 空 div 的方式實現排列和間距。 #### 移動端橫屏布局 - H5 開發過程中,必須要驗證當前頁面在橫屏狀態下不出現狀態混亂。合理地使用彈性布局,確保在設備橫屏時,能獲得比較好的體驗 #### video 的註意事項 - 視頻 video 標簽上方不應該疊加內容(需要 UED 設計時配合),對於國產 UC/百度等瀏覽器,video 標簽上無法疊加內容(他們會接管 video 的渲染,導致無法自定義樣式)。 ### 交互 #### 生產環境不得出現非業務提示 - 項目發布後不能出現彈出服務報錯的調用棧等異常情況,只能通過 console.error 提供排查幫助。 ### 其他 #### 禁止隨意使用 eslint-disable - 除極個別情況(需要與前端項目負責人溝通確認),不可以在業務代碼中使用`eslint-disable`的方式跳過`eslint`校驗規則。 #### 禁止使用 --no-verify 提交代碼 - `-n`/`--no-verify`可以避開`git commit`操作前的檢查,但這很可能將存在問題的代碼提交到了服務器上。 #### 禁止遺留 React Warnning - 對於控制臺中打印的 Warnning 信息,如 React 出現的 duplicate key, update on an unmounted component, invalid value for prop xxx 等問題,請務必解決後再提交代碼。 #### 壹切以生產環境優先 - 如需引入外部資源,或跳轉外部鏈接,且開發/測試/生產環境不壹致的,如需在前端代碼做條件判斷,壹切以生產環境優先。舉幾個例子: - 開發環境和生產環境使用的地圖服務不同,在代碼中請配置為生產環境服務。開發環境通過條件判斷引入。 - 開發環境和生產環境的 API 前綴不同,也請在代碼中配置生產環境的前綴。 ```javascript if (location.hostname === '127.0.0.1' || location.hostname === 'localhost') { // 本地開發,使用高德地圖 document.write( '', ); } else { // 其他情況,請壹律寫生產環境配置 var host = 'xxx.xxx.xxx.xxx'; var version = '1.0'; document.write( '', ); } ``` #### 禁止發布時手動幹預配置 - 禁止在部署時手動調整項目配置,如外部鏈接,umi-config,nginx.conf 等,必須通過自動化完成部署。 - 通過參數/配置/環境檢測等方式,使程序自動切換配置。