179 lines
4.8 KiB
JavaScript
179 lines
4.8 KiB
JavaScript
import { request } from '@/api/request.js'
|
||
import { getBaseURL } from '@/api/config.js'
|
||
import { getToken } from '@/utils/auth.js'
|
||
|
||
/**
|
||
* OA 工作日程(日历待办)接口封装,对应后端 /api/oa/schedule/*。
|
||
* 数据表 yz_backend_oa_schedule,与「日程提醒」(/api/schedule/*,
|
||
* yz_backend_schedule)是两个独立功能,不要混用。
|
||
*/
|
||
|
||
/** 优先级选项(与 Web 后台一致:0 普通 / 1 重要 / 2 紧急) */
|
||
export const OA_SCHEDULE_PRIORITY_OPTIONS = [
|
||
{ value: 0, label: '普通' },
|
||
{ value: 1, label: '重要' },
|
||
{ value: 2, label: '紧急' }
|
||
]
|
||
|
||
/** 归一化单条日程:补齐端上排序/分组用的时间戳与派生字段 */
|
||
export function normalizeOaSchedule(item) {
|
||
const date = String(item.schedule_date || '').slice(0, 10)
|
||
const startTime = item.start_time || ''
|
||
// 拼一个 Date 时间戳便于日历分组与时间排序(全天事件按 00:00)
|
||
let timestamp = 0
|
||
if (date) {
|
||
const [y, m, d] = date.split('-').map(Number)
|
||
const [hh = 0, mm = 0] = startTime ? startTime.split(':').map(Number) : [0, 0]
|
||
timestamp = new Date(y, m - 1, d, hh, mm).getTime()
|
||
}
|
||
return {
|
||
...item,
|
||
schedule_date: date,
|
||
completed: item.status === 1,
|
||
allDay: item.all_day === 1,
|
||
timestamp
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 获取工作日程列表(支持日期区间 / 分类筛选)
|
||
* 返回 { list, total, counts },counts 为各分类数量角标
|
||
*/
|
||
export async function fetchOaSchedules(params = {}) {
|
||
const data = await request({
|
||
url: '/api/oa/schedule/list',
|
||
data: {
|
||
page: params.page || 1,
|
||
pageSize: params.pageSize || 500,
|
||
keyword: params.keyword || '',
|
||
status: params.status || '',
|
||
priority: params.priority || '',
|
||
start_date: params.startDate || '',
|
||
end_date: params.endDate || '',
|
||
category: params.category || 'all'
|
||
}
|
||
})
|
||
const list = (data.list || []).map(normalizeOaSchedule)
|
||
return { list, total: data.total || 0, counts: data.counts || {} }
|
||
}
|
||
|
||
/**
|
||
* 获取单条日程详情
|
||
*/
|
||
export async function getOaSchedule(id) {
|
||
const data = await request({ url: `/api/oa/schedule/detail/${id}` })
|
||
if (!data || !data.item) return null
|
||
return { ...normalizeOaSchedule(data.item), images: data.images || [] }
|
||
}
|
||
|
||
/**
|
||
* 新建日程
|
||
*/
|
||
export async function createOaSchedule(payload) {
|
||
return request({
|
||
url: '/api/oa/schedule/create',
|
||
method: 'POST',
|
||
data: buildOaSchedulePayload(payload)
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 更新日程
|
||
*/
|
||
export async function updateOaSchedule(id, payload) {
|
||
return request({
|
||
url: `/api/oa/schedule/update/${id}`,
|
||
method: 'POST',
|
||
data: buildOaSchedulePayload(payload)
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 删除日程(软删除)
|
||
*/
|
||
export async function deleteOaSchedule(id) {
|
||
await request({ url: `/api/oa/schedule/delete/${id}`, method: 'DELETE' })
|
||
return true
|
||
}
|
||
|
||
/**
|
||
* 切换完成状态(待办 <-> 已完成)
|
||
*/
|
||
export async function toggleOaScheduleComplete(id) {
|
||
const res = await request({ url: `/api/oa/schedule/finish/${id}`, method: 'POST' })
|
||
return { status: res?.status ?? 0, completed: res?.status === 1 }
|
||
}
|
||
|
||
/**
|
||
* 上传日程资料图片(multipart,单张 ≤10MB)
|
||
* 文件落入租户文件管理,返回 { id, url, name } 引用信息
|
||
*/
|
||
export function uploadOaScheduleImage(filePath) {
|
||
return new Promise((resolve, reject) => {
|
||
uni.uploadFile({
|
||
url: `${getBaseURL().replace(/\/$/, '')}/api/oa/schedule/upload`,
|
||
filePath,
|
||
name: 'file',
|
||
header: { Authorization: `Bearer ${getToken()}` },
|
||
success(res) {
|
||
let body = {}
|
||
try {
|
||
body = JSON.parse(res.data || '{}')
|
||
} catch (e) {
|
||
// 非 JSON 响应按失败处理
|
||
}
|
||
if (res.statusCode >= 200 && res.statusCode < 300 && body.code === 200 && body.data) {
|
||
resolve(body.data)
|
||
} else {
|
||
const msg = body.msg || `上传失败(${res.statusCode})`
|
||
uni.showToast({ title: msg, icon: 'none' })
|
||
reject(new Error(msg))
|
||
}
|
||
},
|
||
fail(err) {
|
||
uni.showToast({ title: '网络异常,上传失败', icon: 'none' })
|
||
reject(err)
|
||
}
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 保存日程资料图片引用列表(整体覆盖)
|
||
*/
|
||
export async function setOaScheduleImages(id, images) {
|
||
const res = await request({
|
||
url: `/api/oa/schedule/images/${id}`,
|
||
method: 'POST',
|
||
data: {
|
||
images: (images || []).map(img => ({
|
||
id: Number(img.id) || 0,
|
||
url: img.url,
|
||
name: img.name || ''
|
||
}))
|
||
}
|
||
})
|
||
return res?.images || []
|
||
}
|
||
|
||
/** 组装后端要求的请求体(提醒绑定暂不在小程序端开放) */
|
||
function buildOaSchedulePayload(p) {
|
||
return {
|
||
title: p.title,
|
||
content: p.content || '',
|
||
schedule_date: p.scheduleDate,
|
||
start_time: p.allDay ? '' : p.startTime || '',
|
||
end_time: p.allDay ? '' : p.endTime || '',
|
||
all_day: p.allDay ? 1 : 0,
|
||
priority: p.priority || 0,
|
||
color: p.color || '#409EFF',
|
||
reminder_enabled: false
|
||
}
|
||
}
|
||
|
||
export function getOaPriorityLabel(priority) {
|
||
return (
|
||
OA_SCHEDULE_PRIORITY_OPTIONS.find(item => item.value === Number(priority))?.label || '普通'
|
||
)
|
||
}
|