使用duxapp,我是如何實現快速完成專案開發的?
像下面這個例子,這個專案有140多個頁面,但是真實的開發時間,在熟練使用duxapp的情況下,不會超過兩週,並且可以將它相容APP、小程式、H5
這裡僅展示了其中一部分頁面,這個專案主要包含下這些功能
- 購物訂單流程
- 售後退換
- 文章釋出
- 門店功能
- 送貨人員功能
- 經銷商功能
- 掃碼抽獎
- 等其他功能
下面我將詳細介紹使用了哪些方法,來快速完成專案
使用全域性樣式快速佈局頁面
以這個門店管理首頁為例,你可以看到我並沒有匯入一個scss
檔案,但是我使用了很多的className
,這些就是用的全域性樣式,這全域性樣式都是duxapp模組提供的
import { TopView, Header, Card, Divider, ScrollView, Tag, Row, Image, Column, Text, px, nav, ModalForm, DatePicker, dayjs } from '@/duxui'
import { ArecaIcon, CmsIcon, TipNav, useRequest } from '@/arecaShop'
import { useState } from 'react'
export default function StoreManage() {
const [date, setDate] = useState()
const [{ info = {}, sku = {}, distribution = {} }] = useRequest({
url: 'store/index',
toast: true,
data: {
date
}
}, { reloadForShow: true })
return (
<TopView>
<Header title='門店詳情' />
<ScrollView>
<Card className='p-2 gap-2' margin disableMarginBottom>
<Row className='gap-2'>
<Image className='r-2'
src={info.image}
style={{ width: px(148) }}
square
/>
<Column justify='between' grow>
<Row justify='between' grow>
<Text bold size={4}>{info.name}</Text>
<ArecaIcon name='shezhi' className='text-c1 text-s7'
onClick={() => nav('arecaShop/storeManage/info')}
/>
</Row>
<Column>
<Text color={2} size={1}>聯絡人:{info.contact}</Text>
<Row grow justify='between' items='center'>
<Text color={2} size={1}></Text>
<Tag type='secondary' size='s' radiusType='round' onClick={() => nav(`tel:${info.distributor_tel}`)}>
<ArecaIcon className='text-white text-s2' name='shiwu-shouji' /> 一鍵報單進貨
</Tag>
</Row>
</Column>
</Column>
</Row>
<Divider />
<Row>
<Text color={2} size={1} shrink>門店地址:</Text>
<Text bold size={1}>{info.area}{info.address}</Text>
</Row>
</Card>
<TipNav title='貨品統計' url='arecaShop/storeManage/mallTotal'>
<Row className='items-center' grow>
<ArecaIcon className='text-secondary' name='promot_tips' />
<Text type='secondary' size={2}>{dayjs().format('MM/DD HH:mm')} 更新</Text>
</Row>
</TipNav>
<Card margin disableMarginBottom className='gap-2'>
<Text color={3} size={2}>歷史進貨數量(小包):{sku.in}</Text>
<Row justify='between' className='gap-2'>
<Column grow className='bg-page r-2 p-3 gap-1'>
<Text color={3} size={2}>歷史銷售數量(小包)</Text>
<Text bold size={40}>{sku.out}</Text>
</Column>
<Column grow className='bg-page r-2 p-3 gap-1'>
<Text color={3} size={2}>歷史剩餘數量(小包)</Text>
<Text bold size={40}>{sku.supply}</Text>
</Column>
</Row>
<Text size={22} type='secondary'>*銷量及剩餘僅供參考:記錄消費者掃碼數量,可能與實際結果有出入</Text>
</Card>
<TipNav title='配送記錄'
right={<ModalForm
title='月份'
renderForm={<DatePicker
mode='month'
/>}
childPropsValueKey='value'
value={date}
onChange={setDate}
>
<DateChild />
</ModalForm>}
></TipNav>
<Card margin disableMarginBottom className='gap-2'>
<Text color={3} size={2}>門店配送(中包):{distribution.middle_num}</Text>
<Row justify='between' className='gap-2'>
<Column grow className='bg-page r-2 p-3 gap-1'
onClick={() => nav('arecaShop/storeManage/emptyRecovery', { type: 'store' })}
>
<Text color={3} size={2}>已結算空袋(小包)</Text>
<Row items='center' className='gap-1'>
<Text bold size={40}>{distribution.recycle_num}</Text>
<CmsIcon className='text-c3 text-s5' name='direction_right' />
</Row>
</Column>
<Column grow className='bg-page r-2 p-3 gap-1'
onClick={() => nav('arecaShop/storeManage/deliveryList')}
>
<Text color={3} size={2}>門店已退貨數(小包)</Text>
<Row items='center' className='gap-1'>
<Text bold size={40}>{distribution.refund_num}</Text>
<CmsIcon className='text-c3 text-s5' name='direction_right' />
</Row>
</Column>
</Row>
</Card>
</ScrollView>
</TopView>
)
}
const DateChild = ({ value, onClick }) => {
return <Row items='center' className='r-2 ph-2 bg-white gap-1' onClick={onClick}>
<Text color={value ? 1 : 3}>{value || '請選擇'}</Text>
<ArecaIcon name='rili1' className='text-c3' />
</Row>
}
使用UI庫
在上面的示例中已經展示瞭如何使用UI庫的元件,可以看到使用了UI庫的元件,在結合全域性樣式,你會發現,似乎不需要編寫scss就能很好的完成頁面佈局了
這些元件都是duxui UI庫提供的
使用List元件完成列表頁面
以下面這個列表頁面為例,List元件幫你完成了資料請求、自動分頁、下拉重新整理、自動重新整理等功能,你只需要關注你列表中的每一項是如何編寫的
import { TopView, Header, Card, Tab, Row, Image, Column, Text, px, Empty, DatePicker, SelectorPicker, ModalForm, Button } from '@/duxui'
import { ArecaIcon, List, usePageData, nav } from '@/arecaShop'
import { useState } from 'react'
export default function DeliveryList() {
const [users] = usePageData('store/salesman')
const [user, setUser] = useState()
const [type, setType] = useState(0)
return (
<TopView>
<Header title='配送記錄' />
<Tab className='bg-white' value={type} onChange={setType}>
<Tab.Item title='門店配送' paneKey={0} />
<Tab.Item title='門店退貨' paneKey={1} />
</Tab>
<Row className='ph-3 mt-3' items='center' justify='between'>
<ModalForm
title='業務員'
renderForm={<SelectorPicker range={users} nameKey='nickname' valueKey='id' />}
childPropsValueKey='value'
value={user}
onChange={setUser}
>
<SelectChild />
</ModalForm>
</Row>
<List
key={type}
renderItem={Item}
renderEmpty={<Empty title='暫無記錄' />}
url={type ? 'store/refund' : 'store/distribution'}
data={{
salesman_id: user
}}
/>
</TopView>
)
}
const SelectChild = ({ value, ...props }) => {
return (
<Row items='center' {...props}>
<Text size={2}>{value || '全部業務員'}</Text>
<ArecaIcon name='arrow_down_fill' className='text-s4 text-c2' />
</Row >
)
}
const Item = ({ item }) => {
return <Card margin disableMarginBottom className='gap-3'>
<Row items='center'>
<ArecaIcon className='text-c1 text-s7' name='store' />
<Text size={2} style={{ marginLeft: px(4) }}>{item.store_name}</Text>
<ArecaIcon className='text-c3 text-s5' name='you2' />
</Row>
{
item.goods.map(good => <Row className='gap-3' key={good.id}>
<Image style={{ width: px(160) }} square className='r-2' src={good.image} />
<Column grow justify='between'>
<Text size={2} bold numberOfLines={2}>{good.title}</Text>
<Text size={2} color={3}>規格:{good.spec}</Text>
<Text size={2} color={3}>數量:{good.num}</Text>
</Column>
</Row>)
}
<Column className='r-2 bg-page p-3 gap-2'>
<Row>
<Row grow items='center'>
<ArecaIcon className='text-secondary text-s7' name='man_mine' />
<Text size={2}>{item.salesman_name || '-'}</Text>
</Row>
<Row grow items='center'>
<ArecaIcon className='text-secondary text-s7' name='shiwu-shouji' />
<Text size={2}>{item.salesman_tel || '-'}</Text>
</Row>
</Row>
<Row>
<Row grow items='center'>
<ArecaIcon className='text-secondary text-s7' name='map' />
<Text size={2}>{item.area}</Text>
</Row>
<Row grow items='center'>
<ArecaIcon className='text-secondary text-s7' name='shijian1' />
<Text size={2}>{item.created_at}</Text>
</Row>
</Row>
</Column>
</Card>
}
使用hook快速請求資料
這裡是指的使用useRequest
替代request
快速獲取資料,而不需要在編寫具體請求邏輯
import { TopView, Header, Card, Text, ScrollView, Space, HtmlView, useRoute } from '@/duxui'
import { useRequest } from '@/arecaShop'
export default function HelpDetail() {
const { params } = useRoute()
const [detail] = useRequest(`tools/magic/help/${params.id}`)
return (
<TopView isSafe>
<Header title='幫助詳情' />
<ScrollView >
<Card shadow={false} margin>
<Space size={32}>
<Text bold size={42} >{detail.title}</Text>
<HtmlView html={detail.content} />
</Space>
</Card>
</ScrollView>
</TopView>
)
}
使用現有模組
這個專案中的 購物訂單流程、售後退換、文章釋出等功能,在之前的模組中都已經是開發過的功能,並且他們都是成熟可用的,我們只需要直接使用他們就行了
{
"name": "arecaShop",
"description": "大工匠檳榔商城",
"version": "1.0.0",
"dependencies": [
"duxcmsMall",
"amap"
]
}
在我這個專案模組的配置檔案中,將 duxcmsMall
新增到依賴中,這是商城模組他提供了商品、訂單、售後、購物車、收貨地址等功能
因為當前專案需求是積分兌換商品,但是預設的商城不支援積分功能,下面介紹是使用渲染鉤子來修改為積分商品
使用渲染鉤子對商城進行修改
使用RenderHook,將商城購物流程修改為積分兌換流程,這個檔案需要在模組入口檔案中匯入
import { mallHook, orderHook, Price } from '@/duxcmsMall'
import { Card, contextState, Row, Text } from '@/duxui'
const ListPrice = ({ item, children }) => {
if (item.type === 'point') {
return <Text bold size={4} type='danger'>{item.sell_point}積分</Text>
}
return children
}
mallHook.add('goods.list.item.sellPrice', ListPrice)
mallHook.add('MallCateQuick.item.sellPrice', ListPrice)
mallHook.add('MallList.item.sellPrice', ListPrice)
mallHook.add('detail.info.price', ({ children }) => {
const [data] = contextState.useState()
if (data.type !== 'point') {
return children
}
return <Row className='gap-2' items='center'>
<Text size={40} bold color={4}>
{data.sell_point}積分
</Text>
<Price size={1} delete color={4} className='mt-2'>{data.market_price}</Price>
</Row>
})
mallHook.add('GoodsSpec.price', ({ children, data, item }) => {
if (data.type !== 'point') {
return children
}
return <Text size={48} bold type='danger'>
{item?.sell_point || data.sell_point}積分
</Text>
})
orderHook.add('order.create.data.total', ({ store }) => {
// const isPoint = store.items.some(v => v.type === 'point')
return <>
<Row items='center' justify='between'>
<Text bold>商品金額</Text>
<Price color={2}>{store.total.order_price}</Price>
</Row>
<Row items='center' justify='between'>
<Text bold>運費</Text>
<Price color={2}>{store.total.delivery_price}</Price>
</Row>
{
store.discount.map(item => <Row key={item.name} items='center' justify='between'>
<Text bold>{item.desc}</Text>
<Text type='danger'>-¥{item.price}</Text>
</Row>)
}
{/* {+store.total.discount_price > 0 && <Row items='center' justify='between'>
<Text bold>{isPoint ? '積分抵扣' : '優惠'}</Text>
<Price type='danger'>{-store.total.discount_price}</Price>
</Row>} */}
</>
})
orderHook.add('order.detail.total', () => {
const [{ data }] = contextState.useState()
return <Card margin disableMarginBottom className='gap-3'>
<Row items='center' justify='between'>
<Text color={2}>訂單總額</Text>
<Price bold color={1}>{data.order_price}</Price>
</Row>
<Row items='center' justify='between'>
<Text color={2}>運費</Text>
<Price bold color={1}>{data.delivery_price}</Price>
</Row>
{
data.discount_data?.map(item => <Row key={item.name} items='center' justify='between'>
<Text color={2}>{item.desc}</Text>
<Text bold type='danger'>-¥{item.price}</Text>
</Row>)
}
<Row items='center' justify='between'>
<Text color={2}>實付款</Text>
<Price bold type='primary'>{data.pay_price}</Price>
</Row>
</Card>
})
總結
上面提到的就是用於快速開發的主要方法,當你熟練掌握這些方法後,你的開發速度將一騎絕塵
當然這些上面提到這些並不是全部,你可以閱讀開發文件,從中獲取更多的使用方法
請前往開發文件檢視詳細教程
開發文件:http://duxapp.cn/
GitHub:https://github.com/duxapp