Files
tuanwei-uniapp/utils/gxmu/review-list-service.js
2026-07-20 11:56:02 +08:00

440 lines
14 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { API_BASE_URL } from '../request'
import { apiRequest } from '../../pages/assistant/chat-service'
function request(url, method = 'GET', data) {
return apiRequest({
url: `${API_BASE_URL}${url}`,
method,
data
})
}
export const REVIEW_AUTHORITY = 'gxmu:reviewList:list'
export const MODULE_OPTIONS = [
{ label: '全部模块', value: '' },
{ label: '稿件', value: 'cms_manuscript' },
{ label: '十佳青年岗位能手', value: 'gxmu_sjqn' },
{ label: '十佳团支部书记', value: 'gxmu_sjtbzbsj' },
{ label: '五四红旗团委', value: 'gxmu_wshqtw' },
{ label: '五四红旗团支部', value: 'gxmu_wshqtzb' },
{ label: '优秀共青团干部', value: 'gxmu_yxgqtdgb' },
{ label: '优秀共青团员', value: 'gxmu_yxgqty' },
{ label: '挑战杯', value: 'gxmu_tzbcy_form' },
{ label: '青马工程', value: 'gxmu_qmgc_form' },
{ label: '未来学术之星', value: 'gxmu_wxxzx_project' },
{ label: '团员管理', value: 'gxmu_tygl_form' },
{ label: '团员管理', value: 'gxmu_tygl' }
]
const COMMON_LABELS = {
year: '年份',
id: 'ID',
title: '标题',
content: '内容',
cover: '封面',
createTime: '创建时间',
updateTime: '更新时间',
status: '状态',
sortNumber: '排序',
provinceCity: '省市',
schoolName: '学校名称',
projectName: '项目名称',
projectType: '项目类型',
projectGroup: '项目分组',
publicProjectType: '公开展示项目类型',
publicProjectGroup: '公开展示项目分组',
leader: '负责人',
phone: '联系电话',
teamMembers: '团队成员',
advisors: '指导老师',
projectBrief: '项目简介',
socialValue: '社会价值',
practiceProcess: '实践过程',
innovationMeaning: '创新意义',
developmentProspect: '发展前景',
teamCooperation: '团队协作情况',
projectMaterials: '项目佐证材料',
otherProofs: '其他证明材料',
projectSummary: '项目总结',
teamIntro: '团队介绍',
teamSlogan: '团队口号',
practiceLog: '实践日志',
name: '姓名',
gender: '性别',
nation: '民族',
photo: '电子版照片',
birthMonth: '出生年月',
politics: '政治面貌',
nativePlace: '籍贯',
wechat: '微信号',
email: '邮箱',
qq: 'QQ',
idCardNo: '身份证号',
hobby: '兴趣爱好',
willingToWorkInGuangxi: '是否愿意留桂工作',
schoolInfo: '学校信息',
leaguePosition: '团内职务',
resume: '个人简历',
awards: '获得奖励',
academicPerformance: '学习成绩',
secondaryLeagueOpinion: '二级团组织意见',
secondaryLeagueOpinionDate: '二级团组织意见日期',
secondaryPartyOpinion: '二级党组织意见',
secondaryPartyOpinionDate: '二级党组织意见日期',
schoolLeagueOpinion: '学校团组织意见',
schoolLeagueOpinionDate: '学校团组织意见日期',
applyType: '申报类别',
education: '学历',
position: '职务',
unit: '工作单位',
experience: '主要经历',
mainStory: '主要事迹',
leagueOpinion: '团组织意见',
partyOpinion: '党组织意见',
schoolOpinion: '学校意见',
collegeClass: '学院班级',
branch: '团支部名称',
eduEval: '教育评议情况',
serialNo: '序号',
archiveInCurrentOrg: '团籍是否在本组织',
joinMonth: '入团时间',
memberRecords: '团员记录',
growthArchives: '成长档案',
orgName: '组织名称',
memberTotal: '团员总数',
memberDeveloped2024: '上一年度发展团员数',
smartSystemLogin: '智慧团建系统录入情况',
committeeCount: '团委委员数',
fulltimeCadreCount: '专职团干部数',
parttimeCadreCount: '兼职团干部数',
lastElectionTime: '最近一次换届时间',
feeReceivable2024: '上一年度应收团费',
feeReceived2024: '上一年度实收团费',
feePayable2024: '上一年度应缴团费',
feePaid2024: '上一年度实缴团费',
branchCount: '团支部数量',
standardizedWork2024: '上一年度标准化建设开展情况',
recommendActivist2024: '上一年度推优入党人数',
activistConfirmed: '入党积极分子确定情况',
recommendDevTarget2024: '上一年度推荐发展对象人数',
devTargetConfirmed: '发展对象确定情况',
honorsFiveYears: '近五年获奖情况',
workSummaryThreeYears: '近三年工作总结',
branchName: '团支部名称',
secondOrg: '所属二级党组织',
secretary: '团支部书记',
contact: '联系方式',
establishTime: '成立时间',
branchCommitteeMeetingCount: '支委会次数',
branchMemberMeetingCount: '支部大会次数',
eduEvalDone: '教育评议是否完成',
annualRegDone: '年度团籍注册是否完成',
classCount: '班级数量',
smartSystem100: '智慧团建系统覆盖率',
topicName: '课题名称',
collegeGradeClass: '学院年级班级',
advisor: '指导老师',
topicType: '课题类别',
guidanceTeachers: '指导教师组',
applicants: '申请人信息',
budgets: '经费预算',
rationale: '立项依据',
teacherOpinion: '指导教师意见',
teacherSign: '指导教师签名',
reviewOpinion: '评审意见',
reviewScore: '评审成绩',
reviewLeaderSign: '评审负责人签名',
collegeOpinion: '学院意见',
promiseSigner: '承诺签字人',
promiseSignature: '承诺书签名',
reviewCollege: '评审学院',
reviewReporter: '汇报人',
reviewDate: '评审日期',
reviewMembers: '评审成员',
fundingBudgetFile: '经费预算表',
fundingAllocationFile: '经费划拨明细表',
midtermRemark: '中期检查说明',
midtermMaterials: '中期检查材料',
finalRemark: '结题说明',
finalMaterials: '结题材料',
archiveAwards: '获奖情况',
archiveProofs: '佐证材料',
archiveRecords: '成果归档',
grade: '年级',
className: '班级',
major: '专业',
role: '角色',
item: '项目',
amount: '金额',
reason: '原因',
dept: '部门',
sign: '签名',
department: '部门',
remark: '备注',
type: '类型',
recordTime: '时间',
archiveTime: '时间',
identity: '身份',
organization: '所在组织',
memberNo: '团员编号',
currentDutyTime: '现任职务时间',
cadreYears: '从事团学工作年限',
assessment2024: '上一年度考核情况',
volunteerRegTime: '志愿汇注册时间',
cadreExperience: '团学工作经历',
joinTime: '入团时间',
collegeMajorClass: '学院专业班级',
eduEval2024: '上一年度教育评议情况',
smartSystem: '智慧团建系统录入情况',
totalVolunteerHours: '累计志愿服务时长',
volunteerHours2024: '上一年度志愿服务时长',
duty: '职务',
college: '学院',
gradeMajor: '年级专业',
birthDate: '出生日期',
branchOrganizationName: '所属团支部'
}
export const MODULE_CONFIGS = {
cms_manuscript: { title: '稿件', path: '/cms/manuscript', labels: COMMON_LABELS },
gxmu_sjqn: { title: '十佳青年岗位能手', path: '/gxmu/sjqn-form', labels: COMMON_LABELS },
gxmu_sjtbzbsj: { title: '十佳团支部书记', path: '/gxmu/sjtbzbsj-form', labels: COMMON_LABELS },
gxmu_wshqtw: { title: '五四红旗团委', path: '/gxmu/wshqtw-form', labels: COMMON_LABELS },
gxmu_wshqtzb: { title: '五四红旗团支部', path: '/gxmu/wshqtzb-form', labels: COMMON_LABELS },
gxmu_yxgqtdgb: { title: '优秀共青团干部', path: '/gxmu/yxgqtdgb-form', labels: COMMON_LABELS },
gxmu_yxgqty: { title: '优秀共青团员', path: '/gxmu/yxgqty-form', labels: COMMON_LABELS },
gxmu_tzbcy_form: { title: '挑战杯', path: '/gxmu/tzbcy-form', labels: COMMON_LABELS },
gxmu_qmgc_form: { title: '青马工程', path: '/gxmu/qmgc-form', labels: COMMON_LABELS },
gxmu_wxxzx_project: { title: '未来学术之星', path: '/gxmu/wxxzx-form', labels: { ...COMMON_LABELS, title: '职称' } },
gxmu_tygl_form: { title: '团员管理', path: '/gxmu/tygl-form', labels: COMMON_LABELS },
gxmu_tygl: { title: '团员管理', path: '/gxmu/tygl-form', labels: COMMON_LABELS }
}
export const HIDDEN_FIELDS = new Set([
'reviewList',
'deleted',
'tenantId',
'userId',
'branchOrganizationId'
])
export const IMAGE_FIELDS = new Set(['photo', 'cover', 'promiseSignature'])
export const FILE_FIELDS = new Set([
'fundingBudgetFile',
'fundingAllocationFile',
'midtermMaterials',
'finalMaterials',
'archiveProofs'
])
export function pageGroupReviewList(params) {
return request('/gxmu/review-list/groupPage', 'GET', {
...(params || {}),
backendAccess: true
})
}
export function listReviewList(params) {
return request('/gxmu/review-list', 'GET', params)
}
export function updateReviewList(data) {
return request('/gxmu/review-list', 'PUT', data)
}
export function getModuleDetail(module, id) {
const config = MODULE_CONFIGS[module]
if (!config || !id) {
return Promise.resolve(null)
}
return request(`${config.path}/${id}`, 'GET')
}
export function formatDateTime(value) {
if (!value) {
return '-'
}
const text = String(value).trim()
const normalizedText = text.replace('T', ' ')
if (/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/.test(normalizedText)) {
return normalizedText.slice(0, 19)
}
const timestamp = typeof value === 'number' || /^\d+$/.test(text) ? Number(value) : null
const date = timestamp
? new Date(String(timestamp).length === 10 ? timestamp * 1000 : timestamp)
: new Date(text.includes('T') ? text : text.replace(/-/g, '/'))
if (Number.isNaN(date.getTime())) {
return value
}
const pad = (item) => String(item).padStart(2, '0')
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
}
export function getModuleName(module) {
const option = MODULE_OPTIONS.find((item) => item.value === module)
return (option && option.label) || (MODULE_CONFIGS[module] && MODULE_CONFIGS[module].title) || module || '-'
}
export function getReviewStatusMeta(status) {
if (Number(status) === 1) {
return { text: '通过', tone: 'success' }
}
if (Number(status) === 2) {
return { text: '拒绝', tone: 'danger' }
}
return { text: '待审核', tone: 'warning' }
}
export function getAuthorityValue(item) {
if (!item) {
return ''
}
if (typeof item === 'string') {
return item
}
return item.authority || item.permission || item.code || ''
}
export function hasReviewListAuthority(profile) {
const authorities = Array.isArray(profile && profile.authorities) ? profile.authorities : []
return authorities.some((item) => getAuthorityValue(item) === REVIEW_AUTHORITY)
}
export function isPlainObject(value) {
return Object.prototype.toString.call(value) === '[object Object]'
}
export function hasVisibleValue(value) {
if (value === null || value === undefined) {
return false
}
if (typeof value === 'string') {
return value.trim().length > 0
}
if (Array.isArray(value)) {
return value.length > 0
}
if (isPlainObject(value)) {
return Object.values(value).some((item) => hasVisibleValue(item))
}
return true
}
export function getFieldLabel(module, key) {
const config = MODULE_CONFIGS[module]
const label = config && config.labels && config.labels[key]
if (label) {
return label
}
return String(key || '')
.replace(/([A-Z])/g, ' $1')
.replace(/^./, (text) => text.toUpperCase())
.trim()
}
export function normalizeDetailValue(key, value) {
if (!FILE_FIELDS.has(key) || typeof value !== 'string') {
return value
}
const text = value.trim()
if (!text) {
return value
}
if (key === 'fundingBudgetFile' || key === 'fundingAllocationFile') {
return text
}
try {
const parsed = JSON.parse(text)
return Array.isArray(parsed) ? parsed : text
} catch (error) {
return text
}
}
export function formatSimpleValue(value) {
if (value === null || value === undefined || value === '') {
return '-'
}
return String(value)
}
export function formatDisplayValue(module, key, value) {
if (key === 'createTime' || key === 'updateTime') {
return formatDateTime(value)
}
if (key === 'status' && module === 'cms_manuscript') {
if (Number(value) === 0) {
return '待审核'
}
if (Number(value) === 1) {
return '显示'
}
}
return formatSimpleValue(value)
}
export function getFileName(url) {
if (!url) {
return '未命名文件'
}
const cleanUrl = String(url).split('?')[0]
return decodeURIComponent(cleanUrl.split('/').pop() || cleanUrl)
}
export function normalizeFileEntries(value) {
if (Array.isArray(value)) {
return value
.map((item) => {
if (typeof item === 'string' && item.trim()) {
return { name: getFileName(item), url: item }
}
if (isPlainObject(item) && typeof item.url === 'string' && item.url.trim()) {
return {
name: (typeof item.name === 'string' && item.name.trim()) || getFileName(item.url),
url: item.url
}
}
return null
})
.filter(Boolean)
}
if (typeof value === 'string' && value.trim()) {
return [{ name: getFileName(value), url: value }]
}
return []
}
export function formatObjectLines(module, value) {
return Object.keys(value || {})
.filter((key) => !HIDDEN_FIELDS.has(key) && hasVisibleValue(value[key]))
.map((key) => `${getFieldLabel(module, key)}${formatDisplayValue(module, key, value[key])}`)
}
export function formatArrayEntry(module, entry) {
if (isPlainObject(entry)) {
const lines = formatObjectLines(module, entry)
return lines.length ? lines : ['-']
}
return [formatSimpleValue(entry)]
}
export function buildDescriptionItems(module, detail) {
const source = detail || {}
const labels = (MODULE_CONFIGS[module] && MODULE_CONFIGS[module].labels) || {}
const orderedKeys = Object.keys(labels).filter((key) => (
!HIDDEN_FIELDS.has(key) && hasVisibleValue(source[key])
))
const extraKeys = Object.keys(source).filter((key) => (
!HIDDEN_FIELDS.has(key) &&
hasVisibleValue(source[key]) &&
!orderedKeys.includes(key)
))
return [...orderedKeys, ...extraKeys].map((key) => ({
key,
label: getFieldLabel(module, key),
value: normalizeDetailValue(key, source[key])
}))
}