智慧教务系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

320 lines
10 KiB

<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace app\service\api\apiService;
use app\model\class_grade\ClassGrade;
use app\model\course\Course;
use app\model\dict\Dict;
use app\model\member\Member;
use app\model\sys\SysConfig;
use app\model\sys\SysUser;
use core\base\BaseApiService;
/**
* 公共服务层
* Class MemberService
* @package app\service\api\member
*/
class CommonService extends BaseApiService
{
public function __construct()
{
parent::__construct();
}
//获取字典
public function getDictionary(array $where,string $field = '*'){
$model = (new Dict());
if(!empty($where['key'])){
$model = $model->where('key',$where['key']);
}
$res = $model->field($field)->find();//员工信息
if($res){
$res = $res->toArray()['dictionary'];
}else{
$res = [];
}
return $res;
}
/**
* 忘记密码功能 - 根据用户类型重置密码
* @param string $phone 用户手机号
* @param string $new_password 用户新密码
* @param string $user_type 用户类型|customer=学生|personnel=员工(销售/教师)
*/
public function forgetPassword($phone, $new_password, $user_type){
if($user_type == 'personnel'){
$data = SysUser::where('username', $phone)->find();
if (!$data){
$res = [
'code' => 0,
'msg' => '用户不存在',
'data' => []
];
return $res;
}
//重置员工(销售/教师)密码
$update = SysUser::where('username', $phone)->update([
'password' => create_password($new_password),//创建密码
'update_time' => time(),
]);
if (!$update) {
$res = [
'code' => 0,
'msg' => '操作失败',
'data' => []
];
} else {
$res = [
'code' => 1,
'msg' => '操作成功',
'data' => []
];
}
return $res;
}else{
$data = Member::where('username', $phone)->find();
if (!$data){
$res = [
'code' => 0,
'msg' => '用户不存在',
'data' => []
];
return $res;
}
//重置用户(学生)密码
$update = Member::where('username', $phone)->update([
'password' => create_password($new_password),//创建密码
'update_time' => time(),
]);
if (!$update) {
$res = [
'code' => 0,
'msg' => '操作失败',
'data' => []
];
} else {
$res = [
'code' => 1,
'msg' => '操作成功',
'data' => []
];
}
return $res;
}
}
/**
* 对比新旧数据改变
* @param array $old_data 旧数据
* @param array $new_data 新数据
* @param array $ignoreFields 忽略验证的字段|默认[]
* @return array
*/
public function compareData(array $old_data, array $new_data, array $ignoreFields = ['updated_at'])
{
$changedFields = [];//改了那些字段
$oldChanges = [];//数据修改前的样子
$newChanges = [];//数据修改后的样子
foreach ($new_data as $key => $value) {
// 如果字段在忽略列表中,则跳过
if (in_array($key, $ignoreFields)) {
continue;
}
if (!isset($old_data[$key]) || $old_data[$key] != $value) {
$changedFields[] = $key;
$oldChanges[$key] = $old_data[$key] ?? null;
$newChanges[$key] = $value;
}
}
return [
// 返回发生更改的字段名数组
'changed_fields' => $changedFields,
// 返回旧数据中的更改字段及其值
'old_values' => $oldChanges,
// 返回新数据中的更改字段及其值
'new_values' => $newChanges,
// 将 changed_fields 转换为 JSON 格式,保留中文字符
'changed_fields_json' => json_encode($changedFields, JSON_UNESCAPED_UNICODE),
// 将 old_changes 转换为 JSON 格式,保留中文字符
'old_values_json' => json_encode($oldChanges, JSON_UNESCAPED_UNICODE),
// 将 new_changes 转换为 JSON 格式,保留中文字符
'new_values_json' => json_encode($newChanges, JSON_UNESCAPED_UNICODE)
];
}
/**
* 判断是否在打卡范围内
* @param float $campusLat 地理围栏中心纬度
* @param float $campusLng 地理围栏中心经度
* @param float $checkLat 打卡纬度
* @param float $checkLng 打卡经度
* @param float $radius 地理围栏半径(单位:米)
* @return bool 返回是否在范围内的布尔值
*/
public function isInCheckRange(float $campusLat, float $campusLng, float $checkLat, float $checkLng, float $radius = 3000.0): bool
{
// 使用 Haversine 公式计算两点之间的距离
$earthRadius = 6371000; // 地球半径,单位为米
$latFrom = deg2rad($campusLat);
$lngFrom = deg2rad($campusLng);
$latTo = deg2rad($checkLat);
$lngTo = deg2rad($checkLng);
$latDelta = $latTo - $latFrom;
$lngDelta = $lngTo - $lngFrom;
$angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
cos($latFrom) * cos($latTo) * pow(sin($lngDelta / 2), 2)));
$distance = $angle * $earthRadius;
// 判断计算出的距离是否小于等于设定的围栏半径
return $distance <= $radius;//false=超出打卡范围
}
/**
* 获取配置文件
* @param array $where
*/
public function getConfig(array $where){
$model = (new SysConfig());
if(!empty($where['config_key'])){
$model = $model->where('config_key',$where['config_key']);
}
$data = $model->find();//员工信息
if($data){
$data = $data->toArray();
}else{
$data = [];
}
return $data;
}
//获取微信小程序openid
public function getMiniWxOpenId(string $code)
{
// 微信小程序登录接口地址
$url = 'https://api.weixin.qq.com/sns/jscode2session';
// 从配置中获取appid和secret
$config = (new SysConfig())->where('config_key', 'weapp')->find();//微信小程序配置信息
if (!$config) {
return [
'code' => 0,
'msg' => '未找到微信小程序配置信息',
'data' => []
];
}
$configData = $config->toArray();
$params = [
'appid' => $configData['value']['app_id'] ?? '',
'secret' => $configData['value']['app_secret'] ?? '',
'js_code' => $code,
'grant_type' => 'authorization_code'
];
// 发起请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url . '?' . http_build_query($params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
// 处理响应
$result = json_decode($response, true);
if (isset($result['errcode']) && $result['errcode'] != 0) {
return [
'code' => 0,
'msg' => '获取 openid 失败: ' . $result['errmsg'],
'data' => []
];
}
return [
'code' => 1,
'msg' => '操作成功',
'data' => [
'openid' => $result['openid'] ?? '',
'session_key' => $result['session_key'] ?? ''
]
];
}
//获取全部课程列表
public function getCourseAllList(array $where, string $field = '*')
{
$model = (new Course());
$res = $model->field($field)
->select()
->toArray();//员工信息
return $res;
}
//获取全部班级列表
public function getClassAllList(array $where, string $field = '*')
{
$model = (new ClassGrade());
if(!empty($where['status'])){
$model = $model->where('status',$where['status']);
}
$res = $model->field($field)
->select()
->toArray();//员工信息
return $res;
}
//获取支付类型字典(员工端过滤client_wxpay)
public function getPaymentTypes()
{
$dictData = $this->getDictionary(['key' => 'payment_type']);
if (empty($dictData)) {
return [];
}
// 如果已经是数组,直接使用;如果是JSON字符串,则解析
$paymentTypes = is_array($dictData) ? $dictData : json_decode($dictData, true);
if (!is_array($paymentTypes)) {
return [];
}
// 过滤掉员工端不可选的支付类型
$filteredTypes = array_filter($paymentTypes, function($type) {
return isset($type['value']) && $type['value'] !== 'client_wxpay';
});
// 重新索引数组
return array_values($filteredTypes);
}
}