统一排行榜对齐星雀UI,页面资源后台配置实时刷新
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
461
miniprogram/pages/kaohe_jinpai/kaohe_jinpai.js
Normal file
461
miniprogram/pages/kaohe_jinpai/kaohe_jinpai.js
Normal file
@@ -0,0 +1,461 @@
|
||||
// pages/kaohe_jinpai/kaohe_jinpai.js
|
||||
const app = getApp();
|
||||
import request from '../../utils/request.js';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
activeTab: 'all_tags',
|
||||
plateList: [], // 第一个接口返回的所有板块及标签(含 fee_list)
|
||||
myTags: [],
|
||||
recordList: [],
|
||||
recordPage: 1,
|
||||
recordHasMore: true,
|
||||
recordLoading: false,
|
||||
recordFilter: 'pending',
|
||||
showApplyModal: false,
|
||||
selectedTag: null,
|
||||
applyGameNick: '',
|
||||
applyRemark: '',
|
||||
applyFee: 0,
|
||||
applyJiluId: '',
|
||||
isReapply: false,
|
||||
payLoading: false,
|
||||
ossImageUrl: app.globalData.ossImageUrl || '',
|
||||
|
||||
// 新增:考核官相关
|
||||
kaoheguanList: [], // 所有可选的考核官
|
||||
showKaoheguanModal: false, // 考核官选择弹窗
|
||||
selectedKaoheguanId: '', // 已选择的考核官ID
|
||||
selectedKaoheguanInfo: null, // 已选择的考核官信息(用于展示)
|
||||
searchKeyword: '', // 搜索关键词
|
||||
filteredKaoheguanList: [], // 搜索过滤后的列表
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.fetchAllTags();
|
||||
this.fetchMyRecords(true);
|
||||
},
|
||||
|
||||
switchTab(e) {
|
||||
const tab = e.currentTarget.dataset.tab;
|
||||
if (tab === this.data.activeTab) return;
|
||||
this.setData({ activeTab: tab });
|
||||
if (tab === 'my_records') this.fetchMyRecords(true);
|
||||
},
|
||||
|
||||
// 获取所有板块及标签(含费用列表),缓存到 plateList,同时获取考核官列表
|
||||
async fetchAllTags() {
|
||||
try {
|
||||
const res = await request({ url: '/dengji/dskhhq', method: 'POST' });
|
||||
if (res.data.code === 0) {
|
||||
const { plate_list, my_tags, kaoheguan_list } = res.data.data;
|
||||
// 拼接考核官头像为完整URL
|
||||
const ossUrl = this.data.ossImageUrl;
|
||||
const processedKgList = (kaoheguan_list || []).map(kg => ({
|
||||
...kg,
|
||||
avatar: kg.avatar && !kg.avatar.startsWith('http') ? ossUrl + kg.avatar : kg.avatar,
|
||||
}));
|
||||
this.setData({
|
||||
plateList: plate_list || [],
|
||||
myTags: my_tags || [],
|
||||
kaoheguanList: processedKgList // 使用拼接后的列表
|
||||
});
|
||||
}
|
||||
} catch (e) {}
|
||||
},
|
||||
|
||||
// 获取我的考核记录,并根据 plateList 计算本次/预计下次费用
|
||||
async fetchMyRecords(isRefresh = false) {
|
||||
if (this.data.recordLoading) return;
|
||||
const page = isRefresh ? 1 : this.data.recordPage;
|
||||
this.setData({ recordLoading: true });
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/dengji/dskhjl',
|
||||
method: 'POST',
|
||||
data: { status: this.data.recordFilter, page, page_size: 5 }
|
||||
});
|
||||
if (res.data.code === 0) {
|
||||
const { list, has_more } = res.data.data;
|
||||
|
||||
// 从 plateList 构建标签ID -> 完整标签对象的映射(用于精确匹配费用)
|
||||
const tagMap = {};
|
||||
this.data.plateList.forEach(plate => {
|
||||
(plate.tags || []).forEach(tag => {
|
||||
tagMap[tag.id] = tag; // tag 包含 fee_list
|
||||
});
|
||||
});
|
||||
|
||||
// 处理每条记录:优先使用 tag_obj.id 匹配,其次 chenghao_id
|
||||
const processed = list.map(item => {
|
||||
// 尝试多种方式获取标签ID
|
||||
const tagId = (item.tag_obj && item.tag_obj.id) || item.chenghao_id;
|
||||
const tag = tagMap[tagId] || item.tag_obj || {};
|
||||
const feeList = tag.fee_list || [];
|
||||
let currentFee = 0;
|
||||
let nextFee = 0;
|
||||
if (feeList.length > 0) {
|
||||
const cishu = item.cishu;
|
||||
const cur = feeList.find(f => f.cishu === cishu);
|
||||
currentFee = cur ? cur.feiyong : feeList[feeList.length - 1].feiyong;
|
||||
const nextCishu = cishu + 1;
|
||||
const nxt = feeList.find(f => f.cishu === nextCishu);
|
||||
nextFee = nxt ? nxt.feiyong : feeList[feeList.length - 1].feiyong;
|
||||
}
|
||||
return {
|
||||
...item,
|
||||
current_fee: currentFee,
|
||||
next_fee: nextFee,
|
||||
tag_obj: tag // 使用匹配到的完整标签对象,保证后续“再次考核”能拿到费用
|
||||
};
|
||||
});
|
||||
|
||||
const newList = isRefresh ? processed : [...this.data.recordList, ...processed];
|
||||
this.setData({
|
||||
recordList: newList,
|
||||
recordPage: page + 1,
|
||||
recordHasMore: has_more,
|
||||
recordLoading: false
|
||||
});
|
||||
} else {
|
||||
this.setData({ recordLoading: false });
|
||||
}
|
||||
} catch (e) {
|
||||
this.setData({ recordLoading: false });
|
||||
}
|
||||
},
|
||||
|
||||
filterRecord(e) {
|
||||
const filter = e.currentTarget.dataset.filter;
|
||||
if (filter === this.data.recordFilter) return;
|
||||
this.setData({ recordFilter: filter, recordList: [], recordPage: 1, recordHasMore: true });
|
||||
this.fetchMyRecords(true);
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
if (this.data.activeTab === 'my_records' && this.data.recordHasMore) {
|
||||
this.fetchMyRecords(false);
|
||||
}
|
||||
},
|
||||
|
||||
// 打开申请考核弹窗,费用完全基于 plateList 中的标签数据
|
||||
openApplyModal(e) {
|
||||
const { tag, jiluid, reapply } = e.currentTarget.dataset;
|
||||
// 查找完整标签对象,保证 fee_list 存在
|
||||
let fullTag = tag;
|
||||
if (fullTag && fullTag.fee_list === undefined) {
|
||||
const found = this.findTagInPlateList(fullTag.id);
|
||||
if (found) fullTag = found;
|
||||
}
|
||||
if (!fullTag) {
|
||||
const found = this.findTagInPlateList(tag);
|
||||
if (found) fullTag = found;
|
||||
}
|
||||
|
||||
let fee = 0;
|
||||
if (fullTag) {
|
||||
let nextCishu = 0;
|
||||
// 再次申请时,基于原记录次数计算下一次考核次数
|
||||
if (reapply && jiluid) {
|
||||
const record = this.data.recordList.find(r => r.jilu_id === jiluid);
|
||||
if (record) {
|
||||
nextCishu = record.cishu + 1;
|
||||
} else {
|
||||
nextCishu = (fullTag.my_cishu || 0) + 1;
|
||||
}
|
||||
} else {
|
||||
nextCishu = (fullTag.my_cishu || 0) + 1;
|
||||
}
|
||||
const feeList = fullTag.fee_list || [];
|
||||
const exact = feeList.find(f => f.cishu === nextCishu);
|
||||
if (exact) {
|
||||
fee = exact.feiyong;
|
||||
} else if (feeList.length > 0) {
|
||||
fee = feeList[feeList.length - 1].feiyong;
|
||||
}
|
||||
}
|
||||
// 检查再次申请时原记录是否有考核官,若有则不允许指定
|
||||
let canSpecify = true;
|
||||
let originalShenheguanId = '';
|
||||
if (reapply && jiluid) {
|
||||
const record = this.data.recordList.find(r => r.jilu_id === jiluid);
|
||||
if (record && record.shenheguan_id) {
|
||||
canSpecify = false; // 已有考核官,不能指定新的
|
||||
originalShenheguanId = record.shenheguan_id;
|
||||
}
|
||||
}
|
||||
this.setData({
|
||||
showApplyModal: true,
|
||||
selectedTag: fullTag || null,
|
||||
applyGameNick: '',
|
||||
applyRemark: '',
|
||||
applyFee: fee,
|
||||
applyJiluId: jiluid || '',
|
||||
isReapply: reapply || false,
|
||||
selectedKaoheguanId: '', // 重置
|
||||
selectedKaoheguanInfo: null,
|
||||
canSpecify: canSpecify, // 新增
|
||||
originalShenheguanId: originalShenheguanId, // 新增
|
||||
});
|
||||
},
|
||||
|
||||
// 辅助方法:从 plateList 查找指定 id 的标签
|
||||
findTagInPlateList(tagId) {
|
||||
if (!tagId) return null;
|
||||
for (const plate of this.data.plateList) {
|
||||
for (const t of (plate.tags || [])) {
|
||||
if (t.id === tagId) return t;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
closeApplyModal() {
|
||||
this.setData({ showApplyModal: false });
|
||||
},
|
||||
|
||||
// 实时更新游戏昵称
|
||||
onNickInput(e) {
|
||||
this.setData({ applyGameNick: e.detail.value });
|
||||
},
|
||||
|
||||
// 实时更新备注
|
||||
onRemarkInput(e) {
|
||||
this.setData({ applyRemark: e.detail.value });
|
||||
},
|
||||
|
||||
// 新增:打开考核官选择弹窗
|
||||
openKaoheguanModal() {
|
||||
if (!this.data.canSpecify) {
|
||||
wx.showToast({ title: '已有考核官,无法重新指定', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
// 根据费用筛选可选考核官
|
||||
let all = [...this.data.kaoheguanList];
|
||||
if (this.data.applyFee > 0) {
|
||||
all = all.filter(kg => kg.is_renzheng);
|
||||
}
|
||||
this.setData({
|
||||
showKaoheguanModal: true,
|
||||
filteredKaoheguanList: all,
|
||||
searchKeyword: '',
|
||||
});
|
||||
},
|
||||
|
||||
// 关闭考核官选择弹窗
|
||||
closeKaoheguanModal() {
|
||||
this.setData({ showKaoheguanModal: false });
|
||||
},
|
||||
|
||||
// 搜索输入
|
||||
onSearchInput(e) {
|
||||
const value = e.detail.value.trim();
|
||||
this.setData({ searchKeyword: value });
|
||||
this.filterKaoheguanList(value);
|
||||
},
|
||||
|
||||
// 过滤考核官列表
|
||||
filterKaoheguanList(keyword) {
|
||||
let all = [...this.data.kaoheguanList];
|
||||
if (this.data.applyFee > 0) {
|
||||
all = all.filter(kg => kg.is_renzheng);
|
||||
}
|
||||
if (keyword) {
|
||||
all = all.filter(kg =>
|
||||
kg.yonghuid.includes(keyword) ||
|
||||
(kg.dashou_nick && kg.dashou_nick.includes(keyword))
|
||||
);
|
||||
}
|
||||
this.setData({ filteredKaoheguanList: all });
|
||||
},
|
||||
|
||||
// 选择一个考核官
|
||||
selectKaoheguan(e) {
|
||||
const kg = e.currentTarget.dataset.kg;
|
||||
if (kg.shenhe_zhuangtai !== 0) {
|
||||
wx.showToast({ title: '该考核官正忙,无法指定', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
this.setData({
|
||||
selectedKaoheguanId: kg.yonghuid,
|
||||
selectedKaoheguanInfo: kg,
|
||||
showKaoheguanModal: false,
|
||||
});
|
||||
},
|
||||
|
||||
// 取消已选择的考核官
|
||||
clearSelectedKaoheguan() {
|
||||
this.setData({
|
||||
selectedKaoheguanId: '',
|
||||
selectedKaoheguanInfo: null,
|
||||
});
|
||||
},
|
||||
|
||||
// 提交申请
|
||||
async submitApply() {
|
||||
const { applyGameNick, applyRemark, applyFee, selectedTag, isReapply, applyJiluId, selectedKaoheguanId } = this.data;
|
||||
if (!applyGameNick || !applyGameNick.trim()) {
|
||||
wx.showToast({ title: '请输入游戏昵称', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (!applyRemark || !applyRemark.trim()) {
|
||||
wx.showToast({ title: '请填写备注', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (applyFee > 0) {
|
||||
await this.startPayProcess();
|
||||
} else {
|
||||
await this.doFreeApply();
|
||||
}
|
||||
},
|
||||
|
||||
// 支付流程
|
||||
async startPayProcess() {
|
||||
this.setData({ payLoading: true });
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/yonghu/khzf',
|
||||
method: 'POST',
|
||||
data: {
|
||||
tag_id: this.data.selectedTag.id,
|
||||
game_nick: this.data.applyGameNick,
|
||||
remark: this.data.applyRemark,
|
||||
reapply: this.data.isReapply,
|
||||
jilu_id: this.data.applyJiluId,
|
||||
shenheguan_id: this.data.selectedKaoheguanId, // 新增
|
||||
}
|
||||
});
|
||||
if (res.data.code !== 200) throw new Error(res.data.message || '下单失败');
|
||||
const payParams = res.data.payParams;
|
||||
const dingdanid = res.data.dingdanid;
|
||||
wx.requestPayment({
|
||||
timeStamp: payParams.timeStamp,
|
||||
nonceStr: payParams.nonceStr,
|
||||
package: payParams.package,
|
||||
signType: payParams.signType || 'MD5',
|
||||
paySign: payParams.paySign,
|
||||
success: async () => {
|
||||
await this.pollPayStatus(dingdanid);
|
||||
},
|
||||
fail: () => {
|
||||
wx.showToast({ title: '支付取消或失败', icon: 'none' });
|
||||
request({ url: '/yonghu/khzfsb', method: 'POST', data: { dingdanid } }).catch(()=>{});
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
wx.showToast({ title: e.message || '支付异常', icon: 'none' });
|
||||
} finally {
|
||||
this.setData({ payLoading: false });
|
||||
}
|
||||
},
|
||||
|
||||
// 轮询支付结果
|
||||
async pollPayStatus(dingdanid) {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
try {
|
||||
const res = await request({ url: '/yonghu/khzffc', method: 'POST', data: { dingdanid } });
|
||||
if (res.data.code === 200) {
|
||||
wx.showToast({ title: '申请成功', icon: 'success' });
|
||||
this.closeApplyModal();
|
||||
this.fetchAllTags();
|
||||
this.setData({ recordList: [], recordPage: 1 });
|
||||
this.fetchMyRecords(true);
|
||||
return;
|
||||
}
|
||||
} catch (e) {}
|
||||
await new Promise(r => setTimeout(r, 2000));
|
||||
}
|
||||
wx.showToast({ title: '支付确认超时', icon: 'none' });
|
||||
},
|
||||
|
||||
// 免费申请
|
||||
async doFreeApply() {
|
||||
try {
|
||||
const res = await request({
|
||||
url: '/dengji/dssqkh',
|
||||
method: 'POST',
|
||||
data: {
|
||||
tag_id: this.data.selectedTag.id,
|
||||
game_nick: this.data.applyGameNick,
|
||||
remark: this.data.applyRemark,
|
||||
reapply: this.data.isReapply,
|
||||
jilu_id: this.data.applyJiluId,
|
||||
shenheguan_id: this.data.selectedKaoheguanId, // 新增
|
||||
}
|
||||
});
|
||||
if (res.data.code === 0) {
|
||||
wx.showToast({ title: '申请成功', icon: 'success' });
|
||||
this.closeApplyModal();
|
||||
this.fetchAllTags();
|
||||
this.setData({ recordList: [], recordPage: 1 });
|
||||
this.fetchMyRecords(true);
|
||||
} else {
|
||||
wx.showToast({ title: res.data.msg || '申请失败', icon: 'none' });
|
||||
}
|
||||
} catch (e) {
|
||||
wx.showToast({ title: '网络错误', icon: 'none' });
|
||||
}
|
||||
},
|
||||
|
||||
// 联系考核官(私聊)
|
||||
contactKaoheguan(e) {
|
||||
const item = e.currentTarget.dataset.item;
|
||||
if (!item) return;
|
||||
if (!item.shenheguan_id) {
|
||||
wx.showToast({ title: '暂无考核官信息', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const uid = wx.getStorageSync('uid');
|
||||
if (!uid) {
|
||||
wx.showToast({ title: '用户信息缺失', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
if (app.globalData.currentRole !== 'dashou') {
|
||||
app.globalData.currentRole = 'dashou';
|
||||
wx.setStorageSync('currentRole', 'dashou');
|
||||
}
|
||||
if (app.connectForCurrentRole) {
|
||||
app.connectForCurrentRole();
|
||||
} else if (app.ensureConnection) {
|
||||
app.ensureConnection();
|
||||
}
|
||||
const ossImageUrl = this.data.ossImageUrl || app.globalData.ossImageUrl || '';
|
||||
let fullAvatar = item.shenheguan_avatar || '';
|
||||
if (fullAvatar && !fullAvatar.startsWith('http')) {
|
||||
fullAvatar = ossImageUrl + fullAvatar;
|
||||
}
|
||||
if (!fullAvatar) {
|
||||
fullAvatar = ossImageUrl + (app.globalData.morentouxiang || 'avatar/default.jpg');
|
||||
}
|
||||
const param = {
|
||||
toUserId: 'Kh' + item.shenheguan_id,
|
||||
toName: '考核官' + item.shenheguan_id,
|
||||
toAvatar: fullAvatar
|
||||
};
|
||||
wx.navigateTo({
|
||||
url: '/pages/liaotian/liaotian?data=' + encodeURIComponent(JSON.stringify(param)),
|
||||
fail: (err) => {
|
||||
wx.showToast({ title: '打开聊天失败', icon: 'none' });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
showTagDetail(e) {
|
||||
const tag = e.currentTarget.dataset.tag;
|
||||
const feeStr = this.formatFeeList(tag.fee_list);
|
||||
wx.showModal({
|
||||
title: tag.name,
|
||||
content: `规则:${tag.rule || '暂无'}\n${tag.jinpai ? '【可同时开启金牌】' : ''}\n费用:${feeStr}`,
|
||||
showCancel: false,
|
||||
confirmText: '知道了'
|
||||
});
|
||||
},
|
||||
|
||||
formatFeeList(feeList) {
|
||||
if (!feeList || feeList.length === 0) return '暂无';
|
||||
let str = feeList.map(f => `第${f.cishu}次:¥${f.feiyong}`).join(';');
|
||||
const last = feeList[feeList.length - 1];
|
||||
str += `;第${last.cishu}次及以上:¥${last.feiyong}`;
|
||||
return str;
|
||||
},
|
||||
});
|
||||
9
miniprogram/pages/kaohe_jinpai/kaohe_jinpai.json
Normal file
9
miniprogram/pages/kaohe_jinpai/kaohe_jinpai.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"chenghao-tag": "/components/chenghao-tag/chenghao-tag",
|
||||
"global-notification": "/components/global-notification/global-notification"
|
||||
},
|
||||
"navigationBarTitleText": "考核金牌",
|
||||
"navigationBarBackgroundColor": "#0F0A1E",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
135
miniprogram/pages/kaohe_jinpai/kaohe_jinpai.wxml
Normal file
135
miniprogram/pages/kaohe_jinpai/kaohe_jinpai.wxml
Normal file
@@ -0,0 +1,135 @@
|
||||
<!-- pages/kaohe_jinpai/kaohe_jinpai.wxml -->
|
||||
<view class="page-root">
|
||||
<!-- 顶部Tab切换 -->
|
||||
<view class="tab-bar">
|
||||
<view class="tab-item {{activeTab === 'all_tags' ? 'active' : ''}}" data-tab="all_tags" bindtap="switchTab">考核标签</view>
|
||||
<view class="tab-item {{activeTab === 'my_records' ? 'active' : ''}}" data-tab="my_records" bindtap="switchTab">我的考核</view>
|
||||
</view>
|
||||
|
||||
<!-- 考核标签面板 -->
|
||||
<view class="content-area" wx:if="{{activeTab === 'all_tags'}}">
|
||||
<scroll-view scroll-y="true" class="scroll-view">
|
||||
<view wx:for="{{plateList}}" wx:key="bankuai_id" class="plate-group">
|
||||
<view class="plate-title">{{item.mingcheng}}</view>
|
||||
<view wx:for="{{item.tags}}" wx:key="id" class="tag-card" bindtap="showTagDetail" data-tag="{{item}}">
|
||||
<view class="tag-header">
|
||||
<chenghao-tag mingcheng="{{item.name}}" texiaoJson="{{item.texiao_json}}" />
|
||||
<text wx:if="{{item.jinpai}}" class="jinpai-badge">金牌</text>
|
||||
</view>
|
||||
<view class="fee-line">
|
||||
<text wx:for="{{item.fee_list}}" wx:key="cishu" class="fee-item">{{item.cishu}}次 ¥{{item.feiyong}}</text>
|
||||
<text wx:if="{{item.fee_list.length > 0}}" class="fee-item">≥{{item.fee_list.length}}次 ¥{{item.fee_list[item.fee_list.length-1].feiyong}}</text>
|
||||
</view>
|
||||
<view wx:if="{{!myTags.includes(item.name)}}" class="apply-btn" data-tag="{{item}}" bindtap="openApplyModal">申请考核</view>
|
||||
<view wx:else class="owned-tip">已拥有</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 我的考核面板 -->
|
||||
<view class="content-area" wx:if="{{activeTab === 'my_records'}}">
|
||||
<view class="filter-row">
|
||||
<view class="filter-tag {{recordFilter === 'pending' ? 'active' : ''}}" data-filter="pending" bindtap="filterRecord">进行中/未通过</view>
|
||||
<view class="filter-tag {{recordFilter === 'passed' ? 'active' : ''}}" data-filter="passed" bindtap="filterRecord">已通过</view>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="scroll-view" bindscrolltolower="onReachBottom">
|
||||
<view wx:for="{{recordList}}" wx:key="jilu_id" class="record-card">
|
||||
<view class="card-top">
|
||||
<text class="tag-name">{{item.chenghao_name}}</text>
|
||||
<text class="status-text" style="color: {{item.statusColor}}">{{item.statusText}}</text>
|
||||
</view>
|
||||
<view class="card-info">
|
||||
<text>板块:{{item.bankuai_name}}</text>
|
||||
<text>考核官:{{item.shenheguan_id || '待分配'}}</text>
|
||||
<!-- 联系考核官:纯文字蓝色下划线 -->
|
||||
<view wx:if="{{item.shenheguan_id}}" class="contact-text-link" data-item="{{item}}" bindtap="contactKaoheguan">联系考核官</view>
|
||||
|
||||
<text>游戏ID:{{item.dashou_youxi_id}}</text>
|
||||
<text>备注:{{item.dashou_beizhu}}</text>
|
||||
<text>第{{item.cishu}}次考核 · 共缴 ¥{{item.total_fee}}</text>
|
||||
|
||||
<!-- 进行中/未通过时显示本次及预计下次费用 -->
|
||||
<view wx:if="{{item.zhuangtai !== 1}}" class="fee-predict">
|
||||
<text>本次考核费用:¥{{item.current_fee}}</text>
|
||||
<text>预计下次费用:¥{{item.next_fee}}</text>
|
||||
</view>
|
||||
|
||||
<text wx:if="{{item.last_fail_reason}}">上次拒绝原因:{{item.last_fail_reason}}</text>
|
||||
</view>
|
||||
<!-- 未通过时显示“再次考核”按钮,传递 tag_obj 以便计算费用 -->
|
||||
<view wx:if="{{item.zhuangtai === 2}}" class="reapply-btn" data-tag="{{item.tag_obj}}" data-jiluid="{{item.jilu_id}}" data-reapply="{{true}}" bindtap="openApplyModal">再次考核</view>
|
||||
</view>
|
||||
<view wx:if="{{recordLoading}}" class="loading-more">加载中...</view>
|
||||
<view wx:if="{{!recordHasMore && recordList.length > 0}}" class="no-more">—— 没有更多了 ——</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 申请考核弹窗 -->
|
||||
<view wx:if="{{showApplyModal}}" class="modal-mask" bindtap="closeApplyModal">
|
||||
<view class="modal-dialog" catchtap="noop">
|
||||
<view class="modal-header">申请考核 - {{selectedTag.name}}</view>
|
||||
<view class="form-group">
|
||||
<text class="form-label">游戏昵称</text>
|
||||
<input class="form-input" value="{{applyGameNick}}" bindinput="onNickInput" placeholder="请输入游戏昵称" />
|
||||
</view>
|
||||
<view class="form-group">
|
||||
<text class="form-label">备注</text>
|
||||
<textarea class="form-textarea" value="{{applyRemark}}" bindinput="onRemarkInput" placeholder="区服、时间段等(请勿填写无关内容,违者封号)" maxlength="100" />
|
||||
</view>
|
||||
|
||||
<!-- 指定考核官区域 -->
|
||||
<view class="form-group">
|
||||
<text class="form-label">指定考核官(可选)</text>
|
||||
<view wx:if="{{!canSpecify}}" class="kg-disabled-tip">
|
||||
<text>已有考核官:{{originalShenheguanId}},不可重新指定</text>
|
||||
</view>
|
||||
<view wx:else>
|
||||
<view wx:if="{{!selectedKaoheguanInfo}}" class="select-kg-btn" bindtap="openKaoheguanModal">选择考核官</view>
|
||||
<view wx:else class="selected-kg-card">
|
||||
<image class="kg-avatar" src="{{selectedKaoheguanInfo.avatar}}" mode="aspectFill" />
|
||||
<view class="kg-info">
|
||||
<text class="kg-uid">UID {{selectedKaoheguanInfo.yonghuid}}</text>
|
||||
<text class="kg-nick" wx:if="{{selectedKaoheguanInfo.dashou_nick}}">{{selectedKaoheguanInfo.dashou_nick}}</text>
|
||||
<text class="kg-status {{selectedKaoheguanInfo.is_renzheng ? 'renzheng' : 'not-renzheng'}}">{{selectedKaoheguanInfo.is_renzheng ? '已认证' : '未认证'}}</text>
|
||||
</view>
|
||||
<view class="clear-kg-btn" bindtap="clearSelectedKaoheguan">取消</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view wx:if="{{applyFee > 0}}" class="fee-info">本次需缴纳:<text class="fee-amount">¥{{applyFee}}</text></view>
|
||||
<view class="modal-actions">
|
||||
<view class="btn-cancel" bindtap="closeApplyModal">取消</view>
|
||||
<view class="btn-confirm" bindtap="submitApply">确认申请{{applyFee > 0 ? '并支付' : ''}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 考核官选择弹窗 -->
|
||||
<view wx:if="{{showKaoheguanModal}}" class="modal-mask" bindtap="closeKaoheguanModal">
|
||||
<view class="modal-dialog" catchtap="noop">
|
||||
<view class="modal-header">选择考核官</view>
|
||||
<view class="search-box">
|
||||
<input class="search-input" value="{{searchKeyword}}" bindinput="onSearchInput" placeholder="搜索用户ID或昵称" />
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="kg-scroll">
|
||||
<view wx:for="{{filteredKaoheguanList}}" wx:key="yonghuid" class="kg-item" data-kg="{{item}}" bindtap="selectKaoheguan">
|
||||
<image class="kg-avatar" src="{{item.avatar}}" mode="aspectFill" />
|
||||
<view class="kg-info">
|
||||
<text class="kg-uid">UID {{item.yonghuid}}</text>
|
||||
<text wx:if="{{item.dashou_nick}}" class="kg-nick">{{item.dashou_nick}}</text>
|
||||
<text class="kg-status {{item.is_renzheng ? 'renzheng' : 'not-renzheng'}}">{{item.is_renzheng ? '已认证' : '未认证'}}</text>
|
||||
<text class="kg-state {{item.shenhe_zhuangtai === 0 ? 'free' : 'busy'}}">{{item.shenhe_zhuangtai === 0 ? '空闲' : '忙碌'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view wx:if="{{filteredKaoheguanList.length === 0}}" class="empty-tip">暂无符合条件的考核官</view>
|
||||
</scroll-view>
|
||||
<view class="modal-actions">
|
||||
<view class="btn-cancel" bindtap="closeKaoheguanModal">取消</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<global-notification id="global-notification" />
|
||||
</view>
|
||||
385
miniprogram/pages/kaohe_jinpai/kaohe_jinpai.wxss
Normal file
385
miniprogram/pages/kaohe_jinpai/kaohe_jinpai.wxss
Normal file
@@ -0,0 +1,385 @@
|
||||
/* pages/kaohe_jinpai/kaohe_jinpai.wxss - 晨雾微光风格 */
|
||||
.page-root {
|
||||
min-height: 100vh;
|
||||
background: linear-gradient(135deg, #F5F7FA 0%, #E4E8F0 100%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tab-bar {
|
||||
display: flex;
|
||||
padding: 30rpx 50rpx;
|
||||
gap: 60rpx;
|
||||
background: rgba(255, 255, 255, 0.65);
|
||||
backdrop-filter: blur(15px);
|
||||
border-bottom: 1rpx solid rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.tab-item {
|
||||
font-size: 32rpx;
|
||||
color: #6B7280;
|
||||
padding-bottom: 10rpx;
|
||||
border-bottom: 4rpx solid transparent;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
.tab-item.active {
|
||||
color: #4C5BF0;
|
||||
border-bottom-color: #4C5BF0;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.content-area {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
.scroll-view {
|
||||
height: 100%;
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.plate-group {
|
||||
margin-bottom: 50rpx;
|
||||
}
|
||||
.plate-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 700;
|
||||
color: #1F2937;
|
||||
margin-bottom: 20rpx;
|
||||
padding-left: 30rpx;
|
||||
border-left: 6rpx solid #4C5BF0;
|
||||
margin-left: 30rpx;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
|
||||
.tag-card {
|
||||
background: #FFFFFF;
|
||||
border-radius: 28rpx;
|
||||
padding: 30rpx;
|
||||
margin: 0 30rpx 20rpx 30rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.03);
|
||||
border: 1rpx solid rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.tag-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 18rpx;
|
||||
}
|
||||
.jinpai-badge {
|
||||
font-size: 22rpx;
|
||||
color: #F59E0B;
|
||||
background: rgba(245, 158, 11, 0.1);
|
||||
padding: 4rpx 14rpx;
|
||||
border-radius: 20rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
.fee-line {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.fee-item {
|
||||
font-size: 24rpx;
|
||||
color: #4B5563;
|
||||
background: #F3F4F6;
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
|
||||
.apply-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 80rpx;
|
||||
background: linear-gradient(135deg, #4C5BF0, #6D7AF5);
|
||||
color: #FFFFFF;
|
||||
border-radius: 34rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
letter-spacing: 2rpx;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.apply-btn:active {
|
||||
opacity: 0.85;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
.owned-tip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 80rpx;
|
||||
color: #10B981;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 记录卡片 */
|
||||
.record-card {
|
||||
background: #FFFFFF;
|
||||
border-radius: 28rpx;
|
||||
padding: 30rpx;
|
||||
margin: 0 30rpx 20rpx 30rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.03);
|
||||
border: 1rpx solid rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.card-top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
.tag-name { font-size: 32rpx; font-weight: 600; color: #1F2937; }
|
||||
.status-text { font-size: 26rpx; }
|
||||
.card-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10rpx;
|
||||
font-size: 26rpx;
|
||||
color: #4B5563;
|
||||
}
|
||||
|
||||
/* 联系考核官:蓝色下划线 */
|
||||
.contact-text-link {
|
||||
color: #4C5BF0;
|
||||
text-decoration: underline;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.fee-predict {
|
||||
background: #F3F4F6;
|
||||
padding: 12rpx 16rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-top: 10rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6rpx;
|
||||
font-size: 24rpx;
|
||||
color: #4B5563;
|
||||
}
|
||||
|
||||
.reapply-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 80rpx;
|
||||
margin-top: 20rpx;
|
||||
background: #F59E0B;
|
||||
color: #FFFFFF;
|
||||
border-radius: 34rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
.reapply-btn:active {
|
||||
opacity: 0.85;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.filter-row {
|
||||
display: flex;
|
||||
padding: 20rpx 30rpx;
|
||||
gap: 40rpx;
|
||||
}
|
||||
.filter-tag {
|
||||
font-size: 28rpx;
|
||||
color: #6B7280;
|
||||
padding-bottom: 8rpx;
|
||||
border-bottom: 3rpx solid transparent;
|
||||
}
|
||||
.filter-tag.active {
|
||||
color: #4C5BF0;
|
||||
border-bottom-color: #4C5BF0;
|
||||
}
|
||||
|
||||
/* 弹窗 */
|
||||
.modal-mask {
|
||||
position: fixed; top:0; left:0; width:100%; height:100%;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
.modal-dialog {
|
||||
width: 85%;
|
||||
background: #FFFFFF;
|
||||
border-radius: 36rpx;
|
||||
padding: 40rpx;
|
||||
box-shadow: 0 20rpx 40rpx rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
.modal-header { font-size: 34rpx; font-weight: 700; color: #1F2937; margin-bottom: 30rpx; }
|
||||
.form-group { margin-bottom: 25rpx; }
|
||||
.form-label { font-size: 28rpx; color: #4B5563; margin-bottom: 10rpx; display: block; }
|
||||
.form-input, .form-textarea {
|
||||
width: 100%;
|
||||
background: #F9FAFB;
|
||||
border-radius: 14rpx;
|
||||
padding: 16rpx;
|
||||
font-size: 28rpx;
|
||||
color: #1F2937;
|
||||
border: 1rpx solid #E5E7EB;
|
||||
}
|
||||
.form-textarea { height: 150rpx; }
|
||||
.fee-info { text-align: center; font-size: 30rpx; margin: 20rpx 0; color: #F59E0B; }
|
||||
.fee-amount { font-weight: 700; }
|
||||
.modal-actions { display: flex; gap: 20rpx; margin-top: 30rpx; }
|
||||
.btn-cancel, .btn-confirm {
|
||||
flex: 1;
|
||||
height: 80rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 40rpx;
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.btn-cancel { background: #F3F4F6; color: #4B5563; }
|
||||
.btn-cancel:active { background: #E5E7EB; }
|
||||
.btn-confirm { background: linear-gradient(135deg, #4C5BF0, #6D7AF5); color: #FFFFFF; }
|
||||
.btn-confirm:active { opacity: 0.85; transform: scale(0.98); }
|
||||
|
||||
.loading-more, .no-more { text-align: center; padding: 30rpx; color: #9CA3AF; font-size: 26rpx; }
|
||||
|
||||
.kg-avatar {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 8rpx;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* 原有样式保留,以下是新增样式 */
|
||||
|
||||
/* 指定考核官选择按钮 */
|
||||
.select-kg-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 80rpx;
|
||||
background: #F3F4F6;
|
||||
color: #4B5563;
|
||||
border-radius: 34rpx;
|
||||
font-size: 28rpx;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
.select-kg-btn:active {
|
||||
background: #E5E7EB;
|
||||
}
|
||||
|
||||
/* 已选择的考核官卡片 */
|
||||
.selected-kg-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #F9FAFB;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
margin-top: 10rpx;
|
||||
border: 1rpx solid #E5E7EB;
|
||||
}
|
||||
.kg-avatar {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
.kg-info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4rpx;
|
||||
}
|
||||
.kg-uid {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #1F2937;
|
||||
}
|
||||
.kg-nick {
|
||||
font-size: 24rpx;
|
||||
color: #6B7280;
|
||||
}
|
||||
.kg-status {
|
||||
font-size: 22rpx;
|
||||
padding: 2rpx 12rpx;
|
||||
border-radius: 20rpx;
|
||||
display: inline-block;
|
||||
width: fit-content;
|
||||
}
|
||||
.kg-status.renzheng {
|
||||
background: rgba(16, 185, 129, 0.1);
|
||||
color: #10B981;
|
||||
}
|
||||
.kg-status.not-renzheng {
|
||||
background: rgba(245, 158, 11, 0.1);
|
||||
color: #F59E0B;
|
||||
}
|
||||
.clear-kg-btn {
|
||||
color: #EF4444;
|
||||
font-size: 26rpx;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
.clear-kg-btn:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* 禁用指定提示 */
|
||||
.kg-disabled-tip {
|
||||
background: #FEF3C7;
|
||||
padding: 16rpx;
|
||||
border-radius: 12rpx;
|
||||
font-size: 24rpx;
|
||||
color: #92400E;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
/* 考核官选择弹窗内搜索 */
|
||||
.search-box {
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.search-input {
|
||||
width: 100%;
|
||||
background: #F9FAFB;
|
||||
border-radius: 14rpx;
|
||||
padding: 16rpx;
|
||||
font-size: 28rpx;
|
||||
border: 1rpx solid #E5E7EB;
|
||||
}
|
||||
|
||||
/* 考核官滚动列表 */
|
||||
.kg-scroll {
|
||||
max-height: 500rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 单个考核官项 */
|
||||
.kg-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
background: #FFFFFF;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 12rpx;
|
||||
border: 1rpx solid #F3F4F6;
|
||||
}
|
||||
.kg-item:active {
|
||||
background: #F9FAFB;
|
||||
}
|
||||
.kg-item .kg-state {
|
||||
font-size: 22rpx;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
.kg-state.free {
|
||||
color: #10B981;
|
||||
}
|
||||
.kg-state.busy {
|
||||
color: #EF4444;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
text-align: center;
|
||||
padding: 30rpx;
|
||||
color: #9CA3AF;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
Reference in New Issue
Block a user