Commit a86ad241 by peii

产品

parent 40d3d481
......@@ -2,7 +2,7 @@
* @FilePath: /BoneHouse_Business_APP/src/pages/order/productions/common.tsx
* @Author: peii
* @Date: 2021-07-16 17:04:20
* @LastEditTime: 2021-07-16 17:53:15
* @LastEditTime: 2021-08-05 17:45:16
* @LastEditors: peii
* @Vision: 1.0
* @Description: 一些产品的通用组件
......@@ -10,8 +10,7 @@
// @ts-nocheck
import React, { Component } from 'react'
import { View, Text, Image } from 'react-native'
import { ISupplier } from 'bonehouse'
import { View, Text, Image, ActivityIndicator } from 'react-native'
import * as R from 'ramda'
import { g, isBlank, isNotBlank } from '../../../utils/utils'
import styles from './index.styl'
......@@ -22,7 +21,7 @@ import { TYPES } from '../../../inversify/types'
const store = container.get(TYPES.Store)
type ITextImageProps = {
size: string
big: boolean
image?: string
text?: string
colorNumber: string
......@@ -32,24 +31,50 @@ type ITextImageProps = {
* @description: 文字图片
* @return {*}
*/
export function TextImage({ size, image, text, colorNumber }: ITextImageProps) {
export function TextImage({ big, image, text = '图片', colorNumber }: ITextImageProps) {
const numClass = isNotBlank(colorNumber) ? `text-icon-${colorNumber}` : ''
const style = isNotBlank(size) ? { width: size, height: size } : {}
text = R.take(4, text)
text = R.compose(R.ifElse(R.compose(R.lt(3), R.length), R.take(4), R.take(2)), R.replace(/[(-)::]/g, ''))(text)
return (
<View style="text-image">
{isBlank(image) ? (
<View style={[g(styles, 'text-image__text-icon', numClass), style]}>
<Text style={g(styles, 'text-image__text-icon-text', `${numClass}__text`)}>{text}</Text>
<View
style={[g(styles, { 'text-image__text-icon': true, [numClass]: true, 'text-image__text-icon-big': big })]}
>
<Text
style={g(styles, {
'text-image__text-icon-text': true,
[`${numClass}__text`]: true,
'text-image__text-icon-text-big': big,
})}
>
{text}
</Text>
</View>
) : (
<Image
source={{ uri: store.host + IMAGE_PREFIX + image }}
style={[g(styles, 'text-image__icon'), style]}
style={[g(styles, { 'text-image__icon': true, 'text-image__icon-big': big })]}
resizeMode="contain"
/>
)}
</View>
)
}
/**
* @description: 加载
* @param {*} param1
* @return {*}
*/
export function Loading({ text = '加载中', color, clzss }) {
const style = {}
color && (style.color = color)
return (
<View style={[g(styles, 'loading'), clzss]}>
<ActivityIndicator style={[g(styles, 'loading-icon')]} color={color || '#999'} />
{isNotBlank(text) && <Text style={[g(styles, 'loading-text'), style]}>{text}</Text>}
</View>
)
}
......@@ -2,6 +2,7 @@
@import '../../../assets/styles/variable.styl'
iconWidth = 44px
iconWidthBig = 58px
colors = {
'1':
}
......@@ -34,6 +35,10 @@ colors = {
width iconWidth
height iconWidth
&-big
width iconWidthBig
height iconWidthBig
&__text-icon
width iconWidth
height iconWidth
......@@ -42,16 +47,28 @@ colors = {
align-items center
borderWidth 2px
&-big
width iconWidthBig
height iconWidthBig
borderRadius 29px
&-text
font-size 14px
font-family font_family_semibold
padding 3px
text-align center
line-height 18px
for i in 1 .. 50
&-big
font-size 18px
line-height 22px
for i in 1...50
.text-icon-{i}
borderColor hsl(i * 50, 50%, 50%)
.text-icon-{i}__text
color hsl(i * 30, 50%, 50%)
color hsl(i * 50, 50%, 50%)
.body
width 100%
......@@ -66,7 +83,7 @@ for i in 1 .. 50
height 60px
padding-left 5px
border-bottom-width 1px
border-bottom-color rgba(0, 0, 0, 0.1)
border-bottom-color rgba(99, 99, 99, 0.1)
@extend .row
@extend .center
......@@ -99,9 +116,65 @@ for i in 1 .. 50
.pro
flex 1
background-color foundation_color
padding-left 20px
&-header
border-bottom-width 1px
border-bottom-color #ddd
padding 10px 20px
&__text
font-size 16px
color primary_text_color
font-family font_family_semibold
font-weight bold
&-loading
height 200px
&-empty
height 100px
justify-content center
align-items center
flex-direction row
border-bottom-width 1px
border-bottom-color rgba(99, 99, 99, 0.1)
&__icon
width 20px
height @width
margin-top 3px
margin-right 5px
&__text
font-size 18px
font-family font_family_semibold
color #999
&-item
@extend .row
padding 10px 0
margin-left 20px
border-bottom-width 1px
border-bottom-color rgba(99, 99, 99, 0.1)
align-items center
&__img
margin-right 10px
&__field
&-text
font-size third_text_size
color second_text_color
font-family font_family_semibold
&-title
font-size 16px
color first_text_color
&-only
font-size 16px
color first_text_color
.loading
justify-content center
align-items center
\ No newline at end of file
......@@ -2,7 +2,7 @@
* @FilePath: /BoneHouse_Business_APP/src/pages/order/productions/production.tsx
* @Author: peii
* @Date: 2021-07-16 15:36:02
* @LastEditTime: 2021-08-04 00:03:18
* @LastEditTime: 2021-08-05 17:54:48
* @LastEditors: peii
* @Vision: 1.0
* @Description: 产品列表
......@@ -10,11 +10,13 @@
// @ts-nocheck
import React, { Component } from 'react'
import { View, Text, ScrollView, FlatList } from 'react-native'
import { View, Text, FlatList, Image } from 'react-native'
import { inject, observer } from 'mobx-react'
import { ISupplier } from 'bonehouse'
import { ICategory } from 'bonehouse'
import { toJS } from 'mobx'
import * as R from 'ramda'
import { g, getFormItem, isBlank, isNotBlank, show, translateSysprofile } from '../../../utils/utils'
import { g, isBlank, isNotBlank, show } from '../../../utils/utils'
import { TextImage, Loading } from './common'
import styles from './index.styl'
type IField = {
......@@ -28,28 +30,59 @@ type IProps = {
productionStore: {
productionFields: IField[]
productions: any[]
imgFields: { sourceField: string; textField: string }
loading: boolean
getProductions: Function
activeCatetory: ICategory
}
}
type IState = {}
class Production extends Component<IProps, IState> {
state = {
refreshing: false,
}
async onPullDownRefresh() {
this.setState({ refreshing: true })
await this.props.productionStore.getProductions(false)
this.setState({ refreshing: false })
}
renderItem({ item, index }) {
const productionFields = this.props.productionStore.productionFields
console.log(item)
const imgFields = this.props.productionStore.imgFields
return (
<View style={g(styles, 'pro-item')}>
<View style={g(styles, 'pro-item__img')}>
<TextImage
big={true}
image={
item[imgFields.sourceField] && item[imgFields.sourceField].length > 0
? R.head(item[imgFields.sourceField])
: ''
}
text={item[imgFields.textField]}
colorNumber={(index + 1) % 50}
/>
</View>
<View style={g(styles, 'pro-item__info')}>
{productionFields.map((field, idx) => {
return (
<View key={field.field} style={g(styles, 'pro-item__field')}>
<Text
style={[
g(styles, { 'pro-item__field-text': true, 'pro-item__field-text-title': field.type === 'title' }),
field.style,
]}
numberOfLines={2}
style={g(styles, {
'pro-item__field-text': true,
'pro-item__field-title': field.type === 'title',
'pro-item__field-only': field.type === 'only',
[field.style]: !!field.style,
})}
>
{field.type === 'title' ? (
{/* 单项或者title都加序号 */}
{R.includes(field.type, ['title', 'only']) ? (
<Text>
{index + 1 + '.'} {item[field.field]}
</Text>
......@@ -61,22 +94,53 @@ class Production extends Component<IProps, IState> {
)
})}
</View>
</View>
)
}
render() {
const productions = this.props.productionStore.productions
const productions = toJS(this.props.productionStore.productions)
const loading = this.props.productionStore.loading
const activeCatetory = toJS(this.props.productionStore.activeCatetory)
const { refreshing } = this.state
return (
<View style={g(styles, 'pro')}>
{isNotBlank(activeCatetory) && <Header title={activeCatetory.categoryName} />}
{loading ? (
<Loading clzss={g(styles, 'pro-loading')} text="努力加载中" />
) : (
<FlatList
style={g(styles, 'pro-list')}
data={productions}
renderItem={this.renderItem.bind(this)}
keyExtractor={item => item.itemCode || item.templateNumber}
keyExtractor={item => item.serialNumber || item.itemCode || item.templateNumber || item.categoryCode}
ListEmptyComponent={Empty}
refreshing={refreshing}
onRefresh={this.onPullDownRefresh.bind(this)}
/>
)}
</View>
)
}
}
const Header = ({ title }) => {
return (
<View style={g(styles, 'pro-header')}>
<Text style={g(styles, 'pro-header__text')}>{title}</Text>
</View>
)
}
const Empty = () => {
return (
<View style={g(styles, 'pro-empty')}>
<Image style={g(styles, 'pro-empty__icon')} source={require('../../../assets/images/empty-list.png')} />
<Text style={g(styles, 'pro-empty__text')}>暂无数据</Text>
</View>
)
}
export default inject('productionStore')(observer(Production))
......@@ -2,7 +2,7 @@
* @FilePath: /BoneHouse_Business_APP/src/pages/order/productions/supplier.tsx
* @Author: peii
* @Date: 2021-07-15 12:07:24
* @LastEditTime: 2021-07-16 17:44:43
* @LastEditTime: 2021-08-04 17:56:36
* @LastEditors: peii
* @Vision: 1.0
* @Description: 供应商列表
......@@ -93,7 +93,7 @@ class Supplier extends Component<IProps> {
this.supplierClickHandler(supplier)
}}
>
<TextImage size={42} colorNumber={index + 1} image={icon} text={supplier.supplierShortName} />
<TextImage colorNumber={index + 1} image={icon} text={supplier.supplierShortName} />
</TouchableOpacity>
)
})}
......
......@@ -116,7 +116,7 @@ function createNavigator() {
Productions: { screen: Productions },
Success: { screen: Success },
},
{ initialRouteName: 'Main', ...options },
{ initialRouteName: 'Productions', ...options },
)
return createAppContainer(stackNavigator)
......
......@@ -2,7 +2,7 @@
* @FilePath: /BoneHouse_Business_APP/src/stores/production.ts
* @Author: peii
* @Date: 2021-07-15 10:49:02
* @LastEditTime: 2021-08-03 23:57:52
* @LastEditTime: 2021-08-05 18:05:15
* @LastEditors: peii
* @Vision: 1.0
* @Description: 产品store
......@@ -50,7 +50,7 @@ export default class Production {
// 手术模板显示
SURGERY_TEMPLATE: [
{ field: 'templateName', label: '', type: 'title' },
{ field: 'customerName', label: '客户', style: 'pro-item__text-big' },
{ field: 'customerName', label: '客户', style: 'pro-item__field-text-big' },
{ field: 'doctorName', label: '手术医生' },
{ field: 'surgeryTypeName', label: '手术类型' },
{ field: 'templateDesc', label: '模板说明', style: 'pro-item__text-small' },
......@@ -58,14 +58,14 @@ export default class Production {
// 钉盒及器械包
package: [
{ field: 'itemName', label: '', type: 'title' },
{ field: 'generalName', label: '通用名称', style: 'pro-item__text-big' },
{ field: 'generalName', label: '通用名称', style: 'pro-item__field-text-big' },
{ field: 'specification', label: '规格型号' },
{ field: 'serialNumber', label: '物料序列' },
],
// 零散器械
SCATTERED_EQUIPMENT: [
{ field: 'manufacturerProductCode', label: '', type: 'title' },
{ field: 'itemName', label: '物料名称', style: 'pro-item__text-big' },
{ field: 'itemName', label: '物料名称', style: 'pro-item__field-text-big' },
{ field: 'generalName', label: '通用名称' },
{ field: 'specification', label: '规格型号' },
// { field: 'itemCode', label: '', style: 'production-item__text-small' },
......@@ -73,10 +73,13 @@ export default class Production {
// 耗材
materials: [
{ field: 'itemCode', label: '', type: 'title' },
{ field: 'itemName', label: '物料名称', style: 'pro-item__text-big' },
{ field: 'itemName', label: '物料名称', style: 'pro-item__field-text-big' },
{ field: 'generalName', label: '通用名称' },
{ field: 'specification', label: '规格型号' },
],
// 耗材大类
subMaterialCategory: [{ field: 'categoryName', label: '', type: 'only' }],
}
// 图片字段
......@@ -97,11 +100,16 @@ export default class Production {
sourceField: 'photos',
textField: 'itemName',
},
subMaterialCategory: {
textField: 'categoryName',
},
}
@observable orgCode: string = ''
@observable activeSupplier!: ISupplier
@observable activeCatetory!: ICategory
@observable activeSubCategory!: ICategory
@observable loading: boolean = false
@persist('map')
@observable
......@@ -111,7 +119,6 @@ export default class Production {
@observable
_categories: ObservableMap<string, ICategory[]> = new ObservableMap()
@persist('map')
@observable
_productions: ObservableMap<string, any[]> = new ObservableMap()
......@@ -134,6 +141,8 @@ export default class Production {
if (isBlank(this.orgCode) || isBlank(this.activeSupplier) || isBlank(this.activeCatetory)) {
return []
}
console.log(this.currentProductionKey)
return this._productions.get(this.currentProductionKey)
}
......@@ -152,8 +161,31 @@ export default class Production {
}
let fields = this.showFields[this.activeCatetory.categoryCode]
if (isBlank(fields)) {
if (isNotBlank(this.productions) && R.pathEq([0, '_type'], 'SUB_CATEGORY', this.productions)) {
fields = this.showFields.subMaterialCategory
} else {
fields = this.showFields.materials
}
}
return fields
}
@computed
get imgFields() {
if (isBlank(this.orgCode) || isBlank(this.activeSupplier) || isBlank(this.activeCatetory)) {
return {}
}
if (R.includes(this.activeCatetory.categoryCode, ['1301', '1302'])) {
return this.imageFields.package
}
let fields = this.imageFields[this.activeCatetory.categoryCode]
if (isBlank(fields)) {
if (isNotBlank(this.productions) && R.pathEq([0, '_type'], 'SUB_CATEGORY', this.productions)) {
fields = this.imageFields.subMaterialCategory
} else {
fields = this.imageFields.materials
}
}
return fields
}
......@@ -171,22 +203,25 @@ export default class Production {
setActiveSupplier(supplier: ISupplier) {
this.activeSupplier = supplier
// 选择完供应商后,看当前有没有产品类别,没有就请求,有且没有已选择的类别,选第一个
if (isBlank(this.categories)) {
this.getCategory(supplier.supplierCode)
} else if (
isBlank(this.activeCatetory) ||
R.compose(
R.complement(R.includes)(this.activeCatetory.categoryCode),
R.pluck('categoryCode'),
)(this.defaultCategories)
) {
// if (isBlank(this.categories)) {
// this.getCategory(supplier.supplierCode)
// } else if (
// isBlank(this.activeCatetory) ||
// R.compose(
// R.complement(R.includes)(this.activeCatetory.categoryCode),
// R.pluck('categoryCode'),
// )(this.defaultCategories)
// ) {
if (isNotBlank(this.categories)) {
this.setActiveCategory(R.head(this.categories as any) as any)
}
// }
}
@action
setActiveCategory(category: ICategory) {
this.activeCatetory = category
this.loading = false
if (isBlank(this.productions)) {
this.getProductions()
......@@ -224,6 +259,7 @@ export default class Production {
this._suppliers.set(orgCode, suppliers as ISupplier[])
if (isNotBlank(suppliers)) {
R.compose(R.map(this.getCategory.bind(this)), R.pluck('supplierCode'))(suppliers)
this.setActiveSupplier(R.head(suppliers as any) as any)
}
})
......@@ -252,88 +288,158 @@ export default class Production {
* @param {*}
* @return {*}
*/
getProductions() {
async getProductions(loading = true) {
if (isBlank(this.orgCode) || isBlank(this.activeSupplier)) return
switch (this.activeCatetory.categoryCode) {
// 手术模板
case 'SURGERY_TEMPLATE':
this.getSurgeryTemplates()
await this.getSurgeryTemplates(loading)
break
// 手术模板
case '1301':
case '1302':
this.getPackages()
await this.getPackages(loading)
break
// 零散器械
case 'SCATTERED_EQUIPMENT':
this.getTools()
await this.getTools(loading)
break
// 骨科耗材
default:
this.getItemDetail()
await this.getItemDetail(loading)
break
}
}
addSupplierAndCategoryCode = R.curry((supplierCode: string, categoryCode: string, item: any) => {
item._supplierCode = supplierCode
item._categoryCode = categoryCode
return item
})
/**
* @description: 请求手术模板
* @param {*} function
* @return {*}
*/
getSurgeryTemplates = flow(function* (this: Production) {
getSurgeryTemplates = flow(function* (this: Production, loading: boolean) {
const params = {
orgCode: this.orgCode,
manufacturerCode: this.activeSupplier.supplierCode,
}
if (loading) {
this.loading = true
}
const res = yield this.service.getSurgeryTemplates(params)
this.loading = false
if (res.errorCode) return
this._productions.set(this.currentProductionKey, R.pathOr([], ['data', 'surgeryTemplateHeaders'])(res))
const key = `${params.orgCode}_${params.manufacturerCode}_SURGERY_TEMPLATE`
this._productions.set(
key,
R.compose(
R.map(this.addSupplierAndCategoryCode(params.manufacturerCode, 'SURGERY_TEMPLATE')),
R.sort(R.ascend(R.prop('templateNumber'))),
R.pathOr([], ['data', 'surgeryTemplateHeaders']),
)(res),
)
})
/**
* @description: 请求工具包
* @return {*}
*/
getPackages = flow(function* (this: Production) {
getPackages = flow(function* (this: Production, loading: boolean) {
const params = {
manufacturerCode: this.activeSupplier.supplierCode,
categoryCode: this.activeCatetory.categoryCode,
}
if (loading) {
this.loading = true
}
const res = yield this.service.getItemPackage(params)
this.loading = false
if (res.errorCode) return
this._productions.set(this.currentProductionKey, R.pathOr([], ['data', 'items'])(res))
const key = `${this.orgCode}_${params.manufacturerCode}_${params.categoryCode}`
this._productions.set(
key,
R.compose(
R.map(this.addSupplierAndCategoryCode(params.manufacturerCode, params.categoryCode)),
R.uniqBy(R.prop('serialNumber')),
R.pathOr([], ['data', 'items']),
)(res),
)
})
/**
* @description: 零散工具
* @return {*}
*/
getTools = flow(function* (this: Production) {
getTools = flow(function* (this: Production, loading: boolean) {
const params = {
manufacturerCode: this.activeSupplier.supplierCode,
}
if (loading) {
this.loading = true
}
const res = yield this.service.getTools(params)
this.loading = false
if (res.errorCode) return
this._productions.set(this.currentProductionKey, R.pathOr([], ['data', 'tools'])(res))
const key = `${this.orgCode}_${params.manufacturerCode}_SCATTERED_EQUIPMENT`
this._productions.set(
key,
R.compose(
R.map(this.addSupplierAndCategoryCode(params.manufacturerCode, 'SCATTERED_EQUIPMENT')),
R.pathOr([], ['data', 'tools']),
)(res),
)
})
/**
* @description: 耗材
* @return {*}
*/
getItemDetail = flow(function* (this: Production) {
getItemDetail = flow(function* (this: Production, loading: boolean) {
const params = {
orgCode: this.orgCode,
manufacturerCode: this.activeSupplier.supplierCode,
categoryCode: this.activeCatetory.categoryCode,
}
if (loading) {
this.loading = true
}
const res = yield this.service.getItemDetail(params)
this.loading = false
if (res.errorCode) return
this._productions.set(this.currentProductionKey, R.pathOr([], ['data', 'details'])(res))
const key = `${this.orgCode}_${params.manufacturerCode}_${params.categoryCode}`
// 没有大类,直接返回了物料列表
if (R.compose(R.isNil, R.path(['data', 'items']))(res)) {
this._productions.set(
key,
R.compose(
R.map(this.addSupplierAndCategoryCode(params.manufacturerCode, params.categoryCode)),
R.pathOr([], ['data', 'details']),
)(res),
)
}
// 还有一层分类
else {
this._productions.set(
key,
R.compose(
R.map(item => {
item._type = 'SUB_CATEGORY'
return item
}),
R.map(this.addSupplierAndCategoryCode(params.manufacturerCode, params.categoryCode)),
R.pathOr([], ['data', 'items']),
)(res),
)
}
})
}
......@@ -214,5 +214,6 @@ declare module 'bonehouse' {
categoryName: string
categoryIcon?: string
categoryImage?: string
details?: ICategory[]
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment