to_number 返回值为 .05 ,少一个小数点前面的0

本文探讨了在使用特定数据库函数获取配置参数时遇到的小数点缺失问题,并提供了可能的解决方案,帮助开发者理解并解决类似数据库配置获取过程中的常见错误。
CREATE OR REPLACE PROCEDURE DFMS.SP_GET_SPAM_Weight_Info_test (
   p_pn          IN   VARCHAR2,
   o_std_weight  out  NUMBER,
.......   
)

IS
   v_range  NUMBER;
   v_res    varchar2(100);
   v_minweight  varchar(10);
   ex       exception;
BEGIN
   o_std_weight:='0.0';
   o_pn_desc:='';
   o_mc_code:='';
   o_res :='OK';
   
   v_range := TO_NUMBER (function_get_singlecontrolvalue ('ALL', 'SPAM-WEIGHT-RANGE', '0.05'));   
......



注意  function_get_singlecontrolvalue ('ALL', 'SPAM-WEIGHT-RANGE', '0.05')  返回值为varchar2 类型。  


select   function_get_singlecontrolvalue ('ALL', 'SPAM-WEIGHT-RANGE', '0.05')   from  dual ;  发现返回值为 0.05

select   to_number(function_get_singlecontrolvalue ('ALL', 'SPAM-WEIGHT-RANGE', '0.05'))  from  dual ;  返回值也为 0.05  



但是在Toad中单步调试这个procedure 的时候,  代入值执行发现 v_range 的值为 .05 , 而不是 0.05 , 缺少一个小数点前面的 0,
同样的语句在另外一个结构差不多的10g数据库中却可以正常返回 0.05 , Toad也换了几个版本, 都是一样的结果 。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/35489/viewspace-669546/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/35489/viewspace-669546/

#include "modbus.h" MODBUS_SLAVE Modbus_Slave; //modbus从设备栈 串口2结构体实例化 MODBUS_SLAVE Modbus_Slave_Exp; //modbus拓展从设备栈 串口1结构体实例化 MODBUS_MASTER Modbus_Master; //modbus主设备栈 串口3结构体实例化 volatile uint16_t Master_Time_Out = 0; volatile uint16_t Master_TX_Count = 0; /******************************************************************************* * @brief //串口1初始化,串口1主要连接485显示屏(非隔离485)TX是通道DMA0,CH6,RX是DMA0,CH5 * @param[in] * @param[out] 无 * @return 无 *******************************************************************************/ void Modbus_Slave_Exp_Init(uint32_t bound) { dma_parameter_struct dma_init_struct; // 使能时钟 rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_USART1); rcu_periph_clock_enable(RCU_DMA0); // 配置PA9(TX), PA10(RX), PA8(DE) gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8); RS4851_TX_OFF; // DE初始低电平 // 配置USART1 usart_deinit(USART1); usart_baudrate_set(USART1, bound); usart_word_length_set(USART1, USART_WL_8BIT); usart_stop_bit_set(USART1, USART_STB_1BIT); usart_parity_config(USART1, USART_PM_NONE); usart_hardware_flow_rts_config(USART1, USART_RTS_DISABLE); usart_hardware_flow_cts_config(USART1, USART_CTS_DISABLE); usart_receive_config(USART1, USART_RECEIVE_ENABLE); usart_transmit_config(USART1, USART_TRANSMIT_ENABLE); usart_enable(USART1); // 配置DMA发送(TX) dma_deinit(DMA0, DMA_CH6); dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_addr = (uint32_t)Modbus_Slave_Exp.Data; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; dma_init_struct.number = 256; dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART1); dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; dma_init(DMA0, DMA_CH6, &dma_init_struct); // 配置DMA接收(RX) dma_deinit(DMA0, DMA_CH5); dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; dma_init_struct.memory_addr = (uint32_t)Modbus_Slave_Exp.RxBuf; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; dma_init_struct.number = 256; dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART1); dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.priority = DMA_PRIORITY_HIGH; dma_init(DMA0, DMA_CH5, &dma_init_struct); dma_circulation_enable(DMA0, DMA_CH5); // 循环模式 // 启用DMA dma_channel_enable(DMA0, DMA_CH5); // 使能接收DMA usart_dma_receive_config(USART1, USART_RECEIVE_DMA_ENABLE); usart_dma_transmit_config(USART1, USART_TRANSMIT_DMA_ENABLE); // 添加空闲中断 usart_interrupt_enable(USART1, USART_INT_IDLE); nvic_irq_enable(USART1_IRQn, 1, 0); } /******************************************************************************* * @brief //串口2初始化,串口2主要作为升级调试口。TX是通道DMA0,CH1,RX是DMA0,CH2 * @param[in] * @param[out] 无 * @return 无 *******************************************************************************/ void Modbus_Slave_Init(uint32_t bound) { dma_parameter_struct dma_init_struct; // 使能时钟 rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_USART2); // 配置PA2(TX), PA3(RX), PA4(DE) gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2); gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_3); // 配置PA4为推挽输出模式 (DE控制线) gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4); gpio_bit_reset(GPIOA, GPIO_PIN_4); // 初始接收模式 // 3. 配置USART2 usart_deinit(USART2); usart_baudrate_set(USART2, bound); usart_word_length_set(USART2, USART_WL_8BIT); usart_stop_bit_set(USART2, USART_STB_1BIT); usart_parity_config(USART2, USART_PM_NONE); usart_hardware_flow_rts_config(USART2, USART_RTS_DISABLE); usart_hardware_flow_cts_config(USART2, USART_CTS_DISABLE); usart_receive_config(USART2, USART_RECEIVE_ENABLE); usart_transmit_config(USART2, USART_TRANSMIT_ENABLE); usart_enable(USART2); // 配置DMA发送(TX) dma_deinit(DMA0, DMA_CH1); dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_addr = (uint32_t)Modbus_Slave.Data; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; dma_init_struct.number = 256; dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART2); dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH; dma_init(DMA0, DMA_CH1, &dma_init_struct); // 配置DMA接收(RX) dma_deinit(DMA0, DMA_CH2); dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; dma_init_struct.memory_addr = (uint32_t)Modbus_Slave.RxBuf; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; dma_init_struct.number = 256; dma_init_struct.periph_addr = (uint32_t)&USART_DATA(USART2); dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.priority = DMA_PRIORITY_HIGH; dma_init(DMA0, DMA_CH2, &dma_init_struct); // 启用DMA dma_channel_enable(DMA0, DMA_CH2); // 使能接收DMA usart_dma_receive_config(USART2, USART_RECEIVE_DMA_ENABLE); usart_dma_transmit_config(USART2, USART_TRANSMIT_DMA_ENABLE); // 添加空闲中断 usart_interrupt_enable(USART2, USART_INT_IDLE); nvic_irq_enable(USART2_IRQn, 1, 0); } /******************************************************************************* * @brief //串口3初始化,串口3作为主站,主要逆变器通信(响应和发送)TX是通道DMA1,CH4,RX是DMA2,CH2 * @param[in] * @param[out] 无 * @return 无 *******************************************************************************/ void Modbus_Master_init(uint32_t bound) { dma_parameter_struct dma_init_struct; // 1. 使能外设时钟 rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_UART3); rcu_periph_clock_enable(RCU_DMA1); // USART2使用DMA1 // 2. 配置GPIO引脚 gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10); // TX gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_11); // RX gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12); // DE RS4853_TX_OFF;//DE初始低电平 // 3. 配置USART3参数 usart_deinit(UART3); usart_baudrate_set(UART3, bound); usart_word_length_set(UART3, USART_WL_8BIT); usart_stop_bit_set(UART3, USART_STB_1BIT); usart_parity_config(UART3, USART_PM_NONE); usart_hardware_flow_rts_config(UART3, USART_RTS_DISABLE); usart_hardware_flow_cts_config(UART3, USART_CTS_DISABLE); usart_receive_config(UART3, USART_RECEIVE_ENABLE); usart_transmit_config(UART3, USART_RECEIVE_DMA_ENABLE); usart_enable(UART3); // 4. 配置DMA发送 (TX) dma_deinit(DMA1, DMA_CH4); dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; dma_init_struct.memory_addr = (uint32_t)Modbus_Master.TxData; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; dma_init_struct.number = 256; // 传输长度在发送时设置 dma_init_struct.periph_addr = (uint32_t)&USART_DATA(UART3); dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.priority = DMA_PRIORITY_MEDIUM; dma_init(DMA1, DMA_CH4, &dma_init_struct); // 5. 配置DMA接收 (RX) dma_deinit(DMA1, DMA_CH2); dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; dma_init_struct.memory_addr = (uint32_t)Modbus_Master.Rxbuf; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; dma_init_struct.number = 256; dma_init_struct.periph_addr = (uint32_t)&USART_DATA(UART3); dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.priority = DMA_PRIORITY_HIGH; dma_init(DMA1, DMA_CH2, &dma_init_struct); // 6. 启用DMA dma_circulation_enable(DMA1, DMA_CH2); // 接收循环模式 dma_channel_enable(DMA1, DMA_CH2); usart_dma_receive_config(UART3, USART_RECEIVE_DMA_ENABLE); usart_dma_transmit_config(UART3, USART_RECEIVE_DMA_ENABLE); Modbus_Master.TxID =0x01; } /********************************** *********************************** 指定的串口发送数据 *********************************** **********************************/ void USART_DMA_TX(uint32_t usart_periph, uint8_t *data, uint16_t length) { if(usart_periph == USART1) { RS4851_TX_ON; // 切换为发送模式 dma_flag_clear(DMA0,DMA_CH6,DMA_FLAG_FTF); usart_interrupt_flag_clear(USART1,USART_INT_FLAG_TC); dma_channel_disable(DMA0, DMA_CH6); memcpy(Modbus_Slave_Exp.Data, data, length); DMA_CHCNT(DMA0, 6) = length; DMA_CHMADDR(DMA0, 6) = (uint32_t)Modbus_Slave_Exp.Data; usart_interrupt_enable(USART1,USART_INT_TC); dma_channel_enable(DMA0, DMA_CH6); usart_dma_transmit_config(USART1,USART_TRANSMIT_DMA_ENABLE); } if(usart_periph == USART2) { dma_flag_clear(DMA0,DMA_CH1,DMA_FLAG_FTF); usart_interrupt_flag_clear(USART2,USART_INT_FLAG_TC); dma_channel_disable(DMA0, DMA_CH1); memcpy(Modbus_Slave.Data, data, length); DMA_CHCNT(DMA0, 1) = length; DMA_CHMADDR(DMA0, 1) = (uint32_t)Modbus_Slave.Data; usart_interrupt_enable(USART2,USART_INT_TC); dma_channel_enable(DMA0, DMA_CH1); usart_dma_transmit_config(USART2,USART_TRANSMIT_DMA_ENABLE); } if(usart_periph == UART3) { RS4851_TX_ON; // 切换为发送模式 dma_channel_disable(DMA1, DMA_CH4); memcpy(Modbus_Master.TxData, data, length); DMA_CHCNT(DMA1, 4) = length; DMA_CHMADDR(DMA1, 4) = (uint32_t)Modbus_Master.TxData; dma_channel_enable(DMA1, DMA_CH4); usart_dma_transmit_config(UART3,USART_TRANSMIT_DMA_ENABLE); } } /******************************************************************************* * @brief //MODBUS CRC校验函数 * @param[in] * @param[out] 无 * @return 无 *******************************************************************************/ void GetCrC(uint8_t *pSource, uint8_t len, uint8_t *crc) { uint16_t crc16 = 0xFFFF; uint8_t i = 0; uint8_t j = 0; if(len > 250) return; while(j < len) { crc16 ^= pSource[j]; for(i = 0; i < 8; i++) { if(crc16 & 0x01) { crc16 >>= 1; crc16 ^= 0xA001; } else { crc16 >>= 1; } } j++; } crc[0] = crc16 % 0x100; crc[1] = crc16 / 0x100; } /******************************************************************************* * @brief //MODBUS 03功能码解析函数 * @param[in] * @param[out] 无 * @return 无 *******************************************************************************/ void Modbus_Slave_ReadReg(uint32_t usart_periph, MODBUS_SLAVE Modbus_Slave) { uint8_t *ptr;//读取数据起始地址指针 uint8_t byte_len;//访问内存字节对齐长度 uint8_t i = 0; uint8_t crc[2] = {0, 0}; uint16_t addr_start;//读取寄存器起始地址 uint16_t reg_len = 0; //读取寄存器的数量 GetCrC(Modbus_Slave.Data, 6, crc); if((Modbus_Slave.ID == Modbus_Slave.Data[0]) && (crc[0] == Modbus_Slave.Data[6]) && (crc[1] == Modbus_Slave.Data[7])) //地址匹配且crc校验通过 { addr_start = (Modbus_Slave.Data[2] << 8) + Modbus_Slave.Data[3]; //获取Modbus读取寄存器的起始地址 if((addr_start >= 0x2300) && (addr_start <= 0x23FF)) //读取保护参数配置0x2300-0x23FF { ptr = (uint8_t*)&Pack_Info; byte_len = 2; addr_start -= 0x2300; } else if((addr_start >= 0x5000) && (addr_start <= 0x50FF)) //单体电压 { ptr = (uint8_t*)&Pack_Info.VCell; byte_len = 2; addr_start -= 0x5000; } else if((addr_start >= 0x6000) && (addr_start <= 0x60FF)) //单体温度 { ptr = (uint8_t*)&Pack_Info.Temp; byte_len = 2; addr_start -= 0x6000; } //回传指令 ptr = ptr + addr_start * byte_len; //寄存器地址匹配存储上的偏移 reg_len = (Modbus_Slave.Data[4] << 8) + Modbus_Slave.Data[5]; //要查询寄存器的个数 if(byte_len == 1) { for(i = 0; i < reg_len; i++) //大端 { Modbus_Slave.Data[3 + i * 2] = 0; Modbus_Slave.Data[3 + i * 2 + 1] = *(ptr + i); } } else if(byte_len == 2) { for(i = 0; i < reg_len; i++) //大端 { Modbus_Slave.Data[3 + i * 2] = *(ptr + i * byte_len + 1); Modbus_Slave.Data[3 + i * 2 + 1] = *(ptr + i * byte_len); } } Modbus_Slave.Data[2] = reg_len * 2; //要返回数据的长度 GetCrC(Modbus_Slave.Data, reg_len * 2 + 3, crc); //获取crc Modbus_Slave.Data[reg_len * 2 + 3] = crc[0]; Modbus_Slave.Data[reg_len * 2 + 4] = crc[1]; USART_DMA_TX(usart_periph, Modbus_Slave.Data, reg_len * 2 + 5); //返回要查询的寄存器值 } } /********************************** *********************************** Modbus从设备处理函数 *********************************** **********************************/ void Modbus_Slave_Handle(void) { if(Modbus_Slave.Complete==1)//收到待处理的Modbus指令 { switch(Modbus_Slave.CMD) { case 0x03://ModBus协议读取数据 Modbus_Slave_ReadReg(MODBUS_SLAVE_USART, Modbus_Slave); break; default: break; } Modbus_Slave.Complete=0; Modbus_Slave.Len=0; } if(Modbus_Slave_Exp.Complete==1)//收到待处理的Modbus拓展通道指令 { switch(Modbus_Slave_Exp.CMD) { case 0x03://ModBus协议读取数据 Modbus_Slave_ReadReg(MODBUS_SLAVE_EXP_USART, Modbus_Slave_Exp); break; default: break; } Modbus_Slave_Exp.Complete=0; Modbus_Slave_Exp.Len=0; } } 串口1用于连接485屏,串口2用于和上位机连接(通过485),串口3用于和逆变器连接。逆变器是ASCII码,但是我需要转化为16进制,通过03功能码传给显示屏。 通 信 协 议 通信协议内容 A. 概述: 本文档是专门阐述关于高智能型UPS的RS485接口通信的。 协议中提供了以下内容: 计算机能够通过一个以回车符<cr>结束的查询指令掌握信息的交流。 UPS则会返回以回车符<cr>结束的相应信息或者执行有关动作。 B. 硬件规范 波特率 ............... : 9600 bps 数据长度 .......... : 8 bits 停止位 ..................... : 1 bit 奇偶校验 .................: 无 通信电缆引脚: 计算机 UPS =================================== A <---------- A B ----------> B C 、通信协议 1 、状态查询: 计算机指令:Q1<cr> UPS返回值 : UPS 状态数据流,例如 (MMM.M NNN.N PPP.P QQQ RR.R S.SS TT.T b7b6b5b4b3b2b1b0 UPS 状态数据流: 为了区分各种不同参量的数据,在每段数值之间都有一个空格符。以下是每段数值的具体含义: a. 启始字节:( b. 输入电压值:MMM.M M是0~9的整数。 单位是伏特。 c. I/P故障电压 :NNN 。N N是0到9的整数 。 单位为伏特 。 ** 用于离线UPS** 其目的是识别短时电压故障 这导致离线UPS进入Invter模式 。如果发生这种情况 在故障发生之前 ,输入电压在查询时将显示正常 在下次查询时仍将显示正常 。 I/P故障电压将保持故障电压直到下一次 查询 。查询后 ,I/P故障电压将与I/P相同 电压 ,直到下一个故障发生 。 **用于在线UPS** 其目的是识别短期公用事业故障 这导致在线UPS进入电池模式 。如果发生这种情况 输入电压在故障前查询时将显示正常 在下次查询时仍将显示正常 。 I/P故障电压将保持公用设施故障电压 ,直到 下一个查询 。查询后 ,I/P电压将与I/P相同 电压 ,直到下一次公用事业故障发生 。 d. 输出电压值:PPP.P P是0~9的整数。 单位是伏特。 e. 输出负载百分比值:QQQ QQQ是相对于最大电流值的一个百分比,而不是一个绝对的数值。 f. 输入频率:RR.R R是0~9的整数。 单位是赫兹。 g. 电池电压 : SS.S or S.SS S是0~9的整数。 对于在线式UPS,使用的是电池单体电压格式S.SS; 对于离线式UPS,使用的是电池整体电压格式SS.S;具体使用何种方式由UPS的类型决定。 h. 温度 : TT.T T是0~9的整数。 单位是摄氏度。 i. UPS状态 :<U> <U> 是一个包含二进制信息的字节,例如<b7b6b5b4b3b2b1b0>. 这里bn 是一个ASCII码字符 ‘0 ’ 或 ‘1 ’。 . UPS 状态列表: Bit Logic 1 Logic 0 7 市电失败 (即时) 市电OK 6 电池低 电池OK 5 AVR 正常 4 UPS故障 非UPS故障 3 UPS类型是离线式 UPS类型是在线式 2 自检模式 非自检模式 1 Shutdown 信号发出 未Shutdown 信号发出 0 蜂鸣器打开 蜂鸣器关闭 j. 停止字节 :回车符<cr> 例子: 计算机指令: Q1<cr> UPS返回值: (208.4 140.0 208.4 034 59.9 2.05 35.0 00100001 <cr> 含义 : 输入电压为 208.4V. I/P fault voltage is 140.0V. 输出电压为 208.4V. 输出电流(负载)为 34 %. 输入频率为 59.9 HZ. 电池单体电压为 2.05V. 温度为 35.0 摄氏度 市电OK , 电池OK ,AVR , 非UPS故障。 2.逆变器远程开关机设定计算机: 1) SO<cr> (是字母 O) 如果逆变器接收指令并开机,UPS 将回答: “ ACK ” 2) SF<cr> 如果逆变器接收指令并关机,UPS 将回答: “ ACK ” 3) 否则 UPS 将回答: “ NAK ” 3. UPS额定信息: 计算机指令: F<cr> UPS返回值: #MMM.M QQQ SS.SS RR.R<cr> 此功能将会让UPS返回UPS的额定信息。 在每段内容之间用空格分开。 UPS的回复内容中包含以下内容: a. 额定电压:MMM.M b. 额定电流:QQQ c. 额定电池电压:SS.SS or SSS.S d. 频率:RR.R
最新发布
12-24
但是目前 iphone12显示 没问题 但是iphone15pro的话。就执行兜底逻辑了 iPhone12pro的 getBottomSpace 为 0 /* eslint-disable react-native/no-inline-styles */ /* eslint-disable react/destructuring-assignment */ /* eslint-disable import/no-extraneous-dependencies */ /* eslint-disable no-restricted-properties */ /* eslint-disable no-plusplus */ /* eslint-disable no-cond-assign */ import React, { Component } from 'react' import { View, StyleSheet, Text, Dimensions, TouchableWithoutFeedback } from '@mrn/react-native' import { connect } from 'react-redux' import { getBottomSpace } from 'react-native-iphone-x-helper' import { LinearGradient } from '@mrn/mrn-components' import { color } from '../../styles/text' import { ShoppingCart, CartPoiInfo, getActivityRule, ActivityRuleItem, getTipInfo, TipInfo } from '../../api/multiPerson' import { Tip } from '@roo/roo-mobile-rn' import { RooDialog } from '@mrn/waimai-materials' import isEmpty from '../../utils/collectionUtils' import convertRichTextArray from '../../utils/stringUtils' import MRNUtils from '@mrn/mrn-utils' import judas from '../../utils/constant' interface Props { shopcart: ShoppingCart poiInfo: CartPoiInfo onOrderPreViewPress: Function } interface State { preTotalAndBoxPrice : number } const BottomSafeHeightiOS = getBottomSpace() ? 34 : 8 const { width } = Dimensions.get('screen') const styles = StyleSheet.create({ container: { flexDirection: 'column', }, remindTipContainer: { height: 30, left: 15, right: 15, borderTopLeftRadius:6, borderTopRightRadius:6, width: width - 30, backgroundColor: '#fff1cf', flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }, TipText: { color: color.wm_common_text_main, fontSize: 12 }, TipRedText: { color: '#fb4e44', fontSize: 12 }, poiResetContainer: { height: 50 + BottomSafeHeightiOS, paddingBottom: BottomSafeHeightiOS, width: '100%', color: '#373737f3', alignItems: 'center', justifyContent: 'center', backgroundColor: '#000000' }, poiResetText: { fontSize: 16, color: '#ffffff' }, shopCartContainer: { height: 50 + BottomSafeHeightiOS, width: '100%', flexDirection: 'row', paddingHorizontal: 15, justifyContent: 'space-between' }, shopcartRemindTipContainer: { height: 15, top: 0, width: '100%', backgroundColor: '#fff1cf', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }, noFoodsContainer: { height: 50, width: '100%', top: 0, left: 15, paddingLeft: 25, paddingRight: 20, position: 'absolute', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', borderRadius: 25, overflow: 'hidden', backgroundColor: '#000000' }, foodsContainer: { height: 50, width: '100%', top: 0, left: 15, paddingLeft: 25, paddingRight: 15, position: 'absolute', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', borderRadius: 25, overflow: 'hidden', backgroundColor: '#000000' }, noFoodShipFeeTipText: { fontSize: 12, color: color.wm_common_text_hint }, noFoodMinPriceText: { fontSize: 16, color: color.wm_common_text_hint }, leftContainer: { width: width - 153, height: '100%', flexDirection: 'column', justifyContent: 'center' }, rightContainer: { width: 98, height: '100%', backgroundColor: '#000000', alignItems: 'center', justifyContent: 'center' }, curPriceText: { fontSize: 21, color: '#ffffff' }, originPriceText: { fontSize: 14, color: color.wm_common_text_hint, marginLeft: 8, marginTop: 6, textDecorationLine: 'line-through' }, shippingFeeText: { fontSize: 12, color: color.wm_common_text_hint, marginTop: 2, }, submitText: { fontSize: 16, color: color.wm_common_text_main, width: '100%', paddingTop: 16, paddingRight: 5, textAlign: 'center' }, submitDisableText: { fontSize: 16, color: color.wm_common_text_auxiliary, width: '100%', paddingRight: 15, textAlign: 'center' } }) export class ShopcartView extends Component<Props, State> { _calculateDialog = null constructor(props) { super(props) this.state = { preTotalAndBoxPrice: 0 } //getBottomSpace的返回值 const bottomSpace = getBottomSpace() const windowSize = Dimensions.get('window') const screenSize = Dimensions.get('screen') setTimeout(() => { RooDialog.alert({ header: '调试信息', message: `getBottomSpace: ${bottomSpace} 窗口尺寸: ${windowSize.width}x${windowSize.height} 屏幕尺寸: ${screenSize.width}x${screenSize.height} 最终值: ${bottomSpace ? 34 : 8}`, btnOptions: [{ title: '确定', press: () => {} }] }) }, 1000) // 延迟1秒显示,确保组件已挂载 } //监听购物车价格变化,上报埋点 UNSAFE_componentWillReceiveProps(nextProps, prevState) { const { poiInfo, shopcart } = nextProps; if (shopcart?.original_price && this.state.preTotalAndBoxPrice != shopcart?.original_price) { MRNUtils.lxTrackMGEViewEvent('waimai', judas.WM_SHOPPING_CART_CACULATER_VIEW_BID, judas.MULTI_PERSON_ORDER_ACTIVITY_PV_CID, { poi_id: poiInfo?.poi_id_str, shopcart_orig_price: shopcart?.original_price, is_meet_min_price: (poiInfo?.min_price > shopcart?.original_price) ? 0 : 1 }) } else { } this.setState({ preTotalAndBoxPrice: shopcart?.original_price }) } ///是否有商品 _hasSkuCount = (shopcart: ShoppingCart) => { if (shopcart === undefined || shopcart.shopping_list === undefined || shopcart.shopping_list.length === 0) { return false } for (let i = 0; i < shopcart.shopping_list.length; i++) { const shopcartItem = shopcart.shopping_list[i] if (shopcartItem !== undefined && shopcartItem.product_list.length > 0) { return true } } return false } //金额小数格式化。小数位数超出max则四舍五入截断;默认小数位数最大为2,如2.005 --> 2.01 , 2.001 --> 2 _formatDoubleMoney = (money: number) => { const decimal: number = 2 const multiple = Math.pow(10, decimal) //设置浮点数要扩大的倍数 //防止出现2.00499999的情况 const newMoney = Math.floor(money * multiple + 0.50001) const newMoneyStr: string = `${newMoney / multiple}` //去除小数点之后的0 const start: number = newMoneyStr.indexOf('.') let end: number = newMoneyStr.length if (start >= 0 && start < end) { let c = '' while ((start < end) && (((c = newMoneyStr.substr(end - 1, 1)) === '0') || (c === '.'))) { --end } return newMoneyStr.substr(0, end) } else { return newMoneyStr } } // 是否满足起送 _lessThanMinPrice = (shopcart: ShoppingCart, poiInfo: CartPoiInfo) => { const order_purchase_threshold_info = shopcart?.order_purchase_threshold_info; if (order_purchase_threshold_info && typeof order_purchase_threshold_info === 'object' && !Array.isArray(order_purchase_threshold_info) && Object.keys(order_purchase_threshold_info).length > 0) { // order_purchase_threshold_info 是一个非空对象 const {order_over_purchase_threshold = false} = order_purchase_threshold_info; return !order_over_purchase_threshold; } return shopcart.original_price <= poiInfo.min_price } ///去下单按钮的文案 _previewText = (shopcart: ShoppingCart, poiInfo: CartPoiInfo) => { if (shopcart === undefined || poiInfo === undefined) { return '' } else { const diffPrice = poiInfo.min_price - shopcart.original_price const diffPriceNum: number = (diffPrice < 0.01 && diffPrice > -0.001) ? 0.01 : diffPrice const diffPriceStr = diffPrice > 0 ? `¥${this._formatDoubleMoney(diffPrice)}` : (`¥${diffPriceNum}`) let previewText: string const order_purchase_threshold_info = shopcart?.order_purchase_threshold_info; if (this._lessThanMinPrice(shopcart, poiInfo)) { previewText = `差${diffPriceStr}起送` if (order_purchase_threshold_info && typeof order_purchase_threshold_info === 'object' && !Array.isArray(order_purchase_threshold_info) && Object.keys(order_purchase_threshold_info).length > 0 && !order_purchase_threshold_info.order_over_purchase_threshold){ const { tips = '' } = order_purchase_threshold_info; previewText = tips ? tips : `差${diffPriceStr}起送` // 兜底 } } else if (this._hasSingleBuyProductInfo(shopcart)) { const singleBuy = shopcart.single_buy_product_info.tips if (singleBuy === undefined || singleBuy.length <= 0) { previewText = '单点不配送' } else { previewText = singleBuy } } else { previewText = '去结算' } return previewText } } //获取拼单中已经点菜的人数 getOrderDishUserCount = (shoppingCart: ShoppingCart): number => { if (shoppingCart !== undefined && shoppingCart.shopping_list !== undefined && !isEmpty(shoppingCart.shopping_list)) { return shoppingCart.shopping_list.filter(shoppingItem => shoppingItem.product_list !== undefined && !isEmpty(shoppingItem.product_list)).length } else { return 0 } } _doCalculate() { const tipInfo = getTipInfo(this.props.shopcart) var msg = "去结算后,其他人将不可加入或修改商品" if (tipInfo && tipInfo.popText && tipInfo.popText != '') { msg = tipInfo.popText } this._calculateDialog = RooDialog.open({ header: '确认去结算吗?', message: msg, btnOptions: [{ title: '取消', press: () => { if (this._calculateDialog) { this._calculateDialog.remove() this._calculateDialog = null } }, }, { title: '确定', press: () => { if (this._calculateDialog) { this._calculateDialog.remove() this._calculateDialog = null } this.props.onOrderPreViewPress() }, }], }) } // 是否都是单点不送商品 _hasSingleBuyProductInfo = (shopcart: ShoppingCart) => shopcart !== undefined && shopcart.single_buy_product_info !== undefined && shopcart.single_buy_product_info.only_single_buy shopCartTipInfoRender = (shopcart: ShoppingCart) => { const defaultRet = (shopcart.shopping_list !== undefined && shopcart.shopping_list.length > 1) && <View style={styles.remindTipContainer} > <Text style={styles.TipText}>您的</Text> <Text style={styles.TipRedText}>{shopcart.shopping_list.length - 1}</Text> <Text style={styles.TipText}>位拼友已完成拼单</Text> </View> if (!shopcart.tip_info || shopcart.tip_info.length === 0) { return defaultRet } else { const tipInfo = JSON.parse(shopcart.tip_info) as TipInfo console.log("multi-person shoppcart TipInfo") if (tipInfo !== undefined && typeof tipInfo.tipText !== undefined) { const richTextInfos = convertRichTextArray(tipInfo.tipText,'#FF4A26' ,'#222426' ) if (richTextInfos !== undefined && richTextInfos.length > 0) { return <View style={styles.remindTipContainer}> {richTextInfos.map(content => ( <Text style={[styles.TipText, { color: content.text_color }]}>{content.text}</Text> ))} </View> } else { return defaultRet } } else { return defaultRet } } }; render() { const { shopcart, poiInfo } = this.props ///兜底处理 if (shopcart === undefined || poiInfo === undefined) { return <View /> } const hasSkuCount = this._hasSkuCount(shopcart) const poiStatusRest: boolean = poiInfo.status === 3 const order_purchase_threshold_info = shopcart?.order_purchase_threshold_info; const orderOverPurchase = order_purchase_threshold_info?.order_over_purchase_threshold || false; const useShowPrice = shopcart?.exp_res?.use_show_price_switch_gray_control || false; return ( <View style={styles.container} > {this.shopCartTipInfoRender(shopcart)} {///打烊View poiStatusRest && <View style={styles.poiResetContainer}> <Text style={styles.poiResetText}>本店打烊啦</Text> </View> } { ///无商品购物车样式的view poiStatusRest === false && hasSkuCount === false && <View style={styles.shopCartContainer}> {(shopcart.shopping_list !== undefined && shopcart.shopping_list.length > 1) && <View style={styles.shopcartRemindTipContainer} /> } <View style={styles.noFoodsContainer}> <Text style={styles.noFoodShipFeeTipText}>{shopcart.shipping_fee_cart_tip}</Text> <Text style={styles.noFoodMinPriceText}> ¥ {poiInfo.min_price} 起送 </Text> </View> </View> } { ///正常购物车样式的view poiStatusRest === false && hasSkuCount === true && <View style={styles.shopCartContainer}> {(shopcart.shopping_list !== undefined && shopcart.shopping_list.length > 1) && <View style={styles.shopcartRemindTipContainer} /> } <View style={styles.foodsContainer}> <View style={styles.leftContainer}> <View style={{ flexDirection: 'row' }}> <Text style={styles.curPriceText}> ¥ {shopcart.price} </Text> {useShowPrice && shopcart.underline_price > 0 && <Text style={styles.originPriceText}>¥{shopcart.underline_price}</Text>} {!useShowPrice && shopcart.original_price > shopcart.price + 0.0001 && <Text style={styles.originPriceText}> ¥ {this._formatDoubleMoney(shopcart.original_price)} </Text>} </View> <Text style={styles.shippingFeeText}>{shopcart.shipping_fee_cart_tip}</Text> </View> <View style={styles.rightContainer}> { ///去结算渐变View 和 差X元起送 ((orderOverPurchase || shopcart.original_price > poiInfo.min_price) && !this._hasSingleBuyProductInfo(shopcart)) ? <TouchableWithoutFeedback onPress={() => { this._doCalculate() }} > <LinearGradient colors={['#FFE74D', '#FFDD19']} start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }} style={{ flex: 1, width: '100%' }} > <Text style={styles.submitText}>{this._previewText(shopcart, poiInfo)}</Text> </LinearGradient> </TouchableWithoutFeedback> : <Text style={styles.submitDisableText}>{this._previewText(shopcart, poiInfo)}</Text> } </View> </View> </View> } </View> ) } } const mapState = state => ({ shopcart: state.page.shopcart, poiInfo: state.page.response.poi_info }) const mapDispatch = () => ({}) // Use react-redux's connect export default connect( mapState, mapDispatch )(ShopcartView) 我怎么处理呢?
10-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值