使用AntDesignMobile +TS 開發企業微信的第一步:首頁

背景:PC端的CRM系統第一階段已經開發完畢.使用技術爲:JS + AntDesignPro.如今開始開發企業微信.須要使用的技術爲:TS + AntDesignMobile.由於公司以前有人開發過企業微信版,因此直接拉的別人搭好的架子.
開發以前,反覆瀏覽TS的官網,AntDesignMobile的官網.html

1:項目目錄:

image.png
image.png
與AntDesignPro目錄是差很少的.簡單說下.開發代碼仍是在src下面的pages裏面.assets裏面放的通常都是圖標.components裏面都是本身封裝的組件.layouts裏面是鑑權.interceptors.ts文件裏面是獲取token的地方.umirc.ts裏面是鏈接後端服務器地址的.開發服務器,測試服務器,生產服務器等.react

2:開發首頁頁面:

目錄結構:
image.pngios

上代碼:
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;

3:實現效果:

頭部:
image.png
底部:
image.pngantd

4:說下遇到的BUG:

1:注入model層的時候,一直報錯:
image.png.
實在是第一次用ts.真不會寫..這個類型整死我了... 搞了幾個小時...
換了好幾種寫法.. 最後才解決了...解決方法:把connect放在頁面底部.export default connect(mapStateToProps, mapDispatchToProps)(Home);
2:ESlint 真的很嚴格.. 提交代碼的時候.一直給我報錯.. 一貫急躁的我處處看ts寫法問題... 最後發現... 是個人標籤前面多打了個空格... 我真的要被本身氣死了....
3:頁面樣式問題.AntDesignMobile和AntDesignPro的組件仍是有不少不同的.好比AntDesignPro有的Row和Col,Text等等都沒有了.. 這個寫起來真的好不習慣..AntDesignMobile有Flex佈局.可是這個API用起來和原生的區別真的不大....image.png.
寫代碼幾個小時後就容易疲勞.而後列表循環展現圖標的時候.把Flex標籤放循環裏面了.樣式就可想而知.一塌糊塗.. 這麼淺顯的BUG我居然仍是創造出來了... 寫出來.警告本身.之後不可再犯.app

相關文章
相關標籤/搜索