Files
xingque/pages/fighter-msg/fighter-msg.js
2026-06-27 05:41:55 +08:00

684 lines
20 KiB
JavaScript
Raw 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.
// pages/penalty/penalty.js
import request from '../../utils/request.js'
const app = getApp()
const MEIYE_TIAOSHU = 5
Page({
data: {
zongshu: 0,
daichuli: 0,
yichuli: 0,
shenfen: 0,
chufaList: [],
dangqianye: 1,
haiyougengduo: true,
jiazhaozhong: false,
jiazhaigengduo: false,
scrollHeight: 0,
showXiangqing: false,
xuanzhongChufa: {},
showShensuModal: false,
shensuLiyou: '',
shensuTupian: [],
shensuTupianUrls: [],
shangchuanJindu: 0,
shangchuanZongshu: 0,
jinduWidth: '0%',
isShangchuanzhong: false,
ossImageUrl: '',
fangdouTimer: null
},
onLoad(options) {
this.registerNotificationComponent()
this.initOSSUrl()
this.jisuanGaodu()
this.chushihuaShuju()
},
onShow() {
this.registerNotificationComponent()
},
onUnload() {
if (this.data.fangdouTimer) clearTimeout(this.data.fangdouTimer)
},
onReachBottom() {
this.shanglaShuaxin()
},
registerNotificationComponent() {
const notificationComp = this.selectComponent('#global-notification')
if (notificationComp && notificationComp.showNotification) {
app.globalData.globalNotification = {
show: (data) => notificationComp.showNotification(data),
hide: () => notificationComp.hideNotification()
}
}
},
initOSSUrl() {
const ossImageUrl = app.globalData.ossImageUrl || ''
this.setData({ ossImageUrl })
},
jisuanGaodu() {
const systemInfo = wx.getSystemInfoSync()
const windowHeight = systemInfo.windowHeight
const height = windowHeight - 200 - 100 - 40
this.setData({
scrollHeight: height > 0 ? height : 400
})
},
chushihuaShuju() {
this.setData({
dangqianye: 1,
chufaList: [],
haiyougengduo: true
})
this.jiazhuoquTongji()
this.jiazhuoquChufaList()
},
async jiazhuoquTongji() {
try {
const res = await request({
url: '/yonghu/dshqcfjl',
method: 'POST',
data: { qingqiu_tongji: true }
})
if (res.statusCode === 200 && res.data.code === 0) {
const data = res.data.data
this.setData({
zongshu: data.zongshu || 0,
daichuli: data.daichuli || 0,
yichuli: data.yichuli || 0
})
}
} catch (error) {
console.error('获取统计信息失败:', error)
}
},
async jiazhuoquChufaList(isLoadMore = false) {
if (this.data.jiazhaozhong || this.data.jiazhaigengduo) return
if (isLoadMore) {
if (!this.data.haiyougengduo) return
this.setData({ jiazhaigengduo: true })
} else {
this.setData({ jiazhaozhong: true })
}
try {
const params = {
page: this.data.dangqianye,
page_size: MEIYE_TIAOSHU
}
if (this.data.shenfen === 0) {
params.zhuangtai = 0
} else {
params.zhuangtai = 1
}
const res = await request({
url: '/yonghu/dshqcfjl',
method: 'POST',
data: params
})
//console.log('🔴【后端返回的数据】:', res.data)
if (res.statusCode === 200 && res.data.code === 0) {
const data = res.data.data
if (data.list && Array.isArray(data.list)) {
// 🔴【关键修复】在数据加载时就处理好显示字段
const processedList = data.list.map(item => {
// 处理显示时间
let displayTime = '--'
if (item.create_time) {
if (typeof item.create_time === 'number') {
displayTime = String(item.create_time)
} else if (typeof item.create_time === 'string') {
displayTime = item.create_time
} else {
displayTime = String(item.create_time)
}
}
// 处理显示状态
let displayStatus = '未知状态'
let statusClass = 'zhuangtai-weizhi'
const statusNum = Number(item.sqzhuangtai)
if (!isNaN(statusNum)) {
if (statusNum === 0) {
displayStatus = '待处罚'
statusClass = 'zhuangtai-daichuli'
} else if (statusNum === 1) {
displayStatus = '已处罚'
statusClass = 'zhuangtai-yichufa'
} else if (statusNum === 2) {
displayStatus = '已驳回'
statusClass = 'zhuangtai-yibohui'
} else if (statusNum === 3) {
displayStatus = '申诉中'
statusClass = 'zhuangtai-shensuzhong'
}
}
// 处理图片URL在数据加载时就拼接完整URL
const fullZhengjuTupian = (item.zhengju_tupian || []).map(url => this.getFullImageUrl(url))
const fullShensuTupian = (item.shensu_tupian || []).map(url => this.getFullImageUrl(url))
return {
...item,
display_time: displayTime, // 🔴 处理好的显示时间
display_status: displayStatus, // 🔴 处理好的显示状态
status_class: statusClass, // 🔴 处理好的状态样式类
zhengju_tupian: item.zhengju_tupian || [],
shensu_tupian: item.shensu_tupian || [],
full_zhengju_tupian: fullZhengjuTupian, // 🔴 完整图片URL
full_shensu_tupian: fullShensuTupian // 🔴 完整图片URL
}
})
//console.log('🔴【处理后的数据】:', processedList)
let newList
if (isLoadMore) {
newList = [...this.data.chufaList, ...processedList]
} else {
newList = processedList
}
const hasMore = data.has_more === true
this.setData({
chufaList: newList,
haiyougengduo: hasMore,
dangqianye: this.data.dangqianye + 1
})
} else {
this.setData({ haiyougengduo: false })
}
} else {
throw new Error(res.data?.msg || '加载处罚记录失败')
}
} catch (error) {
console.error('加载处罚记录失败:', error)
wx.showToast({
title: error.message || '加载失败',
icon: 'none'
})
this.setData({ haiyougengduo: false })
} finally {
if (isLoadMore) {
this.setData({ jiazhaigengduo: false })
} else {
this.setData({ jiazhaozhong: false })
}
}
},
qiehuanShenfen(e) {
const type = parseInt(e.currentTarget.dataset.type)
if (this.data.shenfen === type) return
this.setData({
shenfen: type,
dangqianye: 1,
chufaList: [],
haiyougengduo: true
})
this.jiazhuoquChufaList()
},
shanglaShuaxin() {
if (this.data.fangdouTimer) clearTimeout(this.data.fangdouTimer)
const timer = setTimeout(() => {
if (this.data.jiazhaozhong || this.data.jiazhaigengduo) return
if (!this.data.haiyougengduo) return
this.jiazhuoquChufaList(true)
}, 300)
this.setData({ fangdouTimer: timer })
},
chakanXiangqing(e) {
const item = e.currentTarget.dataset.item
this.setData({
xuanzhongChufa: item,
showXiangqing: true
})
},
guanbiXiangqing() {
this.setData({
showXiangqing: false,
xuanzhongChufa: {}
})
},
openShensuModal() {
if (this.data.xuanzhongChufa.ssliyou ||
(this.data.xuanzhongChufa.shensu_tupian && this.data.xuanzhongChufa.shensu_tupian.length > 0)) {
wx.showToast({
title: '您已经提交过申诉,请等待处理结果',
icon: 'none'
})
return
}
this.setData({
showShensuModal: true,
shensuLiyou: '',
shensuTupian: [],
shensuTupianUrls: [],
shangchuanJindu: 0,
shangchuanZongshu: 0,
jinduWidth: '0%'
})
},
closeShensuModal() {
this.setData({
showShensuModal: false,
shensuLiyou: '',
shensuTupian: [],
shensuTupianUrls: []
})
},
onShensuLiyouInput(e) {
const value = e.detail.value.slice(0, 500)
this.setData({ shensuLiyou: value })
},
chooseShensuTupian() {
if (this.data.isShangchuanzhong) return
const shengyu = 9 - this.data.shensuTupian.length
if (shengyu <= 0) {
wx.showToast({
title: '最多只能上传9张图片',
icon: 'none'
})
return
}
wx.chooseMedia({
count: shengyu,
mediaType: ['image'],
sourceType: ['album', 'camera'],
success: (res) => {
const newTupian = [...this.data.shensuTupian, ...res.tempFiles.map(file => file.tempFilePath)]
this.setData({ shensuTupian: newTupian.slice(0, 9) })
}
})
},
deleteShensuTupian(e) {
const index = e.currentTarget.dataset.index
const newTupian = [...this.data.shensuTupian]
newTupian.splice(index, 1)
this.setData({ shensuTupian: newTupian })
},
yulanShensuTupian(e) {
const index = e.currentTarget.dataset.index
const urls = this.data.shensuTupian
if (!urls[index]) return
wx.previewImage({
current: urls[index],
urls: urls
})
},
lianxiKefu() {
const kefuLink = app.globalData.kefuConfig?.link || '';
const corpId = app.globalData.kefuConfig?.enterpriseId || '';
if (!kefuLink || !corpId) {
wx.showToast({
title: '客服配置未加载',
icon: 'none'
});
return;
}
wx.openCustomerServiceChat({
extInfo: { url: kefuLink },
corpId: corpId,
success: (res) => {
console.log('跳转客服成功', res);
},
fail: (err) => {
console.error('跳转客服失败', err);
wx.showToast({
title: '暂时无法连接客服',
icon: 'none'
});
}
});
},
async getCOSZhengshu() {
try {
const res = await request({
url: '/dingdan/dsscpz',
method: 'POST',
data: {
dingdan_id: this.data.xuanzhongChufa.dingdan_id,
yongtu: 'chufa'
}
})
if (res.statusCode === 200 && res.data.code === 0 && res.data.data) {
return res.data.data
} else {
throw new Error(res?.data?.msg || '获取上传凭证失败')
}
} catch (error) {
console.error('获取COS凭证失败:', error)
throw error
}
},
initCOSClient(tokenData) {
const COS = require('../../utils/cos-wx-sdk-v5.min.js')
const credentials = tokenData.credentials || tokenData
const bucket = tokenData.bucket || 'julebu-1361527063'
const region = tokenData.region || 'ap-shanghai'
const cos = new COS({
SimpleUploadMethod: 'putObject',
getAuthorization: async (options, callback) => {
const authParams = {
TmpSecretId: credentials.tmpSecretId,
TmpSecretKey: credentials.tmpSecretKey,
SecurityToken: credentials.sessionToken || '',
StartTime: tokenData.startTime || Math.floor(Date.now() / 1000),
ExpiredTime: tokenData.expiredTime || (Math.floor(Date.now() / 1000) + 7200)
}
callback(authParams)
}
})
return { cos, bucket, region }
},
async shangchuanDanZhangTupian(filePath, cosKey, index, cosInstance, bucket, region) {
return new Promise((resolve) => {
const timeoutId = setTimeout(() => {
resolve({ status: 'optimistic_success', key: cosKey })
}, 2000)
cosInstance.uploadFile({
Bucket: bucket,
Region: region,
Key: cosKey,
FilePath: filePath,
onProgress: (progressInfo) => {
const percent = Math.round(progressInfo.percent * 100)
if (percent === 100) {
clearTimeout(timeoutId)
resolve({ status: 'optimistic_success', key: cosKey })
}
}
})
})
},
async piliangShangchuanShensuTupian() {
const total = this.data.shensuTupian.length
if (total === 0) return []
this.setData({
shangchuanZongshu: total,
shangchuanJindu: 0,
jinduWidth: '0%',
isShangchuanzhong: true
})
let yonghuid = ''
// 方案1直接从全局缓存获取
const uid = wx.getStorageSync('uid')
if (uid) {
yonghuid = String(uid).padStart(7, '0')
//console.log('🔴【从uid获取yonghuid】', yonghuid)
}
// 方案2如果还没有从用户信息获取
if (!yonghuid && app.globalData.userInfo && app.globalData.userInfo.yonghuid) {
yonghuid = String(app.globalData.userInfo.yonghuid).padStart(7, '0')
//console.log('🔴【从userInfo获取yonghuid】', yonghuid)
}
// 方案3如果还没有直接提示并返回
if (!yonghuid) {
wx.showToast({
title: '请先登录',
icon: 'none'
})
this.setData({ isShangchuanzhong: false })
return []
}
const preGeneratedUrls = []
for (let i = 0; i < total; i++) {
const timestamp = Date.now() + i
const random = Math.floor(Math.random() * 10000)
const fileExt = this.getFileExtension(this.data.shensuTupian[i])
const fileName = `${yonghuid}_${timestamp}_${random}${fileExt}`
const cosKey = `a_long/chfajltp/dssstp/${fileName}`
preGeneratedUrls.push(cosKey)
}
let cosClient, bucket, region
try {
const tokenData = await this.getCOSZhengshu()
const { cos, bucket: cosBucket, region: cosRegion } = this.initCOSClient(tokenData)
cosClient = cos
bucket = cosBucket
region = cosRegion
} catch (error) {
wx.showToast({ title: '上传初始化失败', icon: 'none' })
this.setData({ isShangchuanzhong: false })
return []
}
const uploadTasks = []
for (let i = 0; i < total; i++) {
const task = this.shangchuanDanZhangTupian(
this.data.shensuTupian[i],
preGeneratedUrls[i],
i,
cosClient,
bucket,
region
).then((result) => {
const currentDone = i + 1
const jinduPercent = ((currentDone / total) * 100).toFixed(0)
this.setData({
shangchuanJindu: currentDone,
jinduWidth: `${jinduPercent}%`
})
return result
})
uploadTasks.push(task)
}
await Promise.all(uploadTasks)
this.setData({ isShangchuanzhong: false })
return preGeneratedUrls
},
getFileExtension(filePath) {
const lastDotIndex = filePath.lastIndexOf('.')
if (lastDotIndex === -1) return '.jpg'
const ext = filePath.substring(lastDotIndex).toLowerCase()
const allowedExts = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']
return allowedExts.includes(ext) ? ext : '.jpg'
},
async submitShensu() {
if (!this.data.shensuLiyou.trim()) {
wx.showToast({ title: '请输入申诉理由', icon: 'none' }); return
}
if (this.data.shensuTupian.length === 0) {
wx.showModal({
title: '提示',
content: '未上传任何图片,确定要提交申诉吗?',
success: async (res) => {
if (res.confirm) await this.tijiaoShensuData([])
}
})
return
}
wx.showToast({ title: '开始上传图片...', icon: 'none' })
try {
const tupianUrls = await this.piliangShangchuanShensuTupian()
if (!tupianUrls || tupianUrls.length === 0) throw new Error('图片上传失败')
await this.tijiaoShensuData(tupianUrls)
} catch (error) {
console.error('提交申诉失败:', error)
wx.showToast({ title: error.message || '提交失败', icon: 'none' })
}
},
async tijiaoShensuData(tupianUrls) {
wx.showToast({ title: '提交申诉中...', icon: 'none' })
try {
const res = await request({
url: '/yonghu/dscfss',
method: 'POST',
data: {
chufa_id: this.data.xuanzhongChufa.id,
shensu_liyou: this.data.shensuLiyou,
shensu_tupian_urls: tupianUrls
}
})
if (res.statusCode === 200 && res.data.code === 0) {
this.updateChufaRecord({
sqzhuangtai: 3,
ssliyou: this.data.shensuLiyou,
shensu_tupian: tupianUrls
})
this.setData({
showShensuModal: false,
showXiangqing: false,
shensuLiyou: '',
shensuTupian: [],
xuanzhongChufa: {}
})
wx.showToast({ title: '申诉提交成功,请等待处理', icon: 'success' })
setTimeout(() => { this.chushihuaShuju() }, 500)
} else {
throw new Error(res.data?.msg || '提交申诉失败')
}
} catch (error) {
console.error('提交申诉数据失败:', error)
wx.showToast({ title: error.message || '提交失败', icon: 'none' })
}
},
updateChufaRecord(newData) {
const newList = this.data.chufaList.map(item => {
if (item.id === this.data.xuanzhongChufa.id) {
const updatedItem = { ...item, ...newData }
// 🔴 更新显示字段
if (newData.sqzhuangtai === 3) {
updatedItem.display_status = '申诉中'
updatedItem.status_class = 'zhuangtai-shensuzhong'
}
if (newData.shensu_tupian) {
updatedItem.full_shensu_tupian = newData.shensu_tupian.map(url => this.getFullImageUrl(url))
}
return updatedItem
}
return item
})
this.setData({ chufaList: newList })
},
// 🔴【图片URL拼接 - 确保返回完整URL】
getFullImageUrl(relativeUrl) {
//console.log('🔴【图片拼接】输入:', relativeUrl)
if (!relativeUrl) return ''
if (relativeUrl.startsWith('http')) {
//console.log('🔴【已经是完整URL】返回:', relativeUrl)
return relativeUrl
}
const ossUrl = this.data.ossImageUrl
if (!ossUrl) {
//console.log('🔴【OSS地址为空】返回原始URL:', relativeUrl)
return relativeUrl
}
let fullUrl
if (ossUrl.endsWith('/') && relativeUrl.startsWith('/')) {
fullUrl = ossUrl + relativeUrl.substring(1)
} else if (!ossUrl.endsWith('/') && !relativeUrl.startsWith('/')) {
fullUrl = ossUrl + '/' + relativeUrl
} else {
fullUrl = ossUrl + relativeUrl
}
// console.log('🔴【拼接后URL】:', fullUrl)
return fullUrl
},
yulanTupian(e) {
const currentUrl = e.currentTarget.dataset.url
const urls = e.currentTarget.dataset.urls || []
if (!currentUrl) return
const fullCurrentUrl = currentUrl.startsWith('http') ? currentUrl : this.getFullImageUrl(currentUrl)
const fullUrls = urls.map(url => url.startsWith('http') ? url : this.getFullImageUrl(url))
wx.previewImage({
current: fullCurrentUrl,
urls: fullUrls.length > 0 ? fullUrls : [fullCurrentUrl]
})
},
fuzhiWenben(e) {
const text = e.currentTarget.dataset.text
if (!text) return
wx.setClipboardData({
data: text,
success: () => {
wx.showToast({ title: '复制成功', icon: 'success' })
},
fail: () => {
wx.showToast({ title: '复制失败', icon: 'none' })
}
})
},
// 🔴【保留原函数但已不再使用(用于向后兼容)】
formatShijian(shijian) {
if (!shijian) return '--'
return String(shijian)
},
getZhuangtaiText(zhuangtai) {
const statusNum = Number(zhuangtai)
if (statusNum === 0) return '待处罚'
if (statusNum === 1) return '已处罚'
if (statusNum === 2) return '已驳回'
if (statusNum === 3) return '申诉中'
return '未知状态'
},
getZhuangtaiClass(zhuangtai) {
const statusNum = Number(zhuangtai)
if (statusNum === 0) return 'zhuangtai-daichuli'
if (statusNum === 1) return 'zhuangtai-yichufa'
if (statusNum === 2) return 'zhuangtai-yibohui'
if (statusNum === 3) return 'zhuangtai-shensuzhong'
return 'zhuangtai-weizhi'
}
})