|
@@ -0,0 +1,796 @@
|
|
|
|
|
+<?php
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+use app\service\system\SystemService;
|
|
|
|
|
+use support\Response;
|
|
|
|
|
+use Webman\Event\Event;
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists("between_time"))
|
|
|
|
|
+{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 格式化起止时间(为了兼容前端RangePicker组件)
|
|
|
|
|
+ * 2020-04-01T08:15:08.891Z => 1585670400
|
|
|
|
|
+ * @param array $times
|
|
|
|
|
+ * @param bool $isWithTime 是否包含时间
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ */
|
|
|
|
|
+ function between_time(array $times, bool $isWithTime = false): array
|
|
|
|
|
+ {
|
|
|
|
|
+ foreach ($times as &$time) {
|
|
|
|
|
+ $time = trim($time, '"');
|
|
|
|
|
+ $time = str2date($time, $isWithTime);
|
|
|
|
|
+ }
|
|
|
|
|
+ return ['start_time' => current($times), 'end_time' => next($times)];
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+if (!function_exists("str2date"))
|
|
|
|
|
+{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 日期转换时间戳
|
|
|
|
|
+ * 例如: 2020-04-01 08:15:08 => 1585670400
|
|
|
|
|
+ * @param string $date
|
|
|
|
|
+ * @param bool $isWithTime 是否包含时间
|
|
|
|
|
+ * @return int
|
|
|
|
|
+ */
|
|
|
|
|
+ function str2date(string $date, bool $isWithTime = false): int
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!$isWithTime) {
|
|
|
|
|
+ $date = date('Y-m-d', strtotime($date));
|
|
|
|
|
+ }
|
|
|
|
|
+ return strtotime($date);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists("isValidMobile"))
|
|
|
|
|
+{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 验证是否为有效的中国大陆手机号码
|
|
|
|
|
+ * @param string $mobile
|
|
|
|
|
+ * @return bool
|
|
|
|
|
+ */
|
|
|
|
|
+ function isValidMobile(string $mobile): bool
|
|
|
|
|
+ {
|
|
|
|
|
+ // 去除空格、换行等
|
|
|
|
|
+ $mobile = trim($mobile);
|
|
|
|
|
+ // 正则:1 开头,第二位 3-9,后面 9 位数字,总共 11 位
|
|
|
|
|
+ $pattern = '/^1[3-9]\d{9}$/';
|
|
|
|
|
+ return preg_match($pattern, $mobile) === 1;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if(!function_exists("hide_mobile")){
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 手机号码脱敏
|
|
|
|
|
+ * @param string $mobile
|
|
|
|
|
+ * @param int $len 4 末尾4位 6 末尾2位
|
|
|
|
|
+ * @return string
|
|
|
|
|
+ */
|
|
|
|
|
+ function hide_mobile(string $mobile,int $len = 6): string
|
|
|
|
|
+ {
|
|
|
|
|
+ return substr_replace($mobile, ($len==4 ? '****' : '******'), 3, $len);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists('hide_str')) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 将一个字符串部分字符用*替代隐藏
|
|
|
|
|
+ * @param string $string 待转换的字符串
|
|
|
|
|
+ * @param int $begin 起始位置,从0开始计数,当$type=4时,表示左侧保留长度
|
|
|
|
|
+ * @param int $len 需要转换成*的字符个数,当$type=4时,表示右侧保留长度
|
|
|
|
|
+ * @param int $type 转换类型:0,从左向右隐藏;1,从右向左隐藏;2,从指定字符位置分割前由右向左隐藏;3,从指定字符位置分割后由左向右隐藏;4,保留首末指定字符串中间用***代替
|
|
|
|
|
+ * @param string $glue 分割符
|
|
|
|
|
+ * @return string 处理后的字符串
|
|
|
|
|
+ */
|
|
|
|
|
+ function hide_str(string $string, int $begin = 3, int $len = 4, int $type = 0, string $glue = "@"): string
|
|
|
|
|
+ {
|
|
|
|
|
+ $array = array();
|
|
|
|
|
+ if ($type == 0 || $type == 1 || $type == 4) {
|
|
|
|
|
+ $strlen = $length = mb_strlen($string);
|
|
|
|
|
+ while ($strlen) {
|
|
|
|
|
+ $array[] = mb_substr($string, 0, 1, "utf8");
|
|
|
|
|
+ $string = mb_substr($string, 1, $strlen, "utf8");
|
|
|
|
|
+ $strlen = mb_strlen($string);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if ($type == 0) {
|
|
|
|
|
+ for ($i = $begin; $i < ($begin + $len); $i++) {
|
|
|
|
|
+ if (isset($array[$i])) {
|
|
|
|
|
+ $array[$i] = "*";
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ $string = implode("", $array);
|
|
|
|
|
+ } elseif ($type == 1) {
|
|
|
|
|
+ $array = array_reverse($array);
|
|
|
|
|
+ for ($i = $begin; $i < ($begin + $len); $i++) {
|
|
|
|
|
+ if (isset($array[$i])) {
|
|
|
|
|
+ $array[$i] = "*";
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ $string = implode("", array_reverse($array));
|
|
|
|
|
+ } elseif ($type == 2) {
|
|
|
|
|
+ $array = explode($glue, $string);
|
|
|
|
|
+ if (isset($array[0])) {
|
|
|
|
|
+ $array[0] = hide_str($array[0], $begin, $len, 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ $string = implode($glue, $array);
|
|
|
|
|
+ } elseif ($type == 3) {
|
|
|
|
|
+ $array = explode($glue, $string);
|
|
|
|
|
+ if (isset($array[1])) {
|
|
|
|
|
+ $array[1] = hide_str($array[1], $begin, $len, 0);
|
|
|
|
|
+ }
|
|
|
|
|
+ $string = implode($glue, $array);
|
|
|
|
|
+ } elseif ($type == 4) {
|
|
|
|
|
+ $left = $begin;
|
|
|
|
|
+ $right = $len;
|
|
|
|
|
+ $tem = array();
|
|
|
|
|
+ for ($i = 0; $i < ($length - $right); $i++) {
|
|
|
|
|
+ if (isset($array[$i])) {
|
|
|
|
|
+ $tem[] = $i >= $left ? "" : $array[$i];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ $tem[] = '*****';
|
|
|
|
|
+ $array = array_chunk(array_reverse($array), $right);
|
|
|
|
|
+ $array = array_reverse($array[0]);
|
|
|
|
|
+ for ($i = 0; $i < $right; $i++) {
|
|
|
|
|
+ if (isset($array[$i])) {
|
|
|
|
|
+ $tem[] = $array[$i];
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ $string = implode("", $tem);
|
|
|
|
|
+ }
|
|
|
|
|
+ return $string;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists('list_sort_by')) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ *----------------------------------------------------------
|
|
|
|
|
+ * 对查询结果集进行排序
|
|
|
|
|
+ *----------------------------------------------------------
|
|
|
|
|
+ * @access public
|
|
|
|
|
+ *----------------------------------------------------------
|
|
|
|
|
+ * @param array $list 查询结果
|
|
|
|
|
+ * @param string $field 排序的字段名
|
|
|
|
|
+ * @param string $sortBy 排序类型
|
|
|
|
|
+ * @switch string asc正向排序 desc逆向排序 nat自然排序
|
|
|
|
|
+ *----------------------------------------------------------
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ *----------------------------------------------------------
|
|
|
|
|
+ */
|
|
|
|
|
+ function list_sort_by(array $list, string $field, string $sortBy = 'asc'): array
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!empty($list)) {
|
|
|
|
|
+ $refer = $resultSet = array();
|
|
|
|
|
+ foreach ($list as $i => $data)
|
|
|
|
|
+ $refer[$i] = &$data[$field];
|
|
|
|
|
+ switch ($sortBy) {
|
|
|
|
|
+ case 'asc': // 正向排序
|
|
|
|
|
+ asort($refer);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'desc':// 逆向排序
|
|
|
|
|
+ arsort($refer);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'nat': // 自然排序
|
|
|
|
|
+ natcasesort($refer);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ foreach ($refer as $key => $val)
|
|
|
|
|
+ $resultSet[] = &$list[$key];
|
|
|
|
|
+ return $resultSet;
|
|
|
|
|
+ }
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists('supplement_id')) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 用户ID风格
|
|
|
|
|
+ * @param string $id
|
|
|
|
|
+ * @return string
|
|
|
|
|
+ */
|
|
|
|
|
+ function supplement_id(string $id): string
|
|
|
|
|
+ {
|
|
|
|
|
+ $len = strlen($id);
|
|
|
|
|
+ $buf = '000000';
|
|
|
|
|
+ return $len < 6 ? substr($buf, 0, (6 - $len)) . $id : $id;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+if (!function_exists('createOrderId')) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 生成订单号
|
|
|
|
|
+ * @param string $letter
|
|
|
|
|
+ * @param int $length
|
|
|
|
|
+ * @return string
|
|
|
|
|
+ */
|
|
|
|
|
+ function createOrderId(string $letter = '', int $length = 3): string
|
|
|
|
|
+ {
|
|
|
|
|
+ $gradual = 0;
|
|
|
|
|
+ $orderId = date('YmdHis') . mt_rand(10000000, 99999999);
|
|
|
|
|
+ $lengths = strlen($orderId);
|
|
|
|
|
+
|
|
|
|
|
+ // 循环处理随机数
|
|
|
|
|
+ for ($i = 0; $i < $lengths; $i++) {
|
|
|
|
|
+ $gradual += (int)(substr($orderId, $i, 1));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (empty($letter)) {
|
|
|
|
|
+ $letter = get_order_letter($length);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $code = (100 - $gradual % 100) % 100;
|
|
|
|
|
+ return $letter . $orderId . str_pad((string)$code, 2, '0', STR_PAD_LEFT);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists('get_order_letter')) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 生成订单短ID
|
|
|
|
|
+ * @param int $length
|
|
|
|
|
+ * @return string
|
|
|
|
|
+ */
|
|
|
|
|
+ function get_order_letter(int $length = 2): string
|
|
|
|
|
+ {
|
|
|
|
|
+ $letter_all = range('A', 'Z');
|
|
|
|
|
+ shuffle($letter_all);
|
|
|
|
|
+ $letter_array = array_diff($letter_all, ['I', 'O']);
|
|
|
|
|
+ $letter = array_rand(array_flip($letter_array), $length);
|
|
|
|
|
+ return implode('', $letter);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 过滤emoji表情
|
|
|
|
|
+ * @param string $str
|
|
|
|
|
+ * @return string
|
|
|
|
|
+ */
|
|
|
|
|
+if (!function_exists('removeEmoji')) {
|
|
|
|
|
+ function removeEmoji(string $str = '') : string
|
|
|
|
|
+ {
|
|
|
|
|
+ $str = preg_replace('/[\x{1F600}-\x{1F64F}]/u', '', $str);
|
|
|
|
|
+ $str = preg_replace('/[\x{1F300}-\x{1F5FF}]/u', '', $str);
|
|
|
|
|
+ $str = preg_replace('/[\x{1F680}-\x{1F6FF}]/u', '', $str);
|
|
|
|
|
+ $str = preg_replace('/[\x{2600}-\x{26FF}]/u', '', $str);
|
|
|
|
|
+ return preg_replace('/[\x{2700}-\x{27BF}]/u', '', $str);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists('object_array')) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param $array
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ */
|
|
|
|
|
+ function object_array($array): array
|
|
|
|
|
+ {
|
|
|
|
|
+ if(is_object($array)) {
|
|
|
|
|
+ $array = (array)$array;
|
|
|
|
|
+ }
|
|
|
|
|
+ if(is_array($array)) {
|
|
|
|
|
+ foreach($array as $key=>$value) {
|
|
|
|
|
+ $array[$key] = object_array($value);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return $array;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists("getDateFull"))
|
|
|
|
|
+{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param string $format
|
|
|
|
|
+ * @param string $time
|
|
|
|
|
+ * @return string
|
|
|
|
|
+ */
|
|
|
|
|
+ function getDateFull(string $format = "Y-m-d H:i:s",string $time = ""): string
|
|
|
|
|
+ {
|
|
|
|
|
+ if (empty($time)) $time = time();
|
|
|
|
|
+ return date($format??'Y-m-d H:i:s',$time);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists("events"))
|
|
|
|
|
+{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 事件发布
|
|
|
|
|
+ * @param $name
|
|
|
|
|
+ * @param $data
|
|
|
|
|
+ * @return array|mixed|null
|
|
|
|
|
+ */
|
|
|
|
|
+ function events($name,$data): mixed
|
|
|
|
|
+ {
|
|
|
|
|
+ return Event::dispatch($name,$data);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists("success")) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param string $msg
|
|
|
|
|
+ * @param array $data
|
|
|
|
|
+ * @param int $code
|
|
|
|
|
+ * @return Response
|
|
|
|
|
+ */
|
|
|
|
|
+ function success(string $msg = "", array $data = [], int $code = 1): Response
|
|
|
|
|
+ {
|
|
|
|
|
+ return json(compact('code', 'data', 'msg'));
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists("successTrans")) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 消息返回
|
|
|
|
|
+ * @param string $message
|
|
|
|
|
+ * @param array $data
|
|
|
|
|
+ * @param int $code
|
|
|
|
|
+ * @return Response
|
|
|
|
|
+ */
|
|
|
|
|
+ function successTrans(string $message, array $data = [], int $code = 1): Response
|
|
|
|
|
+ {
|
|
|
|
|
+ $msg = trans($message);
|
|
|
|
|
+ return json(compact("msg", "code", "data"));
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists("error")) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param $msg
|
|
|
|
|
+ * @param array $data
|
|
|
|
|
+ * @param int $code
|
|
|
|
|
+ * @return Response
|
|
|
|
|
+ */
|
|
|
|
|
+ function error($msg, array $data = [], int $code = 0): Response
|
|
|
|
|
+ {
|
|
|
|
|
+ return json(compact('code', 'data', 'msg'));
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists("errorTrans")) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 消息返回
|
|
|
|
|
+ * @param string $message
|
|
|
|
|
+ * @param array $data
|
|
|
|
|
+ * @param int $code
|
|
|
|
|
+ * @return Response
|
|
|
|
|
+ */
|
|
|
|
|
+ function errorTrans(string $message = "", array $data = [], int $code = 0): Response
|
|
|
|
|
+ {
|
|
|
|
|
+ $msg = trans($message);
|
|
|
|
|
+ return json(compact("msg", "code", "data"));
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists("pageFormat")) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param $data
|
|
|
|
|
+ * @param int $size
|
|
|
|
|
+ * @return array {page:"",pageSize:"",rows:[],total:""}
|
|
|
|
|
+ */
|
|
|
|
|
+ function pageFormat($data, int $size = 10): array
|
|
|
|
|
+ {
|
|
|
|
|
+ if (empty($data)) return [];
|
|
|
|
|
+ return [
|
|
|
|
|
+ 'total' => $data->total(),
|
|
|
|
|
+ 'page' => $data->currentPage(),
|
|
|
|
|
+ 'pageSize' => $size,
|
|
|
|
|
+ 'rows' => $data->items()
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists("pageFormatMsg")) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param $data
|
|
|
|
|
+ * @param int $size
|
|
|
|
|
+ * @return array {page:"",pageSize:"",rows:[],total:""}
|
|
|
|
|
+ */
|
|
|
|
|
+ function pageFormatMsg($data, int $size = 10): array
|
|
|
|
|
+ {
|
|
|
|
|
+ if (empty($data)) return [];
|
|
|
|
|
+ $rowsData = [];
|
|
|
|
|
+ if ($data->total() > 0) {
|
|
|
|
|
+ foreach ($data as $key=>$row) {
|
|
|
|
|
+ $rowsData[$key] = $row->toArray();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return [
|
|
|
|
|
+ 'total' => $data->total(),
|
|
|
|
|
+ 'page' => $data->currentPage(),
|
|
|
|
|
+ 'pageSize' => $size,
|
|
|
|
|
+ 'rows' => list_sort_by($rowsData,"id","asc")
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+if(!function_exists('format_money')){
|
|
|
|
|
+ function format_money($str,$len = '2',$append = ""): string
|
|
|
|
|
+ {
|
|
|
|
|
+ if (empty($str)) {
|
|
|
|
|
+ return "0.00";
|
|
|
|
|
+ }
|
|
|
|
|
+ return number_format($str, $len, ".", $append);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists('sConf')) {
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取或配置系统参数
|
|
|
|
|
+ * @param string $name 参数名称
|
|
|
|
|
+ * @param string|null $value 参数内容
|
|
|
|
|
+ */
|
|
|
|
|
+ function sConf(string $name = '', string $value = null)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (is_null($value) && is_string($name)) {
|
|
|
|
|
+ return SystemService::get($name);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return SystemService::set($name, $value);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists('sData')) {
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * JSON 数据读取与存储
|
|
|
|
|
+ * @param string $name 数据名称
|
|
|
|
|
+ * @param mixed $value 数据内容
|
|
|
|
|
+ */
|
|
|
|
|
+ function sData(string $name,mixed $value = null)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (is_null($value)) {
|
|
|
|
|
+ return SystemService::getData($name);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return SystemService::setData($name, $value);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists('sOplog')) {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 写入系统日志
|
|
|
|
|
+ * @param string $action 日志行为
|
|
|
|
|
+ * @param string $content 日志内容
|
|
|
|
|
+ * @param string $userName
|
|
|
|
|
+ * @return boolean
|
|
|
|
|
+ */
|
|
|
|
|
+ function sOplog(string $action, string $content, string $userName): bool
|
|
|
|
|
+ {
|
|
|
|
|
+ return SystemService::setOplog($action, $content,$userName);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+if(!function_exists('store_region')){
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 返回附近司机数据
|
|
|
|
|
+ * @param $latitude
|
|
|
|
|
+ * @param $longitude
|
|
|
|
|
+ * @param $type 1 返回查询影响记录数;2 返回数据数组
|
|
|
|
|
+ */
|
|
|
|
|
+ function store_region($latitude,$longitude,$type = 1,$where = 'status = 1',$field="*"){
|
|
|
|
|
+ $sql = "select ".$field." from(
|
|
|
|
|
+SELECT id,poi_id,poi_name,status,poi_address,longitude,latitude,
|
|
|
|
|
+ROUND(6378.138*2*ASIN(SQRT(POW(SIN(({$latitude}*PI()/180-latitude*PI()/180)/2),2)+COS({$latitude}*PI()/180)*COS(latitude*PI()/180)*POW(SIN(({$longitude}*PI()/180-longitude*PI()/180)/2),2)))*1000) AS juli
|
|
|
|
|
+FROM saas_store_shop where ".$where.") as tmp_table_name order by juli asc";
|
|
|
|
|
+ if($type == 1){
|
|
|
|
|
+ return \think\facade\Db::execute($sql);
|
|
|
|
|
+ }
|
|
|
|
|
+ return \think\facade\Db::query($sql);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if(!function_exists('getHourlyTimeSlots')){
|
|
|
|
|
+ function getHourlyTimeSlots($startHour = 9, $endHour = 22, $format = 'H:i'): array
|
|
|
|
|
+ {
|
|
|
|
|
+ $slots = [];
|
|
|
|
|
+
|
|
|
|
|
+ for ($hour = $startHour; $hour < $endHour; $hour++) {
|
|
|
|
|
+ $startTime = sprintf('%02d:00', $hour);
|
|
|
|
|
+ $endTime = sprintf('%02d:00', $hour + 1);
|
|
|
|
|
+
|
|
|
|
|
+ $slots[] = [
|
|
|
|
|
+ 'start' => $startTime,
|
|
|
|
|
+ 'end' => $endTime,
|
|
|
|
|
+ 'display' => $startTime . ' - ' . $endTime
|
|
|
|
|
+ ];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $slots;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists("strToUniqueNumberV4"))
|
|
|
|
|
+{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 名称加密
|
|
|
|
|
+ * @param string $str
|
|
|
|
|
+ * @param string $salt
|
|
|
|
|
+ * @return string
|
|
|
|
|
+ */
|
|
|
|
|
+ function strToUniqueNumberV4(string $str = "", string $salt = ''): string
|
|
|
|
|
+ {
|
|
|
|
|
+ // 添加盐值增加唯一性
|
|
|
|
|
+ $str = $str . $salt;
|
|
|
|
|
+ // 使用多种哈希组合
|
|
|
|
|
+ $crc = abs(crc32($str));
|
|
|
|
|
+ $md5 = hexdec(substr(md5($str), 0, 8));
|
|
|
|
|
+ $sha1 = hexdec(substr(sha1($str), 0, 8));
|
|
|
|
|
+ // 组合并取模
|
|
|
|
|
+ $number = ($crc + $md5 + $sha1) % 1000000000000;
|
|
|
|
|
+ // 使用时间戳微调确保唯一性(针对同一字符串)
|
|
|
|
|
+ static $lastStr = '';
|
|
|
|
|
+ static $counter = 0;
|
|
|
|
|
+ if ($str === $lastStr) {
|
|
|
|
|
+ $counter++;
|
|
|
|
|
+ $number = ($number + $counter) % 1000000000000;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $lastStr = $str;
|
|
|
|
|
+ $counter = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ return str_pad($number, 12, '0', STR_PAD_LEFT);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (!function_exists("extractNodesClean"))
|
|
|
|
|
+{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 多维数组转N个一维
|
|
|
|
|
+ * @param $data
|
|
|
|
|
+ * @param array $result
|
|
|
|
|
+ * @return array
|
|
|
|
|
+ */
|
|
|
|
|
+ function extractNodesClean($data, array &$result = []): array
|
|
|
|
|
+ {
|
|
|
|
|
+ foreach ($data as $node) {
|
|
|
|
|
+ // 复制节点并删除 sub_tree_infos
|
|
|
|
|
+ $cleanNode = $node;
|
|
|
|
|
+ unset($cleanNode['sub_tree_infos']);
|
|
|
|
|
+ $result[] = $cleanNode;
|
|
|
|
|
+
|
|
|
|
|
+ // 递归处理子节点
|
|
|
|
|
+ if (isset($node['sub_tree_infos']) && is_array($node['sub_tree_infos'])) {
|
|
|
|
|
+ extractNodesClean($node['sub_tree_infos'], $result);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return $result;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+if (!function_exists("formatTime"))
|
|
|
|
|
+{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 格式化时间:今天、昨天、前天、正常日期
|
|
|
|
|
+ * @param string $timestamp 时间戳 或 日期字符串
|
|
|
|
|
+ * @return string
|
|
|
|
|
+ */
|
|
|
|
|
+ function formatTime(string $timestamp): string
|
|
|
|
|
+ {
|
|
|
|
|
+ // 先统一转成时间戳
|
|
|
|
|
+ $time = is_numeric($timestamp) ? $timestamp : strtotime($timestamp);
|
|
|
|
|
+
|
|
|
|
|
+ $today = strtotime('today'); // 今天 00:00
|
|
|
|
|
+ $yesterday = strtotime('yesterday'); // 昨天 00:00
|
|
|
|
|
+ $beforeYesterday = strtotime('-2 days'); // 前天 00:00
|
|
|
|
|
+
|
|
|
|
|
+ if ($time >= $today) {
|
|
|
|
|
+ return '今天';
|
|
|
|
|
+ } elseif ($time >= $yesterday) {
|
|
|
|
|
+ return '昨天';
|
|
|
|
|
+ } elseif ($time >= $beforeYesterday) {
|
|
|
|
|
+ return '前天';
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 其他时间返回正常格式
|
|
|
|
|
+ return date('Y-m-d', $time);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+if(! function_exists ('timeDiff') ) {
|
|
|
|
|
+ function timeDiff($begin_time, $end_time): array
|
|
|
|
|
+ {
|
|
|
|
|
+ if ($begin_time < $end_time) {
|
|
|
|
|
+ return ["day" => 0, "hour" => 0, "min" => 0, "sec" => 0];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $starttime = $end_time;
|
|
|
|
|
+ $endtime = $begin_time;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //计算天数
|
|
|
|
|
+ $timediff = $endtime - $starttime;
|
|
|
|
|
+ $days = intval($timediff / 86400);
|
|
|
|
|
+ //计算小时数
|
|
|
|
|
+ $remain = $timediff % 86400;
|
|
|
|
|
+ $hours = intval($remain / 3600);
|
|
|
|
|
+ //计算分钟数
|
|
|
|
|
+ $remain = $remain % 3600;
|
|
|
|
|
+ $mins = intval($remain / 60);
|
|
|
|
|
+ //计算秒数
|
|
|
|
|
+ $secs = $remain % 60;
|
|
|
|
|
+ return ["day" => $days, "hour" => $hours, "min" => $mins, "sec" => $secs];
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if(! function_exists('filterTreeByTargets'))
|
|
|
|
|
+{
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 过滤树,仅保留包含任何目标 category_id 的节点及其祖先
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param array $tree 原始树
|
|
|
|
|
+ * @param array $targetIds 目标 category_id 列表
|
|
|
|
|
+ * @return array 过滤后的树(保持原结构)
|
|
|
|
|
+ */
|
|
|
|
|
+ function filterTreeByTargets($tree, $targetIds) {
|
|
|
|
|
+ $filtered = [];
|
|
|
|
|
+ foreach ($tree as $node) {
|
|
|
|
|
+ // 检查当前节点或子树中是否包含任一目标 ID
|
|
|
|
|
+ $contains = false;
|
|
|
|
|
+ if (in_array($node['category_id'], $targetIds)) {
|
|
|
|
|
+ $contains = true;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 递归检查子节点
|
|
|
|
|
+ $children = [];
|
|
|
|
|
+ if (!empty($node['children']) && is_array($node['children'])) {
|
|
|
|
|
+ $children = filterTreeByTargets($node['children'], $targetIds);
|
|
|
|
|
+ if (!empty($children)) {
|
|
|
|
|
+ $contains = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ($contains) {
|
|
|
|
|
+ // 保留当前节点,并合并过滤后的子节点
|
|
|
|
|
+ $newNode = $node;
|
|
|
|
|
+ if (!empty($node['children']) && is_array($node['children'])) {
|
|
|
|
|
+ $newNode['children'] = filterTreeByTargets($node['children'], $targetIds);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $newNode['children'] = [];
|
|
|
|
|
+ }
|
|
|
|
|
+ $filtered[] = $newNode;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return $filtered;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if(! function_exists('addTypesRecursive'))
|
|
|
|
|
+{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 为树中每个节点添加 types 字段
|
|
|
|
|
+ */
|
|
|
|
|
+ function addTypesRecursive(&$nodes, $typeMap) {
|
|
|
|
|
+ foreach ($nodes as &$node) {
|
|
|
|
|
+ $node['types'] = $typeMap[$node['category_id']] ?? '';
|
|
|
|
|
+ if (isset($node['children']) && is_array($node['children'])) {
|
|
|
|
|
+ addTypesRecursive($node['children'], $typeMap);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+if(! function_exists('emojiToUnicode'))
|
|
|
|
|
+{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param string $str
|
|
|
|
|
+ * @return string
|
|
|
|
|
+ */
|
|
|
|
|
+ function emojiToUnicode(string $str): string
|
|
|
|
|
+ {
|
|
|
|
|
+ return trim(json_encode($str, JSON_UNESCAPED_SLASHES), '"');
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if(! function_exists('unicodeToEmoji'))
|
|
|
|
|
+{
|
|
|
|
|
+ function unicodeToEmoji(string $str): string
|
|
|
|
|
+ {
|
|
|
|
|
+ return json_decode("\"{$str}\"");
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if(! function_exists('removeEmoji2'))
|
|
|
|
|
+{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 清除字符串中所有emoji表情
|
|
|
|
|
+ * @param string $str
|
|
|
|
|
+ * @return string
|
|
|
|
|
+ */
|
|
|
|
|
+ function removeEmoji2(string $str): string
|
|
|
|
|
+ {
|
|
|
|
|
+ // 匹配绝大部分emoji Unicode区间
|
|
|
|
|
+ $pattern = '/[\x{1F600}-\x{1F64F}\x{1F300}-\x{1F5FF}\x{1F680}-\x{1F6FF}\x{1F1E0}-\x{1F1FF}\x{2600}-\x{26FF}\x{2700}-\x{27BF}\xFE00-\xFE0F\x{1F900}-\x{1F9FF}]/u';
|
|
|
|
|
+ return preg_replace($pattern, '', $str);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+if(! function_exists('str_cut_ellipsis'))
|
|
|
|
|
+{
|
|
|
|
|
+ function str_cut_ellipsis(string $str, int $len = 20, string $dot = '...'): string
|
|
|
|
|
+ {
|
|
|
|
|
+ if (mb_strlen($str, 'UTF-8') <= $len) {
|
|
|
|
|
+ return $str;
|
|
|
|
|
+ }
|
|
|
|
|
+ return mb_substr($str, 0, $len, 'UTF-8') . $dot;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+if (! function_exists('filterHtmlTags'))
|
|
|
|
|
+{
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 批量修改 HTML 中指定标签的属性和样式
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param string $html 原始 HTML 内容
|
|
|
|
|
+ * @param array $rules 规则数组,键为标签名(小写),值为配置:
|
|
|
|
|
+ * [
|
|
|
|
|
+ * 'remove' => ['width', 'height'], // 要移除的属性名列表
|
|
|
|
|
+ * 'style' => ['width' => '100%', 'margin' => '0'] // 要强制设置/覆盖的样式
|
|
|
|
|
+ * ]
|
|
|
|
|
+ * @return string 处理后的 HTML
|
|
|
|
|
+ */
|
|
|
|
|
+ function filterHtmlTags($html, $rules) {
|
|
|
|
|
+ // 匹配所有标签的开始部分:<标签名 属性...> 或 <标签名 属性.../> 或 <标签名>
|
|
|
|
|
+ $pattern = '/<(\w+)(?:\s+([^>]*?))?\/?>/i';
|
|
|
|
|
+ return preg_replace_callback($pattern, function($matches) use ($rules) {
|
|
|
|
|
+ $tag = strtolower($matches[1]);
|
|
|
|
|
+ // 如果该标签不在规则中,直接返回原匹配
|
|
|
|
|
+ if (!isset($rules[$tag])) {
|
|
|
|
|
+ return $matches[0];
|
|
|
|
|
+ }
|
|
|
|
|
+ $rule = $rules[$tag];
|
|
|
|
|
+ // 解析属性(如果有)
|
|
|
|
|
+ $attrStr = isset($matches[2]) ? $matches[2] : '';
|
|
|
|
|
+ $attrArray = [];
|
|
|
|
|
+ if ($attrStr) {
|
|
|
|
|
+ // 匹配 属性名="值" 或 属性名='值' 或 属性名=值
|
|
|
|
|
+ preg_match_all('/([a-zA-Z-]+)\s*=\s*("([^"]*)"|\'([^\']*)\'|([^\s>]+))/', $attrStr, $matchesAttr, PREG_SET_ORDER);
|
|
|
|
|
+ foreach ($matchesAttr as $m) {
|
|
|
|
|
+ $name = strtolower($m[1]);
|
|
|
|
|
+ $value = isset($m[3]) ? $m[3] : (isset($m[4]) ? $m[4] : $m[5]);
|
|
|
|
|
+ $attrArray[$name] = $value;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 移除指定属性
|
|
|
|
|
+ if (isset($rule['remove'])) {
|
|
|
|
|
+ foreach ($rule['remove'] as $attr) {
|
|
|
|
|
+ unset($attrArray[$attr]);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 处理样式
|
|
|
|
|
+ if (isset($rule['style']) && is_array($rule['style'])) {
|
|
|
|
|
+ $oldStyle = isset($attrArray['style']) ? $attrArray['style'] : '';
|
|
|
|
|
+ $styles = [];
|
|
|
|
|
+ if ($oldStyle) {
|
|
|
|
|
+ // 简单解析,按分号分割
|
|
|
|
|
+ $parts = array_filter(array_map('trim', explode(';', $oldStyle)));
|
|
|
|
|
+ foreach ($parts as $part) {
|
|
|
|
|
+ if (strpos($part, ':') !== false) {
|
|
|
|
|
+ list($key, $value) = array_map('trim', explode(':', $part, 2));
|
|
|
|
|
+ $styles[$key] = $value;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 强制覆盖(或添加)样式
|
|
|
|
|
+ foreach ($rule['style'] as $key => $value) {
|
|
|
|
|
+ $styles[$key] = $value;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 重组 style
|
|
|
|
|
+ $newStyle = '';
|
|
|
|
|
+ foreach ($styles as $k => $v) {
|
|
|
|
|
+ $newStyle .= $k . ':' . $v . ';';
|
|
|
|
|
+ }
|
|
|
|
|
+ $attrArray['style'] = $newStyle;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 重建属性字符串
|
|
|
|
|
+ $newAttr = '';
|
|
|
|
|
+ foreach ($attrArray as $k => $v) {
|
|
|
|
|
+ $newAttr .= ' ' . $k . '="' . htmlspecialchars($v, ENT_QUOTES, 'UTF-8') . '"';
|
|
|
|
|
+ }
|
|
|
|
|
+ return '<' . $tag . $newAttr . '>';
|
|
|
|
|
+ }, $html);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|