新增后台管理系统(答辩用
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* 工具函数
|
||||
*/
|
||||
|
||||
/**
|
||||
* 格式化日期时间
|
||||
*/
|
||||
export function formatDateTime(dateStr, showTime = true) {
|
||||
if (!dateStr) return '--'
|
||||
const d = new Date(dateStr)
|
||||
const pad = (n) => String(n).padStart(2, '0')
|
||||
const date = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`
|
||||
if (!showTime) return date
|
||||
return `${date} ${pad(d.getHours())}:${pad(d.getMinutes())}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化日期
|
||||
*/
|
||||
export function formatDate(dateStr) {
|
||||
return formatDateTime(dateStr, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化时间
|
||||
*/
|
||||
export function formatTime(dateStr) {
|
||||
if (!dateStr) return '--'
|
||||
const d = new Date(dateStr)
|
||||
const pad = (n) => String(n).padStart(2, '0')
|
||||
return `${pad(d.getHours())}:${pad(d.getMinutes())}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化时间(短格式:MM/DD HH:mm)
|
||||
*/
|
||||
export function formatTimeShort(dateStr) {
|
||||
if (!dateStr) return '--'
|
||||
const d = new Date(dateStr)
|
||||
const pad = (n) => String(n).padStart(2, '0')
|
||||
return `${d.getMonth() + 1}/${d.getDate()} ${pad(d.getHours())}:${pad(d.getMinutes())}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 课程状态(由后端 GET /api/groupCourse/statuses 统一提供,避免前后端各自硬编码)
|
||||
*/
|
||||
let _statusMap = null
|
||||
let _statusClassMap = null
|
||||
|
||||
const DEFAULT_STATUS_MAP = { '0': '正常', '1': '已取消', '2': '已结束', '3': '进行中', '4': '超时' }
|
||||
const DEFAULT_STATUS_CLASS = { '0': 'green', '1': 'orange', '2': 'gray', '3': 'blue', '4': 'red' }
|
||||
|
||||
/**
|
||||
* 从后端加载课程状态映射,返回 Promise<boolean>
|
||||
*/
|
||||
export async function loadCourseStatuses() {
|
||||
try {
|
||||
const res = await uni.request({
|
||||
url: `${getBaseUrl()}/api/groupCourse/statuses`,
|
||||
method: 'GET'
|
||||
})
|
||||
if (res.statusCode === 200 && res.data?.success && Array.isArray(res.data.data)) {
|
||||
const map = {}
|
||||
const cls = {}
|
||||
res.data.data.forEach(item => {
|
||||
map[String(item.dbValue)] = item.label
|
||||
cls[String(item.dbValue)] = item.cssClass
|
||||
})
|
||||
_statusMap = map
|
||||
_statusClassMap = cls
|
||||
return true
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('加载课程状态映射失败,使用默认映射:', e)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function getBaseUrl() {
|
||||
// #ifdef H5
|
||||
return '/gym-api'
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
return 'http://localhost:8084'
|
||||
// #endif
|
||||
}
|
||||
|
||||
function getStatusMap() {
|
||||
return _statusMap || DEFAULT_STATUS_MAP
|
||||
}
|
||||
|
||||
function getStatusClassMap() {
|
||||
return _statusClassMap || DEFAULT_STATUS_CLASS
|
||||
}
|
||||
|
||||
export function getCourseStatusLabel(status, deletedAt) {
|
||||
if (deletedAt) return '已删除'
|
||||
return getStatusMap()[String(status)] || '未知'
|
||||
}
|
||||
|
||||
export function getCourseStatusClass(status, deletedAt) {
|
||||
if (deletedAt) return 'tag-gray'
|
||||
return 'tag-' + (getStatusClassMap()[String(status)] || 'gray')
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断课程是否有实际时间记录
|
||||
*/
|
||||
export function hasActualTime(course) {
|
||||
return !!(course && (course.actualStartTime || course.actualEndTime))
|
||||
}
|
||||
|
||||
/**
|
||||
* Toast 提示
|
||||
*/
|
||||
export function showToast(title, icon = 'none') {
|
||||
uni.showToast({ title, icon, duration: 2000 })
|
||||
}
|
||||
|
||||
/**
|
||||
* 确认弹窗
|
||||
*/
|
||||
export function showConfirm(content, title = '提示') {
|
||||
return new Promise((resolve) => {
|
||||
uni.showModal({
|
||||
title,
|
||||
content,
|
||||
success: (res) => {
|
||||
resolve(res.confirm)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* HTTP请求封装 - 基于 uni.request
|
||||
* 风格参考 gym-manage-cuit 的 request.ts
|
||||
*/
|
||||
|
||||
// 后端API基础地址
|
||||
// H5端: 使用 /gym-api 前缀走vite代理(避免与源码 api/ 目录冲突),代理重写为 /api
|
||||
// App端: 直接请求后端域名
|
||||
// #ifdef H5
|
||||
const BASE_URL = '/gym-api'
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
const BASE_URL = 'http://localhost:8084'
|
||||
// #endif
|
||||
|
||||
// token存储key
|
||||
const TOKEN_KEY = 'coach_access_token'
|
||||
const REFRESH_TOKEN_KEY = 'coach_refresh_token'
|
||||
const USER_INFO_KEY = 'coach_user_info'
|
||||
|
||||
function getToken() {
|
||||
return uni.getStorageSync(TOKEN_KEY) || ''
|
||||
}
|
||||
|
||||
function getRefreshToken() {
|
||||
return uni.getStorageSync(REFRESH_TOKEN_KEY) || ''
|
||||
}
|
||||
|
||||
function setToken(token) {
|
||||
uni.setStorageSync(TOKEN_KEY, token)
|
||||
}
|
||||
|
||||
function setRefreshToken(token) {
|
||||
uni.setStorageSync(REFRESH_TOKEN_KEY, token)
|
||||
}
|
||||
|
||||
function clearAuth() {
|
||||
uni.removeStorageSync(TOKEN_KEY)
|
||||
uni.removeStorageSync(REFRESH_TOKEN_KEY)
|
||||
uni.removeStorageSync(USER_INFO_KEY)
|
||||
}
|
||||
|
||||
/**
|
||||
* 发起请求
|
||||
*/
|
||||
function request(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const token = getToken()
|
||||
const header = {
|
||||
'Content-Type': 'application/json',
|
||||
...(options.header || {})
|
||||
}
|
||||
|
||||
if (token) {
|
||||
header['Authorization'] = `Bearer ${token}`
|
||||
}
|
||||
|
||||
uni.request({
|
||||
url: BASE_URL + options.url,
|
||||
method: options.method || 'GET',
|
||||
data: options.data || {},
|
||||
header: header,
|
||||
timeout: options.timeout || 15000,
|
||||
success: (res) => {
|
||||
const statusCode = res.statusCode
|
||||
if (statusCode >= 200 && statusCode < 300) {
|
||||
resolve(res.data)
|
||||
} else if (statusCode === 401) {
|
||||
// token过期,清除登录状态
|
||||
const isLoginRequest = options.url?.includes('/auth/login')
|
||||
if (!isLoginRequest) {
|
||||
clearAuth()
|
||||
uni.reLaunch({ url: '/pages/login/login' })
|
||||
}
|
||||
reject(res)
|
||||
} else {
|
||||
reject(res)
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.showToast({
|
||||
title: '网络请求失败',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 导出便捷方法
|
||||
request.get = function(url, params = {}) {
|
||||
let query = ''
|
||||
if (Object.keys(params).length > 0) {
|
||||
const parts = []
|
||||
for (const key in params) {
|
||||
if (params[key] !== undefined && params[key] !== null && params[key] !== '') {
|
||||
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
||||
}
|
||||
}
|
||||
if (parts.length > 0) {
|
||||
query = '?' + parts.join('&')
|
||||
}
|
||||
}
|
||||
return request({ url: url + query, method: 'GET' })
|
||||
}
|
||||
|
||||
request.post = function(url, data = {}) {
|
||||
return request({ url, method: 'POST', data })
|
||||
}
|
||||
|
||||
request.put = function(url, data = {}) {
|
||||
return request({ url, method: 'PUT', data })
|
||||
}
|
||||
|
||||
request.delete = function(url, data = {}) {
|
||||
return request({ url, method: 'DELETE', data })
|
||||
}
|
||||
|
||||
export { request, getToken, setToken, setRefreshToken, clearAuth, TOKEN_KEY, USER_INFO_KEY }
|
||||
export default request
|
||||
Reference in New Issue
Block a user