Browse Source

修改 bug

master
王泽彦 9 months ago
parent
commit
2291886dcf
  1. 43
      niucloud/app/Request.php
  2. 4
      niucloud/app/api/controller/member/Member.php
  3. 3
      niucloud/app/api/route/member.php
  4. 2
      niucloud/app/model/personnel_data/PersonnelData.php
  5. 14
      niucloud/app/service/api/member/MemberService.php
  6. 2
      niucloud/core/base/BaseApiService.php
  7. 62
      uniapp/api/apiRoute.js
  8. 38
      uniapp/common/axios.js
  9. 10
      uniapp/common/config.js
  10. 195
      uniapp/components/custom-picker/single-picker.vue
  11. 3
      uniapp/pages.json
  12. 75
      uniapp/pages/coach/schedule/add_schedule.vue
  13. 185
      uniapp/pages/coach/student/student_list.vue

43
niucloud/app/Request.php

@ -1,7 +1,9 @@
<?php <?php
namespace app; namespace app;
use app\dict\common\ChannelDict; use app\dict\common\ChannelDict;
use app\model\campus_person_role\CampusPersonRole;
/** /**
* Class Request * Class Request
@ -29,15 +31,14 @@ class Request extends \think\Request
// 解析name // 解析name
if (strpos($key, '/')) { if (strpos($key, '/')) {
[$name, $type] = explode('/', $key); [$name, $type] = explode('/', $key);
}else{ } else {
$name = $key; $name = $key;
} }
$default = $param[1]; $default = $param[1];
$item_filter = $param[2] ?? $filter; $item_filter = $param[2] ?? $filter;
$input[$key] = $this->paramFilter($this->param($key, $default, $filter_rule ?? ''), $item_filter); $input[$key] = $this->paramFilter($this->param($key, $default, $filter_rule ?? ''), $item_filter);
//过滤后产生空字符串,按照默认值 //过滤后产生空字符串,按照默认值
if($input[$name] === '') if ($input[$name] === '') {
{
$input[$name] = $default; $input[$name] = $default;
} }
} }
@ -110,7 +111,8 @@ class Request extends \think\Request
* @param string $app_type * @param string $app_type
* @return mixed|string * @return mixed|string
*/ */
public function appType(string $app_type = ''){ public function appType(string $app_type = '')
{
if (!empty($app_type)) { if (!empty($app_type)) {
static::$auth_info['app_type'] = $app_type; static::$auth_info['app_type'] = $app_type;
return $app_type; return $app_type;
@ -123,7 +125,8 @@ class Request extends \think\Request
* 获取管理端token * 获取管理端token
* @return array|string|null * @return array|string|null
*/ */
public function adminToken(){ public function adminToken()
{
return $this->header(system_name('admin_token_name')); return $this->header(system_name('admin_token_name'));
} }
@ -132,7 +135,8 @@ class Request extends \think\Request
* 获取会员token * 获取会员token
* @return array|string|null * @return array|string|null
*/ */
public function apiToken(){ public function apiToken()
{
return $this->header(system_name('api_token_name')); return $this->header(system_name('api_token_name'));
} }
@ -140,7 +144,8 @@ class Request extends \think\Request
* 获取场景 * 获取场景
* @return array|string * @return array|string
*/ */
public function getChannel(){ public function getChannel()
{
return $this->header(system_name('channel_name'), ChannelDict::H5); return $this->header(system_name('channel_name'), ChannelDict::H5);
} }
@ -149,7 +154,8 @@ class Request extends \think\Request
* @param $data * @param $data
* @return void * @return void
*/ */
public function pushGet($data){ public function pushGet($data)
{
$param = $this->get(); $param = $this->get();
$this->withGet(array_merge($param, $data)); $this->withGet(array_merge($param, $data));
} }
@ -159,7 +165,8 @@ class Request extends \think\Request
* @param $data * @param $data
* @return void * @return void
*/ */
public function pushHeader($data){ public function pushHeader($data)
{
$param = $this->header(); $param = $this->header();
$this->withHeader(array_merge($param, $data)); $this->withHeader(array_merge($param, $data));
} }
@ -170,11 +177,27 @@ class Request extends \think\Request
* @param $value * @param $value
* @return mixed|string|void * @return mixed|string|void
*/ */
public function auth($key, $value = ''){ public function auth($key, $value = '')
{
if (!empty($value)) { if (!empty($value)) {
static::$auth_info[$key] = $value; static::$auth_info[$key] = $value;
} else { } else {
return static::$auth_info[$key] ?? ''; return static::$auth_info[$key] ?? '';
} }
} }
/**
* 获取人员角色信息
* @return array|string
*/
public function getRoleInfo($key = false)
{
$id = static::$auth_info['member_id'] ?? 0;
$role = CampusPersonRole::where('person_id', $id)
->find();
if ($role) {
$role = $role->toArray();
}
return $key ? $role[$key] ?? '' : $role;
}
} }

4
niucloud/app/api/controller/member/Member.php

@ -203,5 +203,7 @@ class Member extends BaseApiController
return success(( new MemberService() )->contract_sign($data)); return success(( new MemberService() )->contract_sign($data));
} }
public function get_classes_list(){
return success(( new MemberService() )->get_classes_list());
}
} }

3
niucloud/app/api/route/member.php

@ -122,6 +122,9 @@ Route::group('member', function () {
Route::get('sktj', 'member.Member/sktj'); Route::get('sktj', 'member.Member/sktj');
Route::post('contract_sign', 'member.Member/contract_sign'); Route::post('contract_sign', 'member.Member/contract_sign');
Route::get('get_classes_list', 'member.Member/get_classes_list');
Route::get('get_courses_list', 'member.Member/get_courses_list');
})->middleware(ApiChannel::class) })->middleware(ApiChannel::class)
->middleware(ApiPersonnelCheckToken::class, true) ->middleware(ApiPersonnelCheckToken::class, true)
->middleware(ApiLog::class); ->middleware(ApiLog::class);

2
niucloud/app/model/personnel_data/PersonnelData.php

@ -42,7 +42,7 @@ class PersonnelData extends BaseModel
* 定义软删除标记字段. * 定义软删除标记字段.
* @var string * @var string
*/ */
protected $deleteTime = 'delete_time'; protected $deleteTime = 'deleted_at';
/** /**
* 定义软删除字段的默认值. * 定义软删除字段的默认值.

14
niucloud/app/service/api/member/MemberService.php

@ -14,9 +14,11 @@ namespace app\service\api\member;
use app\model\assignment\Assignment; use app\model\assignment\Assignment;
use app\model\attendance\Attendance; use app\model\attendance\Attendance;
use app\model\campus\Campus; use app\model\campus\Campus;
use app\model\class_grade\ClassGrade;
use app\model\class_resources_rel\ClassResourcesRel; use app\model\class_resources_rel\ClassResourcesRel;
use app\model\communication_records\CommunicationRecords; use app\model\communication_records\CommunicationRecords;
use app\model\contract_sign\ContractSign; use app\model\contract_sign\ContractSign;
use app\model\course\Course;
use app\model\course_schedule\CourseSchedule; use app\model\course_schedule\CourseSchedule;
use app\model\member\Member; use app\model\member\Member;
use app\model\person_course_schedule\PersonCourseSchedule; use app\model\person_course_schedule\PersonCourseSchedule;
@ -479,4 +481,16 @@ class MemberService extends BaseApiService
return true; return true;
} }
public function get_classes_list()
{
$data['classes'] = ClassGrade::where('status',1)
->when($this->campus_id, function ($query) {
$query->where('campus_id', $this->campus_id);
})
->select();
$data['course'] = Course::select();
return $data;
}
} }

2
niucloud/core/base/BaseApiService.php

@ -21,11 +21,13 @@ class BaseApiService extends BaseService
protected $member_id; protected $member_id;
protected $channel; protected $channel;
protected $campus_id;
public function __construct() public function __construct()
{ {
parent::__construct(); parent::__construct();
$this->member_id = $this->request->memberId(); $this->member_id = $this->request->memberId();
$this->channel = $this->request->getChannel(); $this->channel = $this->request->getChannel();
$this->campus_id = $this->request->getRoleInfo('campus_id');
} }
} }

62
uniapp/api/apiRoute.js

@ -30,30 +30,6 @@ export default {
return await http.get('/common/getDictionary', data); return await http.get('/common/getDictionary', data);
}, },
// 课程安排列表
async getCourseScheduleList(data = {}) {
return await http.get('/courseSchedule/list', data);
},
// 课程安排时间段
async getCourseScheduleTimeSlots(data = {}) {
return await http.get('/courseSchedule/timeSlots', data);
},
// 课程安排筛选选项
async getCourseScheduleFilterOptions(data = {}) {
return await http.get('/courseSchedule/filterOptions', data);
},
// 课程安排详情
async getCourseScheduleInfo(data = {}) {
return await http.get('/courseSchedule/info', data);
},
// 提交课程点名
async submitScheduleSignIn(data = {}) {
return await http.post('/courseSchedule/signIn', data);
},
// 课程安排列表 - Mock版本 // 课程安排列表 - Mock版本
async getCourseScheduleListMock(data = {}) { async getCourseScheduleListMock(data = {}) {
@ -310,10 +286,7 @@ export default {
async jlPublishJob(data = {}) { async jlPublishJob(data = {}) {
return await http.get('/class/jlPublishJob/add', data); return await http.get('/class/jlPublishJob/add', data);
}, },
//添加作业-学员列表
async jlGetStudentList(data = {}) {
return await http.get('/class/jlGetStudentList/list', data);
},
//添加作业-获取课程列表 //添加作业-获取课程列表
async jlGetCoursesList(data = {}) { async jlGetCoursesList(data = {}) {
return await http.get('/class/jlGetCoursesList/list', data); return await http.get('/class/jlGetCoursesList/list', data);
@ -625,7 +598,9 @@ export default {
}, },
// 创建课程安排 // 创建课程安排
async createCourseSchedule(data = {}) { async createCourseSchedule(data = {}) {
return await http.post('/courseSchedule/create', data); const token = uni.getStorageSync("token");
const apiPath = token ? '/courseSchedule/create' : '/test/courseSchedule/create';
return await http.post(apiPath, data);
}, },
// 批量创建课程安排 // 批量创建课程安排
async batchCreateCourseSchedule(data = {}) { async batchCreateCourseSchedule(data = {}) {
@ -639,11 +614,11 @@ export default {
async deleteCourseSchedule(data = {}) { async deleteCourseSchedule(data = {}) {
return await http.post('/courseSchedule/delete', data); return await http.post('/courseSchedule/delete', data);
}, },
// 获取场地列表 // 获取场地列表(课程安排模块专用)
async getCourseScheduleVenues(data = {}) { async getCourseScheduleVenues(data = {}) {
return await http.get('/courseSchedule/venues', data); return await http.get('/courseSchedule/venues', data);
}, },
// 获取场地可用时间 // 获取场地可用时间(课程安排模块专用)
async getVenueAvailableTime(data = {}) { async getVenueAvailableTime(data = {}) {
return await http.get('/courseSchedule/venueAvailableTime', data); return await http.get('/courseSchedule/venueAvailableTime', data);
}, },
@ -676,22 +651,33 @@ export default {
//↓↓↓↓↓↓↓↓↓↓↓↓-----添加课程安排页面专用接口-----↓↓↓↓↓↓↓↓↓↓↓↓ //↓↓↓↓↓↓↓↓↓↓↓↓-----添加课程安排页面专用接口-----↓↓↓↓↓↓↓↓↓↓↓↓
// 获取课程列表(用于添加课程安排) // 获取课程列表(用于添加课程安排)
async getCourseListForSchedule(data = {}) { async getCourseListForSchedule(data = {}) {
return await http.get('/course/list', data); // 检查是否有token,如果没有则使用测试接口
const token = uni.getStorageSync("token");
const apiPath = token ? '/course/list' : '/test/course/list';
return await http.get(apiPath, data);
}, },
// 获取班级列表(用于添加课程安排) // 获取班级列表(用于添加课程安排)
async getClassListForSchedule(data = {}) { async getClassListForSchedule(data = {}) {
return await http.get('/class/list', data); const token = uni.getStorageSync("token");
const apiPath = token ? '/class/list' : '/test/class/list';
return await http.get(apiPath, data);
}, },
// 获取教练列表(用于添加课程安排) // 获取教练列表(用于添加课程安排)
async getCoachListForSchedule(data = {}) { async getCoachListForSchedule(data = {}) {
return await http.get('/coach/list', data); const token = uni.getStorageSync("token");
const apiPath = token ? '/coach/list' : '/test/coach/list';
return await http.get(apiPath, data);
}, },
// 获取场地列表(用于添加课程安排) // 获取场地列表(用于添加课程安排 - 新开发的通用接口
async getVenueListForSchedule(data = {}) { async getVenueListForSchedule(data = {}) {
return await http.get('/venue/list', data); const token = uni.getStorageSync("token");
const apiPath = token ? '/venue/list' : '/test/venue/list';
return await http.get(apiPath, data);
}, },
// 获取场地可用时间段 // 获取场地可用时间段(新开发的通用接口)
async getVenueTimeSlots(data = {}) { async getVenueTimeSlots(data = {}) {
return await http.get('/venue/timeSlots', data); const token = uni.getStorageSync("token");
const apiPath = token ? '/venue/timeSlots' : '/test/venue/timeSlots';
return await http.get(apiPath, data);
}, },
} }

38
uniapp/common/axios.js

@ -10,9 +10,9 @@ const debounce = (fn, delay = 1000) => {
return function (...args) { return function (...args) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (timer) clearTimeout(timer); if (timer) clearTimeout(timer);
timer = setTimeout(() => { timer = setTimeout(async () => {
try { try {
const result = fn.apply(this, args); const result = await fn.apply(this, args);
resolve(result); resolve(result);
} catch (error) { } catch (error) {
reject(error); reject(error);
@ -38,12 +38,13 @@ const requestInterceptor = (config) => {
// 响应拦截器 // 响应拦截器
const responseInterceptor = (response) => { const responseInterceptor = (response) => {
const { statusCode, data } = response; const { statusCode, data } = response;
console.log('响应数据:', response); console.log('响应拦截器处理:', { statusCode, data });
// 处理HTTP状态码 // 处理HTTP状态码
if (statusCode >= 200 && statusCode < 300) { if (statusCode >= 200 && statusCode < 300) {
// 处理业务状态码 // 处理业务状态码
if (data && data.code) { if (data && typeof data.code !== 'undefined') {
console.log('业务状态码:', data.code);
if (data.code === 1) { // 成功状态码为1 if (data.code === 1) { // 成功状态码为1
// 登录成功,保存token // 登录成功,保存token
if (data.data && data.data.token) { if (data.data && data.data.token) {
@ -59,6 +60,7 @@ const responseInterceptor = (response) => {
} }
return data; return data;
} else if (data.code === 401) { } else if (data.code === 401) {
console.error('401错误 - 未授权');
// 未授权或token过期,清除所有用户缓存信息 // 未授权或token过期,清除所有用户缓存信息
// 清除token // 清除token
uni.removeStorageSync("token"); uni.removeStorageSync("token");
@ -91,25 +93,23 @@ const responseInterceptor = (response) => {
url: '/pages/student/login/login?code=401' url: '/pages/student/login/login?code=401'
}); });
}, 1500); }, 1500);
return Promise.reject(data); throw new Error(data.msg || '未授权');
} else { } else {
// 其他业务错误 // 其他业务错误
uni.showToast({ console.error('业务错误:', data);
title: data.msg || '请求失败', throw new Error(data.msg || '请求失败');
icon: 'none'
});
return Promise.reject(data);
} }
} }
return data; return data;
} }
// HTTP错误处理 // HTTP错误处理
console.error('HTTP错误:', response);
uni.showToast({ uni.showToast({
title: '网络请求失败', title: '网络请求失败',
icon: 'none' icon: 'none'
}); });
return Promise.reject(response); throw new Error('网络请求失败');
}; };
export default { export default {
@ -132,8 +132,9 @@ export default {
} }
}, },
// 防抖处理 // 简化请求处理,去掉防抖避免问题
uni_request: debounce((options) => { uni_request(options) {
console.log('发起请求:', options);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// 创建请求配置 // 创建请求配置
const config = { const config = {
@ -146,22 +147,27 @@ export default {
timeout: 10000 // 设置10秒超时 timeout: 10000 // 设置10秒超时
}; };
console.log('请求配置:', config);
// 应用请求拦截器 // 应用请求拦截器
const interceptedConfig = requestInterceptor(config); const interceptedConfig = requestInterceptor(config);
uni.showLoading({ uni.showLoading({
title: '加载中...' title: '加载中...'
}); });
console.log('即将发起uni.request');
uni.request({ uni.request({
...interceptedConfig, ...interceptedConfig,
success: (res) => { success: (res) => {
console.log('请求成功响应:', res);
try { try {
const response = responseInterceptor(res); const response = responseInterceptor(res);
resolve(response); resolve(response);
} catch (error) { } catch (error) {
console.error('请求处理失败:', error); console.error('请求处理失败:', error);
uni.showToast({ uni.showToast({
title: error.msg || '请求失败', title: error.message || '请求失败',
icon: 'none' icon: 'none'
}); });
reject(error); reject(error);
@ -176,11 +182,12 @@ export default {
reject(error); reject(error);
}, },
complete: () => { complete: () => {
console.log('请求完成');
uni.hideLoading(); uni.hideLoading();
} }
}); });
}); });
}, 100), },
// 封装请求方法 // 封装请求方法
post(url, data = {}) { post(url, data = {}) {
@ -192,6 +199,7 @@ export default {
}, },
get(url, data = {}) { get(url, data = {}) {
console.log('调用get方法:', { url, data });
return this.uni_request({ return this.uni_request({
url, url,
data, data,

10
uniapp/common/config.js

@ -3,12 +3,12 @@
// const img_domian = 'http://146.56.228.75:20025/' // const img_domian = 'http://146.56.228.75:20025/'
//本地测试地址 //本地测试地址
// const Api_url='http://zhjwxt.test/api' const Api_url='http://localhost:20080/api'
// const img_domian = 'http://zhjwxt.test/' const img_domian = 'http://localhost:20080/'
// 生产环境地址
const Api_url='https://api.hnhbty.cn/api' // const Api_url='https://api.hnhbty.cn/api'
const img_domian = 'https://api.hnhbty.cn/' // const img_domian = 'https://api.hnhbty.cn/'
// const Api_url='http://146.56.228.75:20024/api' // const Api_url='http://146.56.228.75:20024/api'
// const img_domian = 'http://146.56.228.75:20024/' // const img_domian = 'http://146.56.228.75:20024/'

195
uniapp/components/custom-picker/single-picker.vue

@ -0,0 +1,195 @@
<template>
<view class="single-picker">
<fui-picker
:layer="1"
:options="formattedOptions"
:show="show"
@change="onChange"
@cancel="onCancel"
:title="title"
></fui-picker>
</view>
</template>
<script>
/**
* 通用单选选择器组件
* @description 基于FirstUI的fui-picker组件封装的通用单选选择器支持灵活配置
*/
export default {
name: "single-picker",
props: {
/**
* 是否显示选择器
* @property {Boolean} show - 控制选择器的显示与隐藏
* @default false
*/
show: {
type: Boolean,
default: false
},
/**
* 数据源
* @property {Array} data - 选择器数据数组
* @default []
*/
data: {
type: Array,
default() {
return []
},
validator(value) {
//
return Array.isArray(value)
}
},
/**
* 值字段名
* @property {String} valueKey - 用作选项值的字段名
* @default 'value'
*/
valueKey: {
type: String,
default: 'value'
},
/**
* 文本字段名
* @property {String|Array} textKey - 用作显示文本的字段名支持字符串或数组
* @default 'text'
*/
textKey: {
type: [String, Array],
default: 'text'
},
/**
* 文本分隔符
* @property {String} textSeparator - 当textKey为数组时各字段之间的分隔符
* @default '-'
*/
textSeparator: {
type: String,
default: '-'
},
/**
* 选择器标题
* @property {String} title - 选择器顶部显示的标题
* @default '请选择'
*/
title: {
type: String,
default: '请选择'
},
/**
* 默认占位文本
* @property {String} placeholder - 当字段为空时显示的占位文本
* @default '未命名'
*/
placeholder: {
type: String,
default: '未命名'
}
},
computed: {
/**
* 格式化后的选项数据适配fui-picker组件
*/
formattedOptions() {
// data
if (!this.data || !Array.isArray(this.data) || this.data.length === 0) {
return []
}
return this.data.map(item => {
return this.getDisplayText(item)
})
}
},
methods: {
/**
* 获取显示文本
* @param {Object} item - 数据项
* @returns {String} 显示文本
*/
getDisplayText(item) {
if (!item || typeof item !== 'object') {
return this.placeholder
}
if (Array.isArray(this.textKey)) {
// textKey
const textParts = this.textKey.map(key => {
return item[key] || this.placeholder
})
return textParts.join(this.textSeparator)
} else {
// textKey
return item[this.textKey] || this.placeholder
}
},
/**
* 获取选项值
* @param {Object} item - 数据项
* @returns {*} 选项值
*/
getDisplayValue(item) {
if (!item || typeof item !== 'object') {
return null
}
return item[this.valueKey]
},
/**
* 选择器确认事件处理
* @param {Object} e - 选择器返回的数据对象
* @emits update:show - 更新show属性
* @emits change - 选择完成事件
*/
onChange(e) {
//
this.$emit('update:show', false)
//
const index = e.index && e.index[0]
//
if (index === undefined || !this.data || !Array.isArray(this.data) || this.data.length === 0 || index >= this.data.length) {
return
}
//
const selectedItem = this.data[index]
//
if (!selectedItem) {
return
}
//
this.$emit('change', {
text: this.getDisplayText(selectedItem),
value: this.getDisplayValue(selectedItem),
index: index,
item: selectedItem
})
},
/**
* 选择器取消事件处理
* @emits update:show - 更新show属性
* @emits cancel - 取消选择事件
*/
onCancel() {
//
this.$emit('update:show', false)
//
this.$emit('cancel')
}
}
}
</script>
<style scoped>
.single-picker {
/* 可以根据需要添加自定义样式 */
}
</style>

3
uniapp/pages.json

@ -1,5 +1,6 @@
{ {
"pages": [{ "pages": [
{
"path": "pages/student/login/login", "path": "pages/student/login/login",
"style": { "style": {
"navigationBarTitleText": "", "navigationBarTitleText": "",

75
uniapp/pages/coach/schedule/add_schedule.vue

@ -247,11 +247,45 @@ export default {
venues: this.venueOptions.length venues: this.venueOptions.length
}); });
//
if (this.courseOptions.length === 0) {
uni.showToast({
title: '暂无可用课程',
icon: 'none'
});
}
if (this.coachOptions.length === 0) {
uni.showToast({
title: '暂无可用教练',
icon: 'none'
});
}
if (this.venueOptions.length === 0) {
uni.showToast({
title: '暂无可用场地',
icon: 'none'
});
}
} catch (error) { } catch (error) {
console.error('加载筛选选项失败:', error); console.error('加载筛选选项失败:', error);
//
let errorMsg = '加载数据失败';
if (error.response) {
errorMsg = `服务器错误: ${error.response.status}`;
} else if (error.request) {
errorMsg = '网络连接失败,请检查网络';
} else {
errorMsg = error.message || '未知错误';
}
uni.showToast({ uni.showToast({
title: '加载筛选选项失败', title: errorMsg,
icon: 'none' icon: 'none',
duration: 3000
}); });
} finally { } finally {
uni.hideLoading(); uni.hideLoading();
@ -327,9 +361,18 @@ export default {
console.error('加载时间段失败:', error); console.error('加载时间段失败:', error);
// API使 // API使
this.generateTimeSlotOptions(); this.generateTimeSlotOptions();
let errorMsg = '获取可用时间段失败,使用默认时间段';
if (error.response && error.response.status === 404) {
errorMsg = '该场地暂无可用时间段';
} else if (error.request) {
errorMsg = '网络连接失败,使用默认时间段';
}
uni.showToast({ uni.showToast({
title: '获取可用时间段失败,使用默认时间段', title: errorMsg,
icon: 'none' icon: 'none',
duration: 2000
}); });
} }
}, },
@ -500,9 +543,29 @@ export default {
} }
} catch (error) { } catch (error) {
console.error('创建课程安排失败:', error); console.error('创建课程安排失败:', error);
//
let errorMsg = '创建失败,请重试';
if (error.response) {
if (error.response.status === 401) {
errorMsg = '登录已过期,请重新登录';
} else if (error.response.status === 403) {
errorMsg = '没有权限执行此操作';
} else if (error.response.status >= 500) {
errorMsg = '服务器内部错误,请联系管理员';
} else {
errorMsg = `请求失败: ${error.response.status}`;
}
} else if (error.request) {
errorMsg = '网络连接失败,请检查网络后重试';
} else {
errorMsg = error.message || '创建失败,请重试';
}
uni.showToast({ uni.showToast({
title: '创建失败,请重试', title: errorMsg,
icon: 'none' icon: 'none',
duration: 3000
}); });
} finally { } finally {
this.submitting = false; this.submitting = false;

185
uniapp/pages/coach/student/student_list.vue

@ -37,62 +37,68 @@
</view> </view>
</view> </view>
</view> </view>
<fui-drawer :show="showSearch" position="top" @close="closeSearch"> <fui-drawer :show="showSearch" position="top" @close="closeSearch" :maskClick="true" background="#23232a">
<view class="fui-page__bd"> <view class="fui-page__bd">
<view class="fui-section__title">学员搜索</view> <view class="fui-section__title">学员搜索</view>
<view class="search-close-icon" @click="closeSearch">
<uni-icons type="closeempty" size="24" color="#ffffff"></uni-icons>
</view>
<fui-form> <fui-form>
<fui-form-item label="学生姓名" required> <fui-form-item label="学生姓名" required>
<fui-input :value="searchForm.name" placeholder="请输入学生姓名" @input="onNameInput"></fui-input> <fui-input :value="searchForm.name" placeholder="请输入学生姓名" @input="onNameInput" borderColor="#00d18c"></fui-input>
</fui-form-item> </fui-form-item>
<fui-form-item label="联系电话"> <fui-form-item label="联系电话">
<fui-input :value="searchForm.phone" placeholder="请输入联系电话" type="number" @input="onPhoneInput"></fui-input> <fui-input :value="searchForm.phone" placeholder="请输入联系电话" type="number" @input="onPhoneInput" borderColor="#00d18c"></fui-input>
</fui-form-item> </fui-form-item>
<fui-form-item label="课时数量"> <fui-form-item label="课时数量">
<fui-input :value="searchForm.lessonCount" placeholder="请输入课时数量" type="number" @input="onLessonCountInput"></fui-input> <fui-input :value="searchForm.lessonCount" placeholder="请输入课时数量" type="number" @input="onLessonCountInput" borderColor="#00d18c"></fui-input>
</fui-form-item> </fui-form-item>
<fui-form-item label="请假次数"> <fui-form-item label="请假次数">
<fui-input :value="searchForm.leaveCount" placeholder="请输入请假次数" type="number" @input="onLeaveCountInput"></fui-input> <fui-input :value="searchForm.leaveCount" placeholder="请输入请假次数" type="number" @input="onLeaveCountInput" borderColor="#00d18c"></fui-input>
</fui-form-item> </fui-form-item>
<fui-form-item label="课程名称"> <fui-form-item label="课程名称">
<view class="custom-picker-input" @click="showCoursePicker = true"> <view class="custom-picker-input" @click="showCoursePicker = true">
<text>{{ searchForm.courseIndex >= 0 ? courseList[searchForm.courseIndex].name : '请选择' }}</text> <text>{{ selectedCourseName || '请选择' }}</text>
<fui-icon name="arrowdown" :size="32" color="#CCCCCC"></fui-icon> <fui-icon name="arrowdown" :size="32" color="#00d18c"></fui-icon>
</view> </view>
<!-- 使用独立的 picker 组件 --> <!-- 使用通用单选选择器组件 -->
<picker <single-picker
v-if="showCoursePicker" :show.sync="showCoursePicker"
mode="selector" :data="courseList"
:range="courseList" valueKey="id"
range-key="name" textKey="course_name"
title="选择课程"
@change="onCourseChange" @change="onCourseChange"
@cancel="showCoursePicker = false" @cancel="showCoursePicker = false"
></picker> ></single-picker>
</fui-form-item> </fui-form-item>
<fui-form-item label="班级"> <fui-form-item label="班级">
<view class="custom-picker-input" @click="showClassPicker = true"> <view class="custom-picker-input" @click="showClassPicker = true">
<text>{{ searchForm.classIndex >= 0 ? classList[searchForm.classIndex].name : '请选择' }}</text> <text>{{ selectedClassName || '请选择' }}</text>
<fui-icon name="arrowdown" :size="32" color="#CCCCCC"></fui-icon> <fui-icon name="arrowdown" :size="32" color="#00d18c"></fui-icon>
</view> </view>
<!-- 使用独立的 picker 组件 --> <!-- 使用通用单选选择器组件 -->
<picker <single-picker
v-if="showClassPicker" :show.sync="showClassPicker"
mode="selector" :data="classList"
:range="classList" valueKey="id"
range-key="name" :textKey="['campus_name', 'class_name']"
textSeparator="-"
title="选择班级"
@change="onClassChange" @change="onClassChange"
@cancel="showClassPicker = false" @cancel="showClassPicker = false"
></picker> ></single-picker>
</fui-form-item> </fui-form-item>
</fui-form> </fui-form>
<view class="fui-btn__box"> <view class="fui-btn__box">
<fui-button type="primary" @click="doSearch">搜索</fui-button> <fui-button type="primary" @click="doSearch" background="#00d18c" color="#FFFFFF" radius="12">搜索</fui-button>
</view> </view>
</view> </view>
</fui-drawer> </fui-drawer>
@ -103,9 +109,11 @@
<script> <script>
import memberApi from '@/api/member.js'; import memberApi from '@/api/member.js';
import AQTabber from "@/components/AQ/AQTabber.vue" import AQTabber from "@/components/AQ/AQTabber.vue"
import SinglePicker from "@/components/custom-picker/single-picker.vue"
export default { export default {
components: { components: {
AQTabber, AQTabber,
SinglePicker
}, },
data() { data() {
return { return {
@ -118,39 +126,47 @@
phone: '', phone: '',
lessonCount: '', lessonCount: '',
leaveCount: '', leaveCount: '',
courseIndex: -1, courseId: null,
classIndex: -1, classId: null,
}, },
courseList: [ selectedCourseName: '',
{ name: '英语基础班' }, selectedClassName: '',
{ name: '数学提高班' }, courseList: [],
{ name: '编程兴趣班' }, classList: [],
],
classList: [
{ name: '一班' },
{ name: '二班' },
{ name: '三班' },
],
} }
}, },
onLoad() { onLoad() {
this.getStudentList(); this.getStudentList();
this.getClassesList();
}, },
methods: { methods: {
navigateBack() { navigateBack() {
uni.navigateBack(); uni.navigateBack();
}, },
async getStudentList() { async getStudentList() {
// API try {
const res = await memberApi.jlGetStudentList({}); // student_listtype
if(res.code == 1) { const params = { type: 'all' };
this.studentList = res.data || []; const res = await memberApi.jlGetStudentList(Object.assign(params, this.searchForm));
} else { console.log('获取学员列表响应:', res);
uni.showToast({ if(res.code == 1) {
title: res.msg || '获取学员列表失败', this.studentList = res.data || [];
icon: 'none' console.log('学员列表更新成功:', this.studentList);
}); } else {
} console.error('API返回错误:', res);
uni.showToast({
title: res.msg || '获取学员列表失败',
icon: 'none'
});
}
}catch ( error) {
console.error('获取学员列表错误', error);
uni.showToast({
title: '获取学员列表失败',
icon: 'none'
});
return;
}
}, },
goToDetail(student) { goToDetail(student) {
uni.navigateTo({ uni.navigateTo({
@ -181,10 +197,12 @@
// //
onCourseChange(e) { onCourseChange(e) {
this.searchForm.courseIndex = e.detail.value; this.searchForm.courseId = e.value;
this.selectedCourseName = e.text;
}, },
onClassChange(e) { onClassChange(e) {
this.searchForm.classIndex = e.detail.value; this.searchForm.classId = e.value;
this.selectedClassName = e.text;
}, },
// //
@ -192,23 +210,38 @@
this.showSearch = false; this.showSearch = false;
}, },
doSearch() { //
// searchForm onMaskClick() {
this.showSearch = false; this.showSearch = false;
},
//
uni.showLoading({
title: '搜索中...'
});
// //
setTimeout(() => { async getClassesList() {
uni.hideLoading(); try {
const res = await memberApi.jlGetClassesList();
if (res.code == 1) {
// API
this.classList = res.data.classes || [];
this.courseList = res.data.course || [];
} else {
uni.showToast({
title: res.msg || '获取班级列表失败',
icon: 'none'
});
}
} catch (error) {
console.error('获取班级列表错误', error);
uni.showToast({ uni.showToast({
title: '搜索功能待实现', title: '获取班级列表失败',
icon: 'none' icon: 'none'
}); });
}, 800); }
},
doSearch() {
// searchForm
this.showSearch = false;
this.getStudentList()
} }
} }
} }
@ -216,7 +249,6 @@
<style lang="scss"> <style lang="scss">
.container { .container {
min-height: 100vh;
background-color: #18181c; background-color: #18181c;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -389,20 +421,41 @@
} }
.fui-btn__box { .fui-btn__box {
margin-top: 40rpx; margin-top: 50rpx;
padding: 0 24rpx; padding: 0 30rpx;
} }
.fui-page__bd { .fui-page__bd {
padding: 30rpx; padding: 30rpx;
background-color: #18181c; padding-top: 70rpx;
background-color: #23232a;
position: relative;
border-top-left-radius: 24rpx;
border-top-right-radius: 24rpx;
} }
.fui-section__title { .fui-section__title {
font-size: 36rpx; font-size: 36rpx;
color: #00d18c; color: #00d18c;
font-weight: bold; font-weight: bold;
margin-bottom: 30rpx; margin-top: 30rpx;
text-align: center; text-align: center;
} }
.search-close-icon {
position: absolute;
top: 24rpx;
right: 24rpx;
z-index: 10;
padding: 10rpx;
}
.custom-picker-input {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24rpx;
border-radius: 8rpx;
border-bottom: 2rpx solid #00d18c;
}
</style> </style>
Loading…
Cancel
Save