'app_account_number', 'search_history'=>'app_user_search_history', 'foodlist4'=>'app_z_national_standard_food_type_4', 'user'=>'app_user_data' ]; protected $token_time = 30;//30天的秒数 protected $file_size = 5*1024*1024; protected $return_data_all = [ '10001'=>'关键参数缺失', '10002'=>'操作失败', '10003'=>'信息核实错误', '10004'=>'未找到有效数据', '10005'=>'参数格式错误', '10006'=>'参数不能为空', '10007'=>'参数错误', '10008'=>'', '10009'=>'', '10010'=>'自定义信息', '20001'=>'登录失效', '99999'=>'网络异常,请稍后重试', ]; // 加 bcadd(,,20) // 减 bcsub(,,20) // 乘 bcmul(,,20) // 除 bcdiv(,,20) ################################################################接口监控################################################################ ################################################################接口监控################################################################ ################################################################接口监控################################################################ // 接口记录 public function record_api_log($params, $error = null, $response = null){ // dump($params); // dump($error); // die; $logContent = "接口请求参数:" . json_encode($params, JSON_UNESCAPED_UNICODE) . PHP_EOL; if ($error) { $logContent .= "错误信息:" . $error['all_content'] . PHP_EOL; if(!cache($error['flie']."_".$error['line'])){ cache($error['flie']."_".$error['line'],"API错误",3600); $this->send_email_api_error(["tsf3920322@126.com"],['title'=>'接口报错','from_user_name'=>'厨房秤(后台)','content'=>$logContent]); } } if ($response) { $logContent .= "返回信息:" . json_encode($response, JSON_UNESCAPED_UNICODE) . PHP_EOL; } // 使用ThinkPHP的日志记录方法 Log::record($logContent, 'api_log'); } /* 接口说明(发邮件) * $address(收件人的邮箱地址) 数组 格式: ['460834639@qq.com','460834639@qq.com'.......] * $content(邮件的主题数据信息) 数组 格式:['title'=>'123','from_user_name'=>'123','content'=>'123'] * $annex(附件路径信息) 字符串 */ public function send_email_api_error($address,$content,$annex=''){ // $ad = '460834639@qq.com'; $ad1 = '295155911@qq.com'; $mail = new PHPMailer(); //实例化 $mail->IsSMTP(); // 启用SMTP $mail->Host = "smtp.126.com"; //SMTP服务器 163邮箱例子 $mail->Port = 465; //邮件发送端口 $mail->SMTPAuth = true; //启用SMTP认证 $mail->SMTPSecure = 'ssl'; $mail->CharSet = "UTF-8"; //字符集 $mail->Encoding = "base64"; //编码方式 $mail->Username = "tsf3920322@126.com"; //你的邮箱 $mail->Password = "HLWXNRPUCTHJFIIX"; //你的密码(邮箱后台的授权密码) $mail->From = "tsf3920322@126.com"; //发件人地址(也就是你的邮箱) // $mail->Subject = "微盟测试邮件"; //邮件标题 $mail->Subject = $content['title']; //邮件标题 // $mail->FromName = "微盟体测中心"; //发件人姓名 $mail->FromName = $content['from_user_name']; //发件人姓名 for ($i=0; $i < count($address); $i++) { $mail->AddAddress($address[$i], ""); //添加收件人(地址,昵称) } if($annex != ''){ // $url = ROOT_PATH. 'public' . DS . 'tsf' . DS .'demoooo.jpg'; $mail->AddAttachment($annex,''); // 添加附件,并指定名称 } $mail->IsHTML(true); //支持html格式内容 $neirong = $content['content']; $mail->Body = $neirong; //邮件主体内容 //发送 if (!$mail->Send()) { return ['code' => 10003,'msg'=>$mail->ErrorInfo]; // return $mail->ErrorInfo; } else { return ['code' => 0]; // return 'success'; } } ################################################################通用工具################################################################ ################################################################通用工具################################################################ ################################################################通用工具################################################################ // 验证验证码是否有效 public function check_code($data = 18530934717 , $code = 123456){ // // 默认验证码正确 if(cache($data) == false){ return '验证码过期'; }else{ if($code != cache($data)){ return '验证码错误'; } } return true; } // 判断字符串是手机还是邮箱 public function is_tel_email($str) { // 手机号码的正则表达式(中国大陆格式)(下面正则实际判断的是是否为11位数字) $mobilePattern = '/^\d{11}$/'; // 电子邮件地址的正则表达式 $emailPattern = '/^[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/'; // 判断是否为手机号码 if (preg_match($mobilePattern, $str)) { return 'tel'; } // 判断是否为电子邮件地址 if (preg_match($emailPattern, $str)) { return 'email'; } // 如果都不是,返回其他 return false; } // 判断token是否过期 public function token_time_validate($token){ // 591b70e0d80b5fa6d77e6e1384453ab9 if(is_string($token)){ $length = strlen($token); if ($length < 10 ) { Log::record('用户尝试更新token时间,token:' . $token.',但是更新token失败,字符串长度小于10', 'token_log'); return false; } }else{ Log::record('用户尝试更新token时间,token:' . $token.',但是更新token失败,不是字符串', 'token_log'); return false; } $cfc = Db::connect('cfc_db'); $user_login = $cfc->table($this->base_use_db_name['user'])->where(['token'=>$token])->field('id,login_time')->find(); if(!$user_login){ Log::record('用户尝试更新token时间,token:' . $token.',但是更新token失败,未找到用户token', 'token_log'); return false; } // 创建 DateTime 对象来表示指定的日期和时间 $specifiedDateTime = new \DateTime($user_login['login_time']); // 获取当前时间的 DateTime 对象 $currentDateTime = new \DateTime(); // 计算两个日期之间的差异(以秒为单位) $interval = $currentDateTime->diff($specifiedDateTime); // 将差异转换为天数(注意:这里的天数可能不是整数,因为差异可能包括小时、分钟等) $daysDifference = $interval->days; // 如果需要更精确的计算(包括小时、分钟等转换成的天数),可以使用以下方式: // $totalSecondsDifference = $interval->format('%a') * 86400 + $interval->format('%h') * 3600 + $interval->format('%i') * 60 + $interval->format('%s'); // $daysDifference = floor($totalSecondsDifference / 86400); // 将总秒数转换为天数并取整 // 判断差异是否超过指定的天数 if ($daysDifference > $this->token_time) { // echo "超过 {$specifiedDays} 天"; Log::record('用户尝试更新token时间,token:' . $token.',但是更新token失败,原因没有找到该token,或该token已经超过30天', 'token_log'); return false; } else { // echo "未超过 {$specifiedDays} 天"; $user_login = $cfc->table($this->base_use_db_name['user'])->where(['token'=>$token])->update(['login_time'=>date('Y-m-d H:i:s')]); if($user_login){ Log::record('用户尝试更新token时间,token:' . $token.',记录成功,最新的时间为'.date('Y-m-d H:i:s'), 'token_log'); return true; }else{ Log::record('用户尝试更新token时间,token:' . $token.',但是更新token失败,数据库更新时间未成功', 'token_log'); return true; } } } // 验证数据类型 public function verify_data_is_ok($data = 2,$type){ if($type == 'str'){ if (is_string($data)) { return true; } else { $this->record_api_log($data, null, ['code'=>10005,'msg'=>'校验参数不为字符串',[]]); return false; } }else if($type == 'num'){ if (is_numeric($data)) { return true; } else { $this->record_api_log($data, null, ['code'=>10005,'msg'=>'校验参数不为数字',[]]); return false; } }else if($type == 'intnum'){ $pattern = '/^\d+$/'; // dump($data); if (preg_match($pattern, $data)) { return true; // 匹配成功,返回 true } else { $this->record_api_log($data, null, ['code'=>10005,'msg'=>'校验参数不为整数数字',[]]); return false; // 匹配失败,返回 false } }else if($type == 'datetime'){ $formats = ['Y-m-d','Y-m-d H:i:s']; foreach ($formats as $format) { $dateTime = \DateTime::createFromFormat($format, $data); // 检查时间字符串是否成功解析,并且解析后的日期时间与原始字符串表示的时间一致 if ($dateTime && $dateTime->format($format) === $data) { return true; } } // 如果所有格式都解析失败,则返回 false $this->record_api_log($data, null, ['code'=>10005,'msg'=>'校验参数不为日期格式',[]]); return false; }else if($type == 'other'){ } } // 计算年龄 public function calculate_age($data = '1991-04-20'){ $today = time(); // 获取当前时间的 Unix 时间戳 $birthDate = strtotime($data); // 将出生日期字符串转换为 Unix 时间戳 if ($birthDate !== false) { $age = date('Y', $today) - date('Y', $birthDate); // 如果当前年份的月份和日期小于出生年份的月份和日期,那么年龄减一 if (date('m-d', $today) < date('m-d', $birthDate)) { $age--; } return $age; } else { return false; } } // 计算常规卡路里 public function count_user_nutrition_all($data){ // 计算基础代谢率(BMR) if($data['gender'] == 1){ // 男性:BMR = 10 × 体重(kg) + 6.25 × 身高(cm) - 5 × 年龄(岁) + 5 $bmr = bcmul(10,$data['weight'],20); $bmr = bcadd($bmr,bcmul(6.25,$data['height'],20),20); $bmr = bcsub($bmr,bcmul(5,$data['age_num'],20),20); $bmr = bcadd($bmr,5,2); }else if($data['gender'] == 2){ // 女性:BMR = 10 × 体重(kg) + 6.25 × 身高(cm) - 5 × 年龄(岁) - 161 $bmr = bcmul(10,$data['weight'],20); $bmr = bcadd($bmr,bcmul(6.25,$data['height'],20),20); $bmr = bcsub($bmr,bcmul(5,$data['age_num'],20),20); $bmr = bcsub($bmr,161,2); }else{ return $this->msg(10003,'性别未知'); } // 每日总能量消耗(TDEE) // 久坐(很少或没有运动):BMR × 1.2 // 轻度活动(每周1-3天轻度运动):BMR × 1.375 // 中度活动(每周3-5天中度运动):BMR × 1.55 // 高度活动(每周6-7天高强度运动):BMR × 1.725 // 极高活动(体力劳动或每天高强度训练):BMR × 1.9 if(array_key_exists('activity_level',$data)){ if($data['activity_level'] != null){ $tdee = bcmul($bmr,$data['activity_level'],2); }else{ $tdee = bcmul($bmr,1.55,2); } }else{ $tdee = bcmul($bmr,1.55,2); } // 碳水化合物:通常占总热量的45-65% // 蛋白质:通常占总热量的10-35% // 脂肪:通常占总热量的20-35% // 孩子&成年人:碳水化合物50%,蛋白质20%,脂肪30%。 // 老人:碳水化合物50%,蛋白质25%,脂肪25%。 // 建议每日摄入量计算: // 1.碳水化合物(克): (TDEE × 碳水化合物比例) / 4 // 2.蛋白质(克):(TDEE × 蛋白质比例) / 4 // 3.脂肪(克): (TDEE × 脂肪比例) / 9 $carbohydrate_p = 0.5; $carbohydrate = bcdiv(bcmul($tdee,0.5,20),4,2); if($data['age_num'] < 65){ $protein_p = 0.2; $fat_p = 0.3; $protein = bcdiv(bcmul($tdee,0.2,20),4,2); $fat = bcdiv(bcmul($tdee,0.3,20),9,2); }else{ $protein_p = 0.25; $fat_p = 0.25; $protein = bcdiv(bcmul($tdee,0.25,20),4,2); $fat =bcdiv(bcmul($tdee,0.25,20),9,2); } return ['kcal'=>$tdee,'carbohydrate'=>$carbohydrate,'protein'=>$protein,'fat'=>$fat,'bmr'=>$bmr,'carbohydrate_p'=>$carbohydrate_p,'protein_p'=>$protein_p,'fat_p'=>$fat_p]; } /** * 将重量转换为克(g) * @param string $weight 重量值 * @param string $unit 单位 (g, oz, lb, lb:oz) * @return float 转换后的克重 */ function convertWeightToGrams($weight, $unit) { // 定义精确的转换常量 $G_PER_OZ = '28.349523125'; $G_PER_LB = '453.59237'; $unit = strtolower($unit); $result = 0; switch ($unit) { case 'g': case '克': // 已经是克,直接返回 $result = $weight; break; case 'oz': case '盎司': // 盎司转克 $result = bcmul($weight,$G_PER_OZ,2); break; case 'lb': case '磅': // 磅转克 $result = bcmul($weight,$G_PER_LB,2); break; case 'lb:oz': case '磅:盎司': // 磅:盎司复合单位处理 if (strpos($weight, ':') !== false) { $temporary_data = explode(':', $weight); $result = bcadd(bcmul($temporary_data[0],$G_PER_LB,20),bcmul($temporary_data[1],$G_PER_OZ,20),2); } else { // 如果格式不正确,可以抛出异常或返回0 $result = '0'; } break; default: $result = '0'; } // 保留两位小数并返回 return $result; } // 计算营养物质 public function calculate_nutrients($data){ // dump($data); $food_id_arr = []; for ($i=0; $i < count($data); $i++) { $food_id_arr[] = $data[$i]['food_id']; } $cfc = Db::connect('cfc_db'); $nutrients_list = $cfc->table($this->base_use_db_name['foodlist4']) ->where("father_id in ('".implode("','",$food_id_arr)."')") // ->field() ->select(); $nutrients_arr = ['VitaminA','VitaminB1','VitaminB2','VitaminB6','VitaminB12','VitaminD','VitaminK','Niacin','VitaminC','VitaminE','FolicAcid','Biotin','PantothenicAcid','TotalCholine','Ca','Phosphorus','Kalium','Mg','Na','Fe','Zn','Se','Cu','Mn','Iodine']; // dump($nutrients_list); // 加 bcadd(,,20) // 减 bcsub(,,20) // 乘 bcmul(,,20) // 除 bcdiv(,,20) for ($i=0; $i < count($data); $i++) { $zong_all = bcadd($data[$i]['protein_val'],bcadd($data[$i]['fat_val'],$data[$i]['carbohydrate_val'],20),20); $data[$i]['nutrients_four'][] = [ 'name' => '卡路里', 'unit' => 'kcal', 'color' => '', 'value' => $data[$i]['kcal_val'], 'proportion' => 0, ]; $data[$i]['nutrients_four'][] = [ 'name' => '蛋白质', 'unit' => 'g', 'color' => '#5180D8', 'value' => $data[$i]['protein_val'], 'proportion' => $zong_all == 0?0:bcmul(bcdiv($data[$i]['protein_val'],$zong_all,2),100,0), ]; $data[$i]['nutrients_four'][] = [ 'name' => '脂肪', 'unit' => 'g', 'color' => '#ED7886', 'value' => $data[$i]['fat_val'], 'proportion' => $zong_all == 0?0:bcmul(bcdiv($data[$i]['fat_val'],$zong_all,2),100,0), ]; $data[$i]['nutrients_four'][] = [ 'name' => '碳水化合物', 'unit' => 'g', 'color' => '#FFB169', 'value' => $data[$i]['carbohydrate_val'], 'proportion' => $zong_all == 0?0:bcmul(bcdiv($data[$i]['carbohydrate_val'],$zong_all,2),100,0), ]; $data[$i]['nutrients_list'][] = [ 'name' => 'Calorie', 'name_ch' => '卡路里', 'unit' => 'kcal', 'value' => $data[$i]['kcal_val'], 'type' => 1, 'type_name' => '能量及宏量营养素', 'color' => '#C4FFE0', ]; $data[$i]['nutrients_list'][] = [ 'name' => 'Protein', 'name_ch' => '蛋白质', 'unit' => 'g', 'value' => $data[$i]['protein_val'], 'type' => 1, 'type_name' => '能量及宏量营养素', 'color' => '#C4FFE0', ]; $data[$i]['nutrients_list'][] = [ 'name' => 'Fat', 'name_ch' => '脂肪', 'unit' => 'g', 'value' => $data[$i]['fat_val'], 'type' => 1, 'type_name' => '能量及宏量营养素', 'color' => '#C4FFE0', ]; $data[$i]['nutrients_list'][] = [ 'name' => 'Carbohydrate', 'name_ch' => '碳水化合物', 'unit' => 'g', 'value' => $data[$i]['carbohydrate_val'], 'type' => 1, 'type_name' => '能量及宏量营养素', 'color' => '#C4FFE0', ]; foreach ($nutrients_list as $key => $value) { if($value['father_id'] == $data[$i]['food_id']){ if(in_array($value['name'],$nutrients_arr)){ $data[$i]['nutrients_list'][] = [ 'name' => $value['name'], 'name_ch' => $value['name_ch'], 'unit' => $value['unit'], 'value' => bcmul($value['value'],bcdiv($data[$i]['weight'],100,20),2), 'type' => $value['type'], 'type_name' => $value['type'] == 1?'能量及宏量营养素':($value['type'] == 2?'维生素':($value['type'] == 3?'矿物质':'')), 'color' => $value['type'] == 1?'#C4FFE0':($value['type'] == 2?'#FFEFB7':($value['type'] == 3?'#7DA8E0':'')), ]; } } } } return $data; } public function add_search_history_action($data){ // 添加一条搜索记录start $cfc = Db::connect('cfc_db'); $insert_search_log = $cfc->table($this->base_use_db_name['search_history'])->where(['user_id'=>$data['id'],'keyword'=>$data['search_data'],'type'=>$data['type']])->field('id,search_count')->find(); if($insert_search_log){ $cfc->table($this->base_use_db_name['search_history'])->where(['id'=>$insert_search_log['id']])->update([ 'search_count'=>$insert_search_log['search_count']+1, 'last_searched_at'=>date('Y-m-d H:i:s'), ]); }else{ $cfc->table($this->base_use_db_name['search_history'])->insert([ 'user_id'=>$data['id'], 'keyword'=>$data['search_data'], 'type'=>$data['type'], ]); } // 添加一条搜索记录end } ####################################################图片选择上传start############################################################## ####################################################图片选择上传start############################################################## ####################################################图片选择上传start############################################################## public function pic_chose_list($page = 1) { $data = input(); $page_num = 20; if(!array_key_exists('token',$data)){ return $this->msg(10001,'token is miss'); } if(array_key_exists('page',$data)){ $page = $data['page']; } $parameter_data = [ 'user_token'=>$data['token'], 'is_del'=>0 ]; $cfc = Db::connect('cfc_db'); $num = $cfc->table('app_user_upload_img')->where($parameter_data)->count(); $result = $cfc->table('app_user_upload_img')->where($parameter_data)->order('id desc')->page($page,$page_num)->field('id,pic_name,pic_url')->select(); $return_result['page_total'] = $page_total = ceil($num/$page_num); $return_result['page_now'] = $page; $return_result['result'] = $result; return $this->msg($return_result); } public function pic_upload_one_action(){ $temporary_data = []; $cfc = Db::connect('cfc_db'); $file = request()->file('image'); $token = request()->param('token'); if(!$token){ return $this->msg(10001,'token is miss'); } if($file){ $name = $file->getInfo()['name']; // 使用 pathinfo() 函数获取文件名的扩展名 $pathinfo = pathinfo($name); $extension = strtolower($pathinfo['extension']); // 转换为小写以进行不区分大小写的比较 $new_filename = time().$this->generateRandomString(). '.' . $extension; $info = $file->validate(['size'=>$this->file_size,'ext'=>'jpg,png,gif'])->move(ROOT_PATH . 'public' . DS . 'kitchenscale_all' . DS . 'user_upload',$new_filename); if($info){ $temporary_data = [ 'user_token'=>$token, 'pic_name'=>$new_filename, 'pic_url'=>"https://tc.pcxbc.com/kitchenscale_all/user_upload/".$new_filename, 'create_time'=>date('Y-m-d H:i:s'), ]; $pic_id = $cfc->table('app_user_upload_img')->insertGetId($temporary_data); if($pic_id){ $temporary_data['id'] = $pic_id; unset($temporary_data['create_time']); unset($temporary_data['user_token']); return $this->msg($temporary_data); }else{ return $this->msg(10002); } }else{ // 上传失败获取错误信息 return $this->msg(10010,$file->getError()); } }else{ return $this->msg(10001,'未选择图片'); } } public function pic_upload_action(){ $insert_data = []; $temporary_data = []; $miss_data = 0; $cfc = Db::connect('cfc_db'); $files = request()->file('images'); $token = request()->param('token'); if(!$token){ return $this->msg(10001,'token is miss'); } if($files){ if(count($files)>5){ return $this->msg(10001,'单次最多上传5张图片'); } foreach($files as $file){ $name = $file->getInfo()['name']; // 使用 pathinfo() 函数获取文件名的扩展名 $pathinfo = pathinfo($name); $extension = strtolower($pathinfo['extension']); // 转换为小写以进行不区分大小写的比较 $file_name = $pathinfo['filename']; // 判断扩展名是否不是 .png 或 .gif if ($extension !== 'png' && $extension !== 'gif') { // 修改文件名,将扩展名改为 .jpg $new_filename = time().$this->generateRandomString(). '.jpg'; } else { $new_filename = time().$this->generateRandomString(). '.' . $extension; } $info = $file->validate(['size'=>$this->file_size,'ext'=>'jpg,png,gif'])->move(ROOT_PATH . 'public' . DS . 'kitchenscale_all' . DS . 'user_upload',$new_filename); if($info){ $temporary_data = [ 'user_token'=>$token, 'pic_name'=>$new_filename, 'pic_url'=>"https://tc.pcxbc.com/kitchenscale_all/user_upload/".$new_filename, 'create_time'=>date('Y-m-d H:i:s'), ]; $pic_id = $cfc->table('app_user_upload_img')->insertGetId($temporary_data); if($pic_id){ $temporary_data['id'] = $pic_id; unset($temporary_data['create_time']); unset($temporary_data['user_token']); array_push($insert_data,$temporary_data); }else{ $miss_data = $miss_data+1; } }else{ $miss_data = $miss_data+1; } } return $this->msg(['error_num'=>$miss_data,'insert_data'=>$insert_data]); }else{ return $this->msg(10001,'未选择图片'); } } ####################################################图片选择上传end############################################################## ####################################################图片选择上传end############################################################## ####################################################图片选择上传end############################################################## ########################################################其他工具######################################################## ########################################################其他工具######################################################## ########################################################其他工具######################################################## public function msg($data,$str='',$result = []){ if(is_array($data)){ if($str != ''){ return json(['code'=>0,'msg'=>$str,'data'=>$data]); }else{ return json(['code'=>0,'msg'=>'操作成功','data'=>$data]); } }else{ if($str != ''){ return json(['code'=>$data,'msg'=>$str,'data'=>$result]); } return json(['code'=>$data,'msg'=>$this->return_data_all[$data],'data'=>$result]); } } public function generateRandomString($length = 10) { $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $charactersLength = strlen($characters); $randomString = ''; for ($i = 0; $i < $length; $i++) { $randomString .= $characters[rand(0, $charactersLength - 1)]; } return $randomString; } public function ceshi(){ echo 'hello'; } }