opennft-front 开源 NFT 前端平台开源项目

我要开发同款
匿名用户2022年03月24日
320阅读

技术信息

系统类型
Web3
开源地址
https://gitee.com/shengjian-tech/opennft-front
授权协议
Apache

作品详情

项目开始BEGIN项目说明基于React16.x、AtDesig4.x,react-admi

目录结构├──cofig//项目构建配置├──public//不参与构建的静态文件├──scripts//构建脚本├──src│├──assets//全项目通用图片文件等│├──commos//全项目通用js,业务相关│├──compoets//全项目通用组件,业务相关│├──cofig//项目构建补充配置│├──layouts//页面框架布局组件+│├──mock//模拟数据│├──models//模块封装,基于redux,提供各组件共享数据、共享逻辑│├──pages//主项目页面目录│├──├──Project//子项目顶级目录│├──├──├──ft//NFT--PC版本项目目录│├──├──├──├──assets//NFT--PC版本公共图片文件│├──├──├──├──compoets//NFT--PC版本公共组件库│├──├──├──├──pages//NFT--PC版本页面目录│├──├──├──mobile//移动端项目目录│├──├──├──├──ft-mobile//NFT--微信版本项目目录│├──├──├──├──├──assets//NFT--微信版本公共图片文件│├──├──├──├──├──compoets//NFT--微信版本公共组件库│├──├──├──├──├──pages//NFT--微信版本页面目录│├──router//路由│├──at.less//主体配置│├──App.js//根组件│├──idex.css//全局样式慎用│├──idex.dark.css//全局样式慎用│├──idex.js//项目入口│├──meus.js//菜单配置│├──setupProxy.js//后端联调代理配置│└──theme.less//主题变量├──package.jso├──README.md└──yar.lock安装依赖$yar启动注意事项依赖安装完成后,src/setupProxy.js为项目本地代理文件,请及时更改您需要代理的接口地址!

!!!微信版本只可以在微信打开运行,并直接在router/AuthRoute.jsx中填入自己申请的appid,目前为''

此为两个项目依托同一底层框架,PC及微信端口分离,如需切换请在router/app.router.js中更换路由,router/AppRoute.jsx中切换引入的AuthRoute(分别为微信版本:AuthRoute.jsx,PC版本:AuthRoutePC.jsx)并在src/commos/PRE_ROUTER.js中进行相关配置,以及package.jso中更改homepage为相应的项目名称。

两套PRE_ROUTER.js中配置分别如下:

微信版本:路由前缀----/frot_ft_mobile请求地址前缀----/api/ft登录页面----/ft_mobile_home

PC版本:路由前缀----/frot_ft_pc请求地址前缀----/api/ft登录页面----/ft_home

开发启动$yarstart#指定端口$PORT=8080yarstart#HTTPS方式启动$HTTPS=trueyarstart生产构建$yarbuild//构建输入到指定目录$BUILD_PATH=../distyarbuild域名子目录发布项目//开发启动$BASE_NAME=/syext-admiyarstart//开发访问'https://localhost:XXXX/syext-admi/'//生产环境同上$BASE_NAME=/syext-admiyarstart//访问'https://xxx.com/syext-admi'菜单配置//在/src/meus.js文件中配置菜单数据,前端硬编码或异步加载菜单数据。//菜单支持头部、左侧、头部+左侧三种布局方式,默认左侧菜单。如需放开设置,请到'src/layouts/idex.jsx'放开注释//菜单字段说明。字段必须说明key是//需要唯一paretKey否//用于关联父级path是//菜单对应的路由地址text是//菜单标题ico否//菜单图标配置url否//菜单对应会打开url对应的iframe页面,如果配置了url,path将无效target否//配合url使用,菜单将为a标签<ahref={url}target={target}>{text}</a>order否//菜单排序,数值越大越靠前显示type否//如果菜单数据中携带功能权限配置,type==='1'为菜单,type==='2'为功能code否//功能码,如果是type==='2',会用到此字段页面开发//配置组件importReact,{Compoet}from'react';importcofigfrom'src/commos/cofig-hoc';@cofig({title:'页面title',ajax:true,...})exportdefaultclassSomePageextedCompoet{compoetDidMout(){this.props.ajax.get(...).the(...)}...}参数类型默认值说明oFramebooleafalse标记当前页面为不需要导航框架的页面,比如登录页,通过脚本抓取实现oAuthbooleafalse标记当前页面为不需要登录即可访问的页面,通过脚本抓取实现keepAliveboolea-标记当前页面内容在页面切换之后是否保持titleboolea或strig或ReactNode或object或fuctio(props)truetrue:当前页面显示通过菜单结构自动生成的title;false:当前页面不显示title;strig:自定义title;object:{text,ico}text为显示的名称,ico为图标;fuctio(props):返回值作为titlebreadcrumbsboolea或array或fuctio(props)truetrue:当前页面显示通过菜单结构自动生成的面包屑;false:当前页面不显示面包屑;object:[{ico,text,...}];fuctio(props):返回值作为面包屑appedBreadcrumbsarray或fuctio(props)[]在当前面包屑基础上添加;fuctio(props):返回值作为新添加的面包屑pageHeadboolea-页面头部是否显示sideboolea-页面左侧是否显示sideCollapsedboolea-左侧是否收起ajaxbooleatrue是否添加ajax高阶组件,内部可以通过this.props.ajax使用ajaxAPI,组件卸载时,会自动打断未完成的请求routerbooleafalse是否添加withRouter装饰器,组件内部可以使用this.props.history等APIquerybooleafalse是否添加地址查询字符串转换高阶组件,内部可以通过this.props.query访问查询字符串coectboolea或fuctio(state)false是否与redux进行连接,true:只注入了this.props.actio相关方法;false:不与redux进行连接;(state)=>({title:state.page.title}):将函数返回的数据注入this.propsevetbooleafalse是否添加evet高阶组件,可以使用this.props.addEvetListeer添加dom事件,并在组件卸载时会自动清理;通过this.props.removeEvetListeer移出dom事件pubSubbooleafalse是否添加发布订阅高阶组件,可以使用this.props.subscribe(topic,(msg,data)=>{...})订阅事件,并在组件卸载时,会自动取消订阅;通过this.props.publish(topic,data)发布事件modalstrig或objectfalse当前组件是否是modal。strig:弹框标题;object:弹框配置注:

oFrame、oAuth、keepAlive 只有配置了path才有效!cofig装饰器可以用于任何组件,但是title、breadcrumbs、appedBreadcrumbs、pageHead、side、sideCollapsed最好在路由对应的页面组件中使用//页面保持//页面渲染一次之后会保持状态,再次跳转到此页面不会重新创建或重新渲染开启方式:1./src/models/system.jsiitState.keepAlive属性修改默认值2.cofig装饰器keepAlive属性页面显示/隐藏事件cofig 装饰器为组件注入了两个事件 oCompoetWillShow、oCompoetWillHide ,如果页面使用了KeepAlive功能,切换显示/隐藏时会触发

@cofig({...})exportdefaultclassSomePageextedsReact.Compoet{costructor(...props){super(...props);this.props.oCompoetWillShow(()=>{//dosomethig});this.props.oCompoetWillHide(()=>{//dosomethig});}...}页面容器PageCotet系统提供了页面的跟节点PageCotet,有如下特性:

添加了margipaddig样式;添加了footer;支持页面loadig;自动判定是否有底部工具条FixBottom组件,为底部工具条腾出空间;是否显示footer,默认true

<PageCotetfooter={false}>...</PageCotet>显示loadig,有两种方式。

model方式

this.props.actio.page.showLoadig();this.props.actio.page.hideLoadig(); props方式

cost{loadig}=this.state;<PageCotetloadig={loadig}>...</PageCotet>;弹框页面开发添加、修改等场景,往往会用到弹框,atdModal组件使用不当会产生脏数据问题(两次弹框渲染数据互相干扰)

系统提供了基于modal封装的高阶组件,每次弹框关闭,都会销毁弹框内容,避免互相干扰

modal高阶组件modal高阶组件集成到了cofig中,也可以单独引用:import{ModalCotet}from'src/commos/ra-lib';

importReactfrom"react";importcofigfrom"src/commos/cofig-hoc";import{ModalCotet}from"src/commos/ra-lib";exportdefaultcofig({modal:{title:"弹框标题",},})((props)=>{cost{oOk,oCacel}=props;retur(<ModalCotetoOk={oOk}oCacel={oCacel}>弹框内容</ModalCotet>);});modal所有参数说明如下:

如果是strig,作为modal的title如果是函数,函数返回值作为Modal参数如果是对象,为Modal相关配置,具体参考 atdModal组件optios.fullScreeboolea默认false,是否全屏显示弹框ModalCotet组件弹框内容通过ModalCotet包裹,具体参数如下:

参数类型默认值说明surplusSpacebooleafalse是否使用屏幕垂直方向剩余空间otherHeightumber-除了主体内容之外的其他高度,用于计算主体高度;loadigbooleafalse加载中loadigTip--加载提示文案footer--底部okTextstrig-确定按钮文案oOkfuctio-确定按钮事件cacelTextstrig-取消按钮文案oCacelfuctio-取消按钮事件resetTextstrig-重置按钮文案oResetfuctio-重置按钮事件styleobject-最外层容器样式bodyStyleobject-内容容器样式系统路由系统路由使用react-router,通过route-loader将路由内容填充到/src/pages/page-routes.js文件,支持两种写法:

常量方式exportcostPAGE_ROUTE="/path"; 页面cofig装饰器(推荐)@cofig({path:'/path',})exportdefaultclassSomePageextedsReact.Compoet{...}二级页面二级页面如果要保持父级菜单的选中状态,以父级path开始并以/_/作为分隔符即可:paret/path/_/child/path

//paretpage@cofig({path:'/paret/path'})exportdefaultclassParetextedsReact.Compoet{...}//childpage@cofig({path:'/paret/path/_/child/path'})exportdefaultclassParetextedsReact.Compoet{...}AJAX请求系统的ajax请求基于axios封装。基于restful规范,提供了5个方法:

get获取服务端数据,参数拼接在url上,以querystrig方式发送给后端post新增数据,参数以body形式发送给后端put修改数据,参数以body形式发送给后端del删除数据,参数拼接在url上,以querystrig方式发送给后端patch修改部分数据,参数以body形式发送给后端调用方式三种//第一种cofig装饰器ajax属性(推荐)importReact,{Compoet}from'react';importcofigfrom'src/commos/cofig-hoc';@cofig({ajax:true,...})exportdefaultclassSomePageextedCompoet{compoetDidMout(){this.props.ajax.get(...).the(...)}...}//第二种ajax装饰器importReact,{Compoet}from'react';import{ajaxHoc}from'src/commpos/ajax';@ajaxHoc()exportdefaultclassSomePageextedCompoet{compoetDidMout(){this.props.ajax.get(...).the(...)}...}//第三种直接引入ajax对象importReact,{Compoet}from'react';import{sxAjax}from'src/commpos/ajax';exportdefaultclassSomePageextedCompoet{compoetDidMout(){sxAjax.post(...).the(...);//组件卸载或者其他什么情况,需要打算ajax请求,可以用如下方式costajax=sxAjax.get(...);ajax.the(...).fially(...);ajax.cacel();}...}注:cofig、ajaxHoc方式做了封装,页面被卸载之后会自动打断未完成的请求

接收参数所有的ajax方法参数统一,都能够接受三个参数:参数|说明---|---url|请求地址params|请求传递给后端的参数optios|请求配置,即axios的配置。

optios配置参数说明axios配置可以接受axios参数successTip扩展的参数,成功提示errorTip扩展的参数,失败提示oEmpty扩展的参数,过滤掉''、ull、udefied的参数,不提交给后端origiRespose扩展参数,.the中可以拿到完整的respose,而不只是respose.data注:全局默认参数可以在src/commos/ajax.js中进行配置,默认baseURL='/api'、timeout=1000*60。

请求结果提示系统对ajax失败做了自动提示,开发人员可通过src/commos/hadle-error.js进行配置;成功提示默认不显示,如果需要成功提示,可以配置successTip参数,或者.the()中自行处理;成功提示在src/commos/hadle-success.js中配置;this.props.ajax.del("/user/1",ull,{successTip:"删除成功!",errorTip:"删除失败!",oEmpty:true,});loadig处理系统扩展了promise,提供了fially方法,用于无论成功还是失败,都要进行的处理。一般用于关闭loadig

this.setState({loadig:true});this.props.ajax.get('/url').the(...).fially(()=>this.setState({loadig:false}));Mock模拟数据前后端并行开发,为了方便后端快速开发,不需要等待后端接口,系统提供了mock功能。基于mockjs

编写模拟数据在/src/mock目录下进行mock数据编写,比如:

import{getUsersByPageSize}from"./mockdata/user";exportdefault{"post/mock/logi":(cofig)=>{cost{userName,password}=JSON.parse(cofig.data);returewPromise((resolve,reject)=>{if(userName!=="test"||password!=="111"){setTimeout(()=>{reject({code:1001,message:"用户名或密码错误",});},1000);}else{setTimeout(()=>{resolve([200,{id:"1234567890abcde",ame:"MOCK用户",logiName:"MOCK登录名",},]);},1000);}});},"post/mock/logout":{},"get/mock/user-ceter":(cofig)=>{cost{pageSize,pageNum}=cofig.params;returewPromise((resolve)=>{setTimeout(()=>{resolve([200,{pageNum,pageSize,total:888,list:getUsersByPageSize(pageSize),},]);},1000);});},"getre:/mock/user-ceter/.+":{id:1,ame:"熊大",age:22,job:"前端",},"post/mock/user-ceter":true,"put/mock/user-ceter":true,"deletere:/mock/user-ceter/.+":"id",};简化为了方便mock接口编写,系统提供了简化脚本(/src/mock/simplify.js),上面的例子就是简化写法

对象的key由methodurldelay,各部分组成,以空格隔开

字段说明method请求方法getpost等url请求的urldelay模拟延迟,毫秒默认1000调用系统封装的ajax可以通过以下两种方式,自动区分是mock数据,还是真实后端数据,无需其他配置

mock请求:

url以/mock/开头的请求/src/mock/url-cofig.js中配置的请求this.props.ajax.get('/mock/users').the(...);如果后端真实接口准备好之后,去掉url中的/mock即可

注:mock功能只有开发模式下开启了,生产模式不会开启mock功能,如果其他环境要开启mock使用MOCK=true参数,比如 MOCK=trueyarbuild

样式系统使用less进行样式的编写。为了避免多人合作样式冲突,系统对src下的less文件启用了CssModule,css文件没有使用CssModule。

style.less

.root{width:100%;height:100%;}Some.jsx

import"/path/to/style.less";exportdefaultclassSomeextedsReact.Compoet{reder(){retur<divstyleName="root"></div>;}} 注:基础组件不使用CssModule,不利于样式覆盖;

主题使用less,通过样式覆盖来实现。

编写主题less文件中使用主题相关变量;编写/src/theme.less通过less-loader的modifyVars覆盖less中的变量;注:目前每次修改了theme.less需要重新yarstart才能生效

参考AtDesig主题参考:https://at-desig.gitee.io/docs/react/customize-theme-c导航布局为了满足不同系统的需求,提供了四种导航布局:

头部菜单左侧菜单头部+左侧菜单tab页方式更改方式用户可以通过页面有上角用户头像->设置页面进行选择(如果您为用户提供了此页面);开发人员可以通过修改src/models/idex.js指定布局方式;不需要导航有些页面可能不需要显示导航,可以通过如下任意一种方式进行设置:

页面配置高级组件@cofig({oFrame:true,}) 浏览器url中oFrame=true参数/path/to?oFrame=trueTab标签页页面头部标签,有如下特性:

在当前tab标签之后打开新的tab标签;记录并恢复滚动条位置;保持页面状态(需要开启KeepPageAlive);tab标签右键操作;tab页操作API;tab标签拖拽排序;关闭一个二级页面tab,尝试打开它的父级;Tab操作APIsystemmodel(redux)中提供了如下操作tab页的方法:

API说明setCurretTabTitle(title)设置当前激活的tab标题title:stirg或{text,ico}

功能介绍

项目开始 BEGIN 项目说明 基于 React16.x、Ant Design4.x,react-admin 目录结构
├── config // 项目构建配置
...

声明:本文仅代表作者观点,不代表本站立场。如果侵犯到您的合法权益,请联系我们删除侵权资源!如果遇到资源链接失效,请您通过评论或工单的方式通知管理员。未经允许,不得转载,本站所有资源文章禁止商业使用运营!
下载安装【程序员客栈】APP
实时对接需求、及时收发消息、丰富的开放项目需求、随时随地查看项目状态

评论