背景:PC端的CRM系統第一階段已經開發完畢.使用技術爲:JS + AntDesignPro.如今開始開發企業微信.須要使用的技術爲:TS + AntDesignMobile.由於公司以前有人開發過企業微信版,因此直接拉的別人搭好的架子.
開發以前,反覆瀏覽TS的官網,AntDesignMobile的官網.html
與AntDesignPro目錄是差很少的.簡單說下.開發代碼仍是在src下面的pages裏面.assets裏面放的通常都是圖標.components裏面都是本身封裝的組件.layouts裏面是鑑權.interceptors.ts文件裏面是獲取token的地方.umirc.ts裏面是鏈接後端服務器地址的.開發服務器,測試服務器,生產服務器等.react
目錄結構:
ios
上代碼:
services層:axios
import axios from 'axios'; /** * 首頁列表 */ export async function listHome(data : any) { return axios.post(`/${process.env.APIPREFIX}/ticket/listHome`, data); }
model層:後端
import * as services from './service'; export default { namespace: 'home', effects: { // 首頁列表 *listHome({ data, callback} : any, { put, call }: any) { const datas = yield call(services.listHome, data); yield put({ type: 'save', payload:{listHome : datas.data} , }); if (datas.code === '0000') { callback && callback(datas.data); } }, }, reducers: { save(state : any, { payload } : any) { return { ...state, ...payload, }; }, } }
index.tsx:服務器
/** * title: '昆藥CRM' */ import React from 'react'; import { List } from 'antd-mobile'; import router from 'umi/router'; import styles from './index.less'; import { connect } from 'dva'; import IconBlock from './components/IconBlock'; import { Flex } from 'antd-mobile'; const Item = List.Item; const Brief = Item.Brief; const namespace = 'home'; const mapStateToProps = (state: any) => { const states = state[namespace]; return { ...states, }; }; const mapDispatchToProps = (dispatch: any) => ({ // 首頁列表 listHome(data: any, callback: any) { dispatch({ type: `${namespace}/listHome`, data, callback, }); }, }); class Home extends React.Component { constructor(props: any) { super(props); this.state = { menu: [], order: { groupTitle: '訂單相關查詢', menuList: [], }, // 訂單類 invoiceFinancial: { groupTitle: '回款相關查詢', menuList: [], }, // 發票財務類 masterData: { groupTitle: '主數據查詢', menuList: [], }, // 主數據類 }; } componentDidMount() { this.getList(); } // 獲取首頁圖標 getList = () => { const { listHome }: any = this.props; listHome({}, (res: any) => { res.menus && res.menus.map((val: any) => { val.children.map((value: any) => { if (value.menuName === '訂單類') { const { order }: any = this.state; this.setState( { order: { ...order, menuList: value.children, }, }, () => { const { order }: any = this.state; this.setState({ menu: [order] }); }, ); } if (value.menuName === '發票財務類') { const { invoiceFinancial }: any = this.state; this.setState( { invoiceFinancial: { ...invoiceFinancial, menuList: value.children, }, }, () => { const { menu, invoiceFinancial }: any = this.state; this.setState({ menu: [invoiceFinancial, ...menu] }); }, ); } if (value.menuName === '主數據類') { const { masterData }: any = this.state; this.setState( { masterData: { ...masterData, menuList: value.children, }, }, () => { const { menu, masterData }: any = this.state; this.setState({ menu: [masterData, ...menu] }); }, ); } }); }); }); }; // 跳轉 jump = (path: any) => { const { menuList, dispatch }: any = this.props; let key: any = ''; let menuList1 = menuList.menuData.menuList; let query = (arr: any, index: number) => { if (arr.path === path) { key = index && index; } else if (arr.children.length > 0) { arr.children.map((i: any) => { query(i, index); }); } }; menuList1.map((item: any, index: number) => { query(item, index); }); dispatch && dispatch({ type: 'global/changeLayoutCollapsed', payload: false, }); localStorage.setItem('menuNav', key.toString()); router.push({ pathname: path, }); }; render() { const { menu }: any = this.state; return ( <div style={{marginBottom:50}}> <img src={require('../../assets/icons/banner.png')} style={{width:'100%',marginBottom:20}}/> {menu && menu.map((value: any) => ( <div key={value.groupTitle}> <span className={styles.section_title}>{value.groupTitle}</span> <Flex wrap="wrap"> {value.menuList.map((item: any, index: number) => ( <IconBlock key={index} titleName={item.menuName} iconPath={item.icon} method={() => this.jump(item.url)} /> ))} </Flex> </div> ))} </div> ); } } export default connect(mapStateToProps, mapDispatchToProps)(Home);
components-IconBlock.tsx:微信
import React from 'react'; import styles from './style.less'; interface IconBlockProps { titleName: string, iconPath: string, method: (e: React.MouseEvent) => void; } const IconBlock: React.FC<IconBlockProps> = ({ titleName, iconPath, method }) => { return ( <div className={styles.blockWrapper} onClick={method}> <div className={styles.icon}> <img src={iconPath}/> </div> <div className={styles.title}>{titleName}</div> </div> ) } export default IconBlock;
頭部:
底部:
antd
1:注入model層的時候,一直報錯:
.
實在是第一次用ts.真不會寫..這個類型整死我了... 搞了幾個小時...
換了好幾種寫法.. 最後才解決了...解決方法:把connect放在頁面底部.export default connect(mapStateToProps, mapDispatchToProps)(Home);
2:ESlint 真的很嚴格.. 提交代碼的時候.一直給我報錯.. 一貫急躁的我處處看ts寫法問題... 最後發現... 是個人標籤前面多打了個空格... 我真的要被本身氣死了....
3:頁面樣式問題.AntDesignMobile和AntDesignPro的組件仍是有不少不同的.好比AntDesignPro有的Row和Col,Text等等都沒有了.. 這個寫起來真的好不習慣..AntDesignMobile有Flex佈局.可是這個API用起來和原生的區別真的不大.....
寫代碼幾個小時後就容易疲勞.而後列表循環展現圖標的時候.把Flex標籤放循環裏面了.樣式就可想而知.一塌糊塗.. 這麼淺顯的BUG我居然仍是創造出來了... 寫出來.警告本身.之後不可再犯.app