8451952d by lttnew

证书+调度

1 parent 0ac7b897
......@@ -493,6 +493,15 @@ export function getMobilizelist(params) {
})
}
// 调动记录
export function logList(params) {
return request({
url: '/person/transferLog/list',
method: 'get',
params
})
}
// 调动会员成员
export function getTransferList(data) {
return request({
......@@ -2115,6 +2124,20 @@ export function postCert(ids) {
}
/**
* 手工录入证书邮寄物流信息
* @param data
* @returns {*}
*/
export function editPostInfo(data) {
return request({
url: '/exam/payment/editPostInfo',
method: 'post',
params: data
})
}
/**
* 查看物流信息
* @param id
* @returns {*}
......
......@@ -7,6 +7,10 @@
</view>
<view class="info-content">
<view class="info-row">
<text class="label">快递公司</text>
<text class="value">{{ currentItem.postName || '京东物流' }}</text>
</view>
<view class="info-row">
<text class="label">运单号</text>
<text class="value tracking-number" @click="copyTracking">
{{ currentItem.postCode || '-' }}
......@@ -15,7 +19,7 @@
</view>
</view>
<view class="timeline-section">
<view class="timeline-section" v-if="currentItem.postType === '0'">
<view class="section-header">
<uni-icons type="location-filled" size="20" color="#AD181F"></uni-icons>
<text class="section-title">运输轨迹</text>
......@@ -50,10 +54,21 @@
</view>
<view class="nodata" v-else>
<image mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image>
<text>暂无物流信息</text>
<image class="empty-img" mode="aspectFit" :src="emptyImageUrl" @error="handleEmptyImageError"></image>
<text>暂无数据</text>
</view>
</view>
</view>
<view class="timeline-section" v-else>
<view class="section-header">
<uni-icons type="location-filled" size="20" color="#AD181F"></uni-icons>
<text class="section-title">物流跟踪</text>
</view>
<view class="nodata">
<image class="empty-img" mode="aspectFit" :src="emptyImageUrl" @error="handleEmptyImageError"></image>
<text>暂无数据</text>
</view>
</view>
</view>
</template>
......@@ -68,14 +83,19 @@ const loading = ref(false)
const payId = ref('')
const currentItem = ref({})
const trackingNodes = ref([])
const emptyImageUrl = ref(config.baseUrl_api + '/fs/static/nodata.png')
onLoad((options) => {
if (!options.payId) return
payId.value = options.payId
if (options.postCode) currentItem.value.postCode = options.postCode
if (options.postName) currentItem.value.postName = decodeURIComponent(options.postName)
currentItem.value.postType = options.postType || '0'
if (options.postStatus) currentItem.value.postStatus = parseInt(options.postStatus)
if (options.submitTime) currentItem.value.submitTime = options.submitTime
if (currentItem.value.postType === '0') {
getLogisticsInfo()
}
})
function getLogisticsInfo() {
......@@ -101,6 +121,10 @@ function copyTracking() {
}
})
}
function handleEmptyImageError() {
emptyImageUrl.value = '/static/nodata.png'
}
</script>
<style lang="scss" scoped>
......@@ -303,9 +327,12 @@ function copyTracking() {
justify-content: center;
padding: 80rpx 0;
image {
.empty-img {
width: 200rpx;
height: 200rpx;
display: block !important;
opacity: 0.8 !important;
filter: none !important;
}
text {
......
<template>
<view class="mail-page" :class="{ 'no-scroll': showMailPopup }">
<view class="mail-tabs">
<view
v-for="tab in typeTabs"
:key="tab.type"
class="mail-tab"
:class="{ active: queryParams.type === tab.type }"
@click="switchType(tab.type)"
>
{{ tab.name }}
</view>
</view>
<scroll-view
scroll-y
class="mail-list-scroll"
......@@ -57,7 +68,9 @@
<view class="btn-group">
<button
v-if="showMailButton(item)"
v-if="deptType === '1'"
:class="{ disabled: String(item.postStatus) === '1' }"
:disabled="String(item.postStatus) === '1'"
class="btn btn-mail"
@click.stop="openMailPopup(item)"
>
......@@ -94,30 +107,30 @@
<text class="form-label">邮寄方式</text>
<radio-group class="radio-group" @change="handleMailTypeChange">
<label class="radio-item" @click.stop>
<radio value="1" color="#C4121B" :checked="mailForm.type === '1'" />
<radio value="0" color="#C4121B" :checked="mailForm.postType === '0'" />
<text>自动邮寄</text>
</label>
<label class="radio-item" @click.stop>
<radio value="2" color="#C4121B" :checked="mailForm.type === '2'" />
<radio value="1" color="#C4121B" :checked="mailForm.postType === '1'" />
<text>人工邮寄</text>
</label>
</radio-group>
</view>
<view v-if="mailForm.type === '2'" class="form-item">
<view v-if="mailForm.postType === '1'" class="form-item">
<text class="form-label">快递公司</text>
<input
v-model.trim="mailForm.tt"
v-model.trim="mailForm.postName"
class="form-input"
placeholder="请输入快递公司"
maxlength="30"
/>
</view>
<view v-if="mailForm.type === '2'" class="form-item">
<view v-if="mailForm.postType === '1'" class="form-item">
<text class="form-label">快递号</text>
<input
v-model.trim="mailForm.code"
v-model.trim="mailForm.postCode"
class="form-input"
placeholder="请输入快递号"
maxlength="40"
......@@ -149,6 +162,11 @@ const deptType = ref('')
const loadStatus = ref('more')
const showMailPopup = ref(false)
const currentRow = ref(null)
const typeTabs = [
{ name: '级位证书', type: '1' },
{ name: '段位证书', type: '2' },
{ name: '越段证书', type: '3' }
]
const queryParams = ref({
pageNum: 1,
......@@ -158,9 +176,9 @@ const queryParams = ref({
const mailForm = ref({
payId: '',
type: '1',
tt: '',
code: ''
postType: '0',
postName: '',
postCode: ''
})
onLoad((options) => {
......@@ -194,6 +212,12 @@ function init() {
getList()
}
function switchType(type) {
if (queryParams.value.type === type) return
queryParams.value.type = type
init()
}
function getList() {
if (loadStatus.value === 'nomore' || loading.value) return
......@@ -233,22 +257,26 @@ function loadMore() {
}
function handleView(item) {
if (queryParams.value.type === '1') {
uni.navigateTo({
url: `/pages/rank/applyDetail?examId=${item.examId}&type=${queryParams.value.type}`
url: `/level/applyDetail?examId=${item.examId}`
})
return
}
const detailType = queryParams.value.type === '3' ? '4' : '2'
uni.navigateTo({
url: `/pages/rank/applyDetail?examId=${item.examId}&type=${detailType}`
})
}
function showMailButton(item) {
return deptType.value === '1' && String(item.postStatus) !== '1'
}
function openMailPopup(item) {
if (String(item.postStatus) === '1') return
currentRow.value = item
mailForm.value = {
payId: item.payId,
type: '1',
tt: '',
code: ''
postType: '0',
postName: '',
postCode: ''
}
showMailPopup.value = true
}
......@@ -259,22 +287,22 @@ function closeMailPopup() {
}
function handleMailTypeChange(e) {
mailForm.value.type = e.detail.value
if (mailForm.value.type === '1') {
mailForm.value.tt = ''
mailForm.value.code = ''
mailForm.value.postType = e.detail.value
if (mailForm.value.postType === '0') {
mailForm.value.postName = ''
mailForm.value.postCode = ''
}
}
async function submitMail() {
if (!mailForm.value.payId) return
if (mailForm.value.type === '2') {
if (!mailForm.value.tt) {
if (mailForm.value.postType === '1') {
if (!mailForm.value.postName) {
uni.showToast({ title: '请输入快递公司', icon: 'none' })
return
}
if (!mailForm.value.code) {
if (!mailForm.value.postCode) {
uni.showToast({ title: '请输入快递号', icon: 'none' })
return
}
......@@ -282,7 +310,11 @@ async function submitMail() {
try {
uni.showLoading({ title: '提交中' })
if (mailForm.value.postType === '0') {
await api.postCert(mailForm.value.payId)
} else {
await api.editPostInfo({ ...mailForm.value })
}
uni.showToast({ title: '操作成功', icon: 'success' })
closeMailPopup()
init()
......@@ -294,12 +326,9 @@ async function submitMail() {
}
function handleLogistics(item) {
if (String(item.postStatus) !== '1' || !item.postCode) {
uni.showToast({ title: '暂无物流信息', icon: 'none' })
return
}
const postName = encodeURIComponent(item.postName || '')
uni.navigateTo({
url: `/level/ztx/certLogistics?payId=${item.payId}&postCode=${item.postCode}&postStatus=${item.postStatus}&submitTime=${item.submitTime || ''}`
url: `/level/ztx/certLogistics?payId=${item.payId}&postCode=${item.postCode || ''}&postName=${postName}&postType=${item.postType || '0'}&postStatus=${item.postStatus || ''}&submitTime=${item.submitTime || ''}`
})
}
......@@ -324,6 +353,40 @@ function formatDate(dateStr) {
}
}
.mail-tabs {
display: flex;
flex-shrink: 0;
background: #fff;
border-bottom: 1rpx solid #eee;
.mail-tab {
flex: 1;
height: 84rpx;
line-height: 84rpx;
text-align: center;
font-size: 28rpx;
color: #666;
position: relative;
&.active {
color: #c30d23;
font-weight: bold;
&::after {
content: '';
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
width: 72rpx;
height: 4rpx;
border-radius: 2rpx;
background: #c30d23;
}
}
}
}
.mail-list-scroll {
flex: 1;
height: 0;
......@@ -591,6 +654,13 @@ function formatDate(dateStr) {
border: 1rpx solid #ccc;
background: #fff;
}
.disabled,
button[disabled] {
color: #b8b8b8;
border-color: #e1e1e1;
background: #f5f5f5;
}
}
.popup-mask {
......
......@@ -230,9 +230,9 @@
考试申请
</view>
<view @click="goPath('/level/ztx/mail')">
<view @click="goPath('/level/ztx/mail?type=1')">
<image :src="config.baseUrl_api+'/fs/static/icon/25.png'"/>
证书邮寄
证书邮寄1
</view>
<!-- <view @click="goPath('/level/ztx/costSettlement')">
<image :src="config.baseUrl_api+'/fs/static/icon/10.png'"/>
......@@ -433,14 +433,7 @@
<image :src="config.baseUrl_api+'/fs/static/icon/2.png'"/>
考试审核
</view>
<view @click="goPath('/level/ztx/mail')">
<image :src="config.baseUrl_api+'/fs/static/icon/3.png'"/>
证书邮寄
</view>
<view @click="goPath('/level/ztx/cert?type=1')">
<image :src="config.baseUrl_api+'/fs/static/icon/18.png'"/>
证书发布
</view>
<view @click="goPath('/personalVip/changeLevelAudit')">
<image :src="config.baseUrl_api+'/fs/static/icon/26.png'"/>
变更审核
......@@ -449,7 +442,14 @@
<image :src="config.baseUrl_api+'/fs/static/icon/10.png'"/>
结算审核
</view>
<view @click="goPath('/level/ztx/mail?type=1')">
<image :src="config.baseUrl_api+'/fs/static/icon/5.png'"/>
证书邮寄
</view>
<view @click="goPath('/level/ztx/cert?type=1')">
<image :src="config.baseUrl_api+'/fs/static/icon/18.png'"/>
证书发布
</view>
<view @click="goPath('/personalVip/order?type=2')">
<image :src="config.baseUrl_api+'/fs/static/icon/6.png'"/>
订单列表
......@@ -468,6 +468,11 @@
<image :src="config.baseUrl_api+'/fs/static/icon/19.png'"/>
成绩审核
</view>
<view @click="goPath('/level/ztx/mail?type=2')">
<image :src="config.baseUrl_api+'/fs/static/icon/5.png'"/>
证书邮寄
</view>
<view @click="goPath('/level/ztx/cert?type=2')">
<image :src="config.baseUrl_api+'/fs/static/icon/20.png'"/>
证书发布
......@@ -490,6 +495,10 @@
<image :src="config.baseUrl_api+'/fs/static/icon/22.png'"/>
成绩审核
</view>
<view @click="goPath('/level/ztx/mail?type=3')">
<image :src="config.baseUrl_api+'/fs/static/icon/5.png'"/>
证书邮寄
</view>
<view @click="goPath('/level/ztx/cert?type=3')">
<image :src="config.baseUrl_api+'/fs/static/icon/23.png'"/>
证书发布
......
<template>
<view>
<view class="record-page">
<scroll-view
class="record-scroll"
:show-scrollbar="false"
lower-threshold="160"
scroll-y
@scrolltolower="loadMore"
>
<view class="appList">
<view class="appItem" v-for="(item,index) in list" :key="index" @click="goDetail(item)">
<view class="status">
<text :class="statusClass(item)">{{ statusText(item) }}</text>
</view>
<view class="appItem" v-for="(item, index) in list" :key="item.id || index">
<!-- 头部:姓名+日期 -->
<view class="record-header">
<!-- <view class="avatar">
<text>{{ (item.personName || '-').charAt(0) }}</text>
</view> -->
<view class="header-info">
<view class="name">{{ item.personName || '-' }}{{ item.personIdcCode || '-' }}</view>
<view class="name mt0">
{{ item.name || '调动记录' }}
</view>
<text class="time">{{ formatDate(item.operTime) }}</text>
</view>
<view class="flexbox" v-if="deptType == 1 || deptType == 2 || deptType == 3">
<view class="w50">
申请调入单位
<view><text>{{ item.targetDeptName || '-' }}</text></view>
<!-- 单位信息对比区 -->
<view class="unit-section">
<view class="unit-item">
<view class="unit-label">原单位</view>
<view class="unit-value">{{ item.sourceMemName || '-' }}</view>
</view>
<view class="w50">
会员合计
<view>{{ item.personCount || 0 }}</view>
<view class="divider-line">
<uni-icons type="arrow-right" size="16" color="#999"></uni-icons>
</view>
<view class="unit-item target">
<view class="unit-label">申请单位</view>
<view class="unit-value">{{ item.targetMemName || '-' }}</view>
</view>
<view v-else class="pp">
会员合计:
<text class="text-primary">{{ item.personCount || 0 }}</text>
</view>
</view>
<view class="loading-tip" v-if="loading">加载中...</view>
<view class="no-more" v-if="!loading && !hasMore && list.length > 0">没有更多了</view>
</view>
</scroll-view>
<view class="nodata" v-if="list.length==0 && !loading">
<view class="nodata" v-if="list.length === 0 && !loading">
<image mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image>
<text>暂无数据</text>
</view>
......@@ -38,16 +52,19 @@
<script setup>
import * as api from '@/common/api.js'
import config from '@/config.js'
import { ref } from 'vue'
import { reactive, ref } from 'vue'
import { onLoad, onShow } from '@dcloudio/uni-app'
const app = getApp()
const queryParams = ref({})
const list = ref([])
const total = ref(0)
const deptType = ref('')
const loading = ref(false)
const hasMore = ref(true)
const hasInited = ref(false)
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
noAuditProcess: '1'
})
onLoad(() => {
if (app.globalData.isLogin) {
......@@ -61,93 +78,205 @@
onShow(() => {
if (hasInited.value) {
getList()
resetList()
}
})
function init() {
deptType.value = app.globalData.deptType
queryParams.value = {}
if (deptType.value == 2 || deptType.value == 3) {
queryParams.value.dgId = -1
}
if (deptType.value == 1) {
queryParams.value.dgId = -2
}
if (deptType.value == 6) {
queryParams.value.dgId = 1
}
hasInited.value = true
resetList()
}
function resetList() {
queryParams.pageNum = 1
list.value = []
hasMore.value = true
getList()
}
function getList() {
if (loading.value || !hasMore.value) return
loading.value = true
uni.showLoading({
title: '加载中',
mask: true
api.logList(queryParams).then(res => {
const rows = res.rows || []
if (queryParams.pageNum === 1) {
list.value = rows
} else {
list.value.push(...rows)
}
hasMore.value = list.value.length < Number(res.total || 0)
}).catch(() => {
uni.showToast({
title: '加载失败',
icon: 'none'
})
api.getMobilizelist(queryParams.value).then(res => {
list.value = res.rows || []
total.value = res.total || 0
if (queryParams.pageNum > 1) {
queryParams.pageNum--
}
}).finally(() => {
loading.value = false
uni.hideLoading()
})
}
function statusText(item) {
if (deptType.value == 1) {
const map = {
0: '审核中',
1: '审核通过',
2: '审核拒绝',
3: '撤销申请'
function loadMore() {
if (loading.value || !hasMore.value) return
queryParams.pageNum++
getList()
}
return map[item.ztxRes] || '-'
function formatDate(dateValue) {
if (!dateValue) return '-'
return String(dateValue).substring(0, 10)
}
if (deptType.value == 2 || deptType.value == 3) {
const map = {
0: '审核中',
1: '审核通过',
2: '审核拒绝',
3: '撤销申请'
</script>
<style scoped lang="scss">
.record-page {
height: 100vh;
background: #f5f7fa;
position: relative;
}
return map[item.shenRes] || '-'
.record-scroll {
height: 100%;
}
.appList {
// padding: 10rpx;
box-sizing: border-box;
}
const map = {
0: '待提交',
1: '审核中',
2: '审核拒绝',
3: '审核通过',
4: '已撤回'
.appItem {
background: #fff;
border-radius: 16rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
padding:0 20rpx 20rpx 20rpx;
margin-bottom: 20rpx;
transition: all 0.2s ease;
&:active {
transform: scale(0.99);
box-shadow: 0 1rpx 8rpx rgba(0, 0, 0, 0.08);
}
return map[item.status] || '-'
}
function statusClass(item) {
const value = deptType.value == 1 ? item.ztxRes : (deptType.value == 2 || deptType.value == 3 ? item.shenRes : item.status)
if (value == 1 || value == 3) return 'text-success'
if (value == 2 || value == 4) return 'text-danger'
return 'text-primary'
.record-header {
display: flex;
align-items: center;
// margin-bottom: 24rpx;
}
function goDetail(item) {
const auditLog = encodeURIComponent(JSON.stringify(item.auditLog))
const form = encodeURIComponent(JSON.stringify(item))
uni.navigateTo({
url: `/personalVip/mobilizeDetail?rangeId=${item.id}&auditLog=${auditLog}&form=${form}`
})
.avatar {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
display: flex;
align-items: center;
justify-content: center;
margin-right: 16rpx;
text {
font-size: 28rpx;
color: #fff;
font-weight: 500;
}
}
</script>
<style scoped lang="scss">
.mt0 {
margin-top: 0 !important;
.header-info {
flex: 1;
}
.appList .appItem .name {
width: 80%;
.name {
font-size: 32rpx;
font-weight: 600;
color: #1a1a1a;
margin-bottom: 6rpx;
}
.id-card {
display: flex;
align-items: center;
.label {
font-size: 24rpx;
color: #999;
}
.value {
font-size: 24rpx;
color: #666;
}
}
.time {
font-size: 24rpx;
color: #999;
}
.unit-section {
display: flex;
align-items: center;
background: #f9fafc;
border-radius: 12rpx;
padding: 20rpx 16rpx;
}
.unit-item {
flex: 1;
padding: 0 12rpx;
.unit-label {
font-size: 22rpx;
color: #999;
margin-bottom: 8rpx;
}
.unit-value {
font-size: 26rpx;
color: #333;
line-height: 1.4;
word-break: break-all;
}
&.target .unit-value {
color: #C4121B;
}
}
.divider-line {
display: flex;
align-items: center;
justify-content: center;
padding: 0 8rpx;
}
.loading-tip,
.no-more {
text-align: center;
color: #999;
font-size: 24rpx;
padding: 20rpx 0;
}
.nodata {
position: absolute;
top: 180rpx;
left: 0;
right: 0;
display: flex;
flex-direction: column;
align-items: center;
image {
width: 280rpx;
height: 280rpx;
margin-bottom: 16rpx;
}
text {
color: #999;
font-size: 26rpx;
}
}
</style>
\ No newline at end of file
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!