1、调整退费跳转逻辑
2、完善退费申请逻辑
This commit is contained in:
parent
b34ca07a45
commit
d46c17386d
@ -87,3 +87,35 @@ export const xkkclxFindAllApi = async () => {
|
|||||||
export const getXkkcDetailByIdApi = async (id: string) => {
|
export const getXkkcDetailByIdApi = async (id: string) => {
|
||||||
return await get("/api/xkkc/getXkkcDetailById?id=" + id);
|
return await get("/api/xkkc/getXkkcDetailById?id=" + id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验学生选课退费(用于退费时使用)
|
||||||
|
*/
|
||||||
|
export const checkXkTfApi = async (params: any) => {
|
||||||
|
return await get("/mobile/jz/checkXkTf", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取选课退费分页查询
|
||||||
|
* @param params
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const findPageXkTfApi = async (params: any) => {
|
||||||
|
return await get("/api/xkTf/findPage", params);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取选课退费详情
|
||||||
|
* @param params
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const getXkTfDetailByIdApi = async (id: string) => {
|
||||||
|
return await get("/api/xkTf/getDetailById?id=" + id);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 家长申请退费
|
||||||
|
*/
|
||||||
|
export const xkTfSqApi = async (params: any) => {
|
||||||
|
return await post("/api/xkTf/sq", params);
|
||||||
|
};
|
||||||
|
|||||||
@ -43,4 +43,4 @@ function change(e: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|||||||
@ -21,7 +21,7 @@
|
|||||||
const attrs = useAttrs()
|
const attrs = useAttrs()
|
||||||
|
|
||||||
const blob = ref<string | null>(null)
|
const blob = ref<string | null>(null)
|
||||||
const popup = ref<{ open: (v: string) => void } | null>(null)
|
const popup = ref<{ open: (v: string) => void, close: () => void }>({ open: () => { }, close: () => { }})
|
||||||
|
|
||||||
const emits = defineEmits(['select', 'close'])
|
const emits = defineEmits(['select', 'close'])
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="wh-full">
|
<view class="wh-full">
|
||||||
<u-upload
|
<u-upload :fileList="data.fileList" @oversize="oversize" @afterRead="afterRead" @delete="deletePic" v-bind="attrs"
|
||||||
:fileList="data.fileList"
|
:deletable="!attrs.disabled" />
|
||||||
@afterRead="afterRead"
|
|
||||||
@delete="deletePic"
|
|
||||||
v-bind="attrs"
|
|
||||||
:deletable="!attrs.disabled"
|
|
||||||
/>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -53,6 +48,18 @@ watchEffect(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
async function oversize(file: any) {
|
||||||
|
// 动态显示文件大小限制
|
||||||
|
const maxSize = attrs.maxSize || 5 * 1024 * 1024; // 默认5MB
|
||||||
|
const maxSizeMB = (maxSize / 1024 / 1024).toFixed(2);
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: `文件大小不能超过${maxSizeMB}MB`,
|
||||||
|
icon: 'none',
|
||||||
|
duration: 3000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function afterRead(event: any) {
|
async function afterRead(event: any) {
|
||||||
isUpdate = true
|
isUpdate = true
|
||||||
// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式
|
// 当设置 mutiple 为 true 时, file 为数组格式,否则为对象格式
|
||||||
@ -68,7 +75,7 @@ async function afterRead(event: any) {
|
|||||||
|
|
||||||
for (let i = 0; i < lists.length; i++) {
|
for (let i = 0; i < lists.length; i++) {
|
||||||
showLoading({ title: '上传中' })
|
showLoading({ title: '上传中' })
|
||||||
const {result} = await attachmentUpload(lists[i].url)
|
const { result } = await attachmentUpload(lists[i].url) as any
|
||||||
hideLoading()
|
hideLoading()
|
||||||
let item = data.fileList[fileListLen]
|
let item = data.fileList[fileListLen]
|
||||||
data.fileList.splice(fileListLen, 1, Object.assign(item, {
|
data.fileList.splice(fileListLen, 1, Object.assign(item, {
|
||||||
|
|||||||
134
src/components/PreviewImage/index.vue
Normal file
134
src/components/PreviewImage/index.vue
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
<template>
|
||||||
|
<view class="image-preview-container">
|
||||||
|
<view class="preview-title" v-if="title">{{ title }}</view>
|
||||||
|
<view class="image-list" v-if="imageList && imageList.length > 0">
|
||||||
|
<view
|
||||||
|
class="image-item"
|
||||||
|
v-for="(image, index) in imageList"
|
||||||
|
:key="index"
|
||||||
|
@click="previewImages(index)"
|
||||||
|
:style="{ width: width + 'rpx', height: height + 'rpx' }"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
:src="getImageUrl(image)"
|
||||||
|
class="preview-image"
|
||||||
|
mode="aspectFill"
|
||||||
|
/>
|
||||||
|
<view class="image-overlay" v-if="showOverlay">
|
||||||
|
<uni-icons type="eye" size="24" color="#fff"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="no-image" v-else>
|
||||||
|
{{ emptyText || '暂无图片' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { imagUrl } from '@/utils'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
imageList: {
|
||||||
|
type: Array as () => string[],
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
emptyText: {
|
||||||
|
type: String,
|
||||||
|
default: '暂无图片'
|
||||||
|
},
|
||||||
|
showOverlay: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: Number,
|
||||||
|
default: 120
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: Number,
|
||||||
|
default: 120
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const getImageUrl = (url: string) => {
|
||||||
|
if (url && (url.startsWith('http://') || url.startsWith('https://'))) {
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
return imagUrl(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
const previewImages = (currentIndex: number) => {
|
||||||
|
if (!props.imageList || props.imageList.length === 0) return
|
||||||
|
|
||||||
|
const urls = props.imageList.map(item => getImageUrl(item))
|
||||||
|
|
||||||
|
uni.previewImage({
|
||||||
|
current: currentIndex,
|
||||||
|
urls: urls as string[]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.image-preview-container {
|
||||||
|
padding: 20rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-item {
|
||||||
|
position: relative;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1rpx solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-item:hover .image-overlay {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-overlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-image {
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
padding: 40rpx 0;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@ -227,6 +227,20 @@
|
|||||||
"enablePullDownRefresh": false
|
"enablePullDownRefresh": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/base/xk/tf/sq",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "选课退费申请",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/base/xk/tf/detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "选课退费详情",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/base/xk/qk/wks",
|
"path": "pages/base/xk/qk/wks",
|
||||||
"style": {
|
"style": {
|
||||||
@ -286,6 +300,13 @@
|
|||||||
"enablePullDownRefresh": false
|
"enablePullDownRefresh": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/base/gzs/tf",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "退费告知书",
|
||||||
|
"enablePullDownRefresh": false
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/base/jc/index",
|
"path": "pages/base/jc/index",
|
||||||
"style": {
|
"style": {
|
||||||
|
|||||||
@ -63,6 +63,10 @@ onLoad(async (options: any) => {
|
|||||||
async function submit() {
|
async function submit() {
|
||||||
// 显示加载中
|
// 显示加载中
|
||||||
const data = await signCompRef.value.getSyncSignature();
|
const data = await signCompRef.value.getSyncSignature();
|
||||||
|
if (!data) {
|
||||||
|
console.log("请签名");
|
||||||
|
return;
|
||||||
|
}
|
||||||
sign_file.value = data.base64;
|
sign_file.value = data.base64;
|
||||||
setFile({
|
setFile({
|
||||||
sign_file: sign_file.value,
|
sign_file: sign_file.value,
|
||||||
|
|||||||
127
src/pages/base/gzs/tf.vue
Normal file
127
src/pages/base/gzs/tf.vue
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<template>
|
||||||
|
<BasicLayout>
|
||||||
|
<view class="p-15">
|
||||||
|
<view class="white-bg-color p-15 r-md" v-if="notice">
|
||||||
|
<RichTextContent :content="notice" />
|
||||||
|
<!-- <view v-html="notice" />" -->
|
||||||
|
</view>
|
||||||
|
<BasicSign ref="signCompRef" title="签名"></BasicSign>
|
||||||
|
</view>
|
||||||
|
<template #bottom>
|
||||||
|
<view class="white-bg-color py-5">
|
||||||
|
<view class="flex-row items-center pb-10 pt-5">
|
||||||
|
<u-button
|
||||||
|
text="下一步"
|
||||||
|
class="mx-15"
|
||||||
|
type="primary"
|
||||||
|
@click="submit"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</BasicLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { xkgzsApi } from "@/api/base/server";
|
||||||
|
import { useDataStore } from "@/store/modules/data";
|
||||||
|
import { showLoading } from "@/utils/uniapp";
|
||||||
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
|
import RichTextContent from "@/components/RichTextContent/RichTextContent.vue";
|
||||||
|
|
||||||
|
const signCompRef = ref<any>(null);
|
||||||
|
const sign_file = ref<any>(null);
|
||||||
|
const { setFile } = useDataStore();
|
||||||
|
|
||||||
|
const notice = ref("");
|
||||||
|
const lxId = ref("");
|
||||||
|
|
||||||
|
onLoad(async (options: any) => {
|
||||||
|
lxId.value = options.lxId || '';
|
||||||
|
let kcLx = "";
|
||||||
|
switch (lxId.value) {
|
||||||
|
case "JC": {
|
||||||
|
kcLx = "就餐";
|
||||||
|
} break;
|
||||||
|
case "816059832": {
|
||||||
|
kcLx = "俱乐部退费";
|
||||||
|
} break;
|
||||||
|
case "962488654": {
|
||||||
|
kcLx = "兴趣课退费";
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
uni.reLaunch({ url: '/pages/base/home/index' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showLoading({ title: "加载中..." });
|
||||||
|
const res = await xkgzsApi({ kcLx: kcLx });
|
||||||
|
notice.value = res.rows?.[0]?.content || "";
|
||||||
|
uni.hideLoading();
|
||||||
|
});
|
||||||
|
|
||||||
|
async function submit() {
|
||||||
|
// 显示加载中
|
||||||
|
const data = await signCompRef.value.getSyncSignature();
|
||||||
|
if (!data) {
|
||||||
|
console.log("请签名");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sign_file.value = data.base64;
|
||||||
|
setFile({
|
||||||
|
sign_file: sign_file.value,
|
||||||
|
});
|
||||||
|
switch (lxId.value) {
|
||||||
|
case "JC": {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: "/pages/base/jc/tf",
|
||||||
|
});
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
uni.reLaunch({
|
||||||
|
url: "/pages/base/xk/tf/sq?xklxId=" + lxId.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 页面样式
|
||||||
|
.white-bg-color {
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.r-md {
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-15 {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.py-5 {
|
||||||
|
padding: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pb-10 {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pt-5 {
|
||||||
|
padding-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items-center {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx-15 {
|
||||||
|
margin: 0 15px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -223,6 +223,7 @@ const menuItems = ref([
|
|||||||
icon: "/static/base/home/file-text-line.png",
|
icon: "/static/base/home/file-text-line.png",
|
||||||
path: "/pages/base/gzs/index",
|
path: "/pages/base/gzs/index",
|
||||||
permissionKey: "school-xqkxk", // 兴趣课选课权限编码
|
permissionKey: "school-xqkxk", // 兴趣课选课权限编码
|
||||||
|
action: 'jf',
|
||||||
lxId: '962488654',
|
lxId: '962488654',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -230,6 +231,7 @@ const menuItems = ref([
|
|||||||
icon: "/static/base/home/contacts-book-3-line.png",
|
icon: "/static/base/home/contacts-book-3-line.png",
|
||||||
path: "/pages/base/gzs/index",
|
path: "/pages/base/gzs/index",
|
||||||
permissionKey: "school-jlbxk", // 俱乐部选课权限编码
|
permissionKey: "school-jlbxk", // 俱乐部选课权限编码
|
||||||
|
action: 'jf',
|
||||||
lxId: '816059832',
|
lxId: '816059832',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -237,13 +239,24 @@ const menuItems = ref([
|
|||||||
icon: "/static/base/home/contacts-book-3-line.png",
|
icon: "/static/base/home/contacts-book-3-line.png",
|
||||||
path: "/pages/base/gzs/index",
|
path: "/pages/base/gzs/index",
|
||||||
permissionKey: "school-jcjf",
|
permissionKey: "school-jcjf",
|
||||||
|
action: 'jf',
|
||||||
lxId: 'JC',
|
lxId: 'JC',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "退费申请",
|
title: "兴趣课退费",
|
||||||
icon: "/static/base/home/contacts-book-3-line.png",
|
icon: "/static/base/home/contacts-book-3-line.png",
|
||||||
path: "/pages/base/tf/index",
|
path: "/pages/base/gzs/tf",
|
||||||
permissionKey: "school-jlb",
|
permissionKey: "school-xqk-tf",
|
||||||
|
action: "tf",
|
||||||
|
lxId: "962488654",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "俱乐部退费",
|
||||||
|
icon: "/static/base/home/contacts-book-3-line.png",
|
||||||
|
path: "/pages/base/gzs/tf",
|
||||||
|
permissionKey: "school-jlb-tf",
|
||||||
|
action: "tf",
|
||||||
|
lxId: "816059832",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -268,13 +281,13 @@ const goToGlxs = () => {
|
|||||||
// 处理菜单点击
|
// 处理菜单点击
|
||||||
const handleMenuClick = debounce(async (item: any) => {
|
const handleMenuClick = debounce(async (item: any) => {
|
||||||
if (item.path) {
|
if (item.path) {
|
||||||
if (!item.lxId) {
|
if (item.lxId) {
|
||||||
|
setGlobal({ lxId: item.lxId, action: item.action, from: 'home' });
|
||||||
|
PageUtils.toHome(item.lxId, item.action);
|
||||||
|
} else {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: item.path,
|
url: item.path,
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
setGlobal({ lxId: item.lxId, from: 'home' });
|
|
||||||
PageUtils.toHome(item.lxId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -23,7 +23,7 @@ const switchXs = (xs: any) => {
|
|||||||
// 设置学生选择器已初始化标记
|
// 设置学生选择器已初始化标记
|
||||||
setXsPickerInitialized(true);
|
setXsPickerInitialized(true);
|
||||||
// 检查逻辑页面
|
// 检查逻辑页面
|
||||||
PageUtils.checkLogicPage(xs.lxId);
|
PageUtils.checkLogicPage(getGlobal.lxId, getGlobal.action);
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,8 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="xkqd-list">
|
<view class="xkqd-list">
|
||||||
<!-- 课程信息卡片 -->
|
<!-- 课程信息卡片 -->
|
||||||
<view class="info-card" v-for="(item, index) in dataList" :key="index">
|
<view class="info-card" v-for="(item, index) in dataList" :key="index" @click="handleClick(item)">
|
||||||
|
<view class="card-header">
|
||||||
<view class="card-title">课程信息</view>
|
<view class="card-title">课程信息</view>
|
||||||
|
<view class="card-actions" v-if="canSelected">
|
||||||
|
<view class="radio-container">
|
||||||
|
<uni-icons
|
||||||
|
:type="item.selected ? 'checkbox-filled' : 'circle'"
|
||||||
|
:color="item.selected ? '#3FBF72' : '#ccc'"
|
||||||
|
size="30"
|
||||||
|
></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view class="divider"></view>
|
<view class="divider"></view>
|
||||||
|
|
||||||
<view class="course-info">
|
<view class="course-info">
|
||||||
@ -27,72 +39,108 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { imagUrl } from "@/utils";
|
import { imagUrl } from "@/utils";
|
||||||
|
|
||||||
// 接收外部传入属性
|
// 接收外部传入属性并设置默认值
|
||||||
const props = defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
dataList: any
|
dataList: any[];
|
||||||
}>();
|
canSelected: boolean,
|
||||||
|
}>(), {
|
||||||
|
xk: () => ({}),
|
||||||
|
canSelected: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleClick = (item: any) => {
|
||||||
|
if (!props.canSelected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
item.selected = !item.selected;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取已选课程列表
|
||||||
|
const getSelectedList = () => {
|
||||||
|
const list = props.dataList || [];
|
||||||
|
return list.filter((item: any) => item.selected);
|
||||||
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
getSelectedList,
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.xkqd-list {
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
.info-card {
|
.info-card {
|
||||||
margin: 15px;
|
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 8px;
|
border-radius: 10px;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.card-title {
|
.card-title {
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #333;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
height: 1px;
|
height: 1px;
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
margin-bottom: 15px;
|
margin: 10px 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.course-info {
|
.course-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
.course-image {
|
.course-image {
|
||||||
width: 120px;
|
width: 100px;
|
||||||
height: 120px;
|
height: 100px;
|
||||||
border-radius: 8px;
|
border-radius: 5px;
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.course-details {
|
.course-details {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.course-name {
|
.course-name {
|
||||||
font-size: 18px;
|
font-size: 16px;
|
||||||
font-weight: 500;
|
font-weight: bold;
|
||||||
color: #333;
|
margin-bottom: 5px;
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.course-teacher,
|
.course-teacher,
|
||||||
.course-location {
|
.course-location {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #666;
|
color: #666;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.course-price {
|
.course-price {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #666;
|
color: #ff6600;
|
||||||
|
}
|
||||||
|
|
||||||
.price-value {
|
.price-value {
|
||||||
color: #ff6b00;
|
font-size: 16px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
.radio-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.radio-container uni-icons {
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@ -173,7 +173,7 @@ const submit = debounce(async () => {
|
|||||||
title: res.message,
|
title: res.message,
|
||||||
icon: "none",
|
icon: "none",
|
||||||
});
|
});
|
||||||
PageUtils.toHome(xklxId.value);
|
PageUtils.toHome(xklxId.value, "jf");
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
@ -182,7 +182,7 @@ const submit = debounce(async () => {
|
|||||||
title: error.message || "报名失败",
|
title: error.message || "报名失败",
|
||||||
icon: "none",
|
icon: "none",
|
||||||
});
|
});
|
||||||
PageUtils.toHome(xklxId.value);
|
PageUtils.toHome(xklxId.value, "jf");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ onLoad((options:any) => {
|
|||||||
if (dataObj.action === 'qk') {
|
if (dataObj.action === 'qk') {
|
||||||
if (dataObj.code === 1 && dataObj.data === "qk") {
|
if (dataObj.code === 1 && dataObj.data === "qk") {
|
||||||
clearXkkcSelected();
|
clearXkkcSelected();
|
||||||
PageUtils.toHome(xklxId.value);
|
PageUtils.toHome(xklxId.value, "jf");
|
||||||
} else if (dataObj.code === 2) { // 课程提示
|
} else if (dataObj.code === 2) { // 课程提示
|
||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@ -136,7 +136,7 @@ const submit = async () => {
|
|||||||
xkId: curXk.value.id,
|
xkId: curXk.value.id,
|
||||||
xkkcIds: selectedXkkcIds.value,
|
xkkcIds: selectedXkkcIds.value,
|
||||||
jzId: getUser.jzId,
|
jzId: getUser.jzId,
|
||||||
qmFile: sign_file ? sign_file.value : "",
|
qmFile: sign_file ? sign_file : "",
|
||||||
};
|
};
|
||||||
const res = await jzXkQkjApi(params);
|
const res = await jzXkQkjApi(params);
|
||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
|
|||||||
@ -136,7 +136,7 @@ const submit = async () => {
|
|||||||
xkId: curXk.value.id,
|
xkId: curXk.value.id,
|
||||||
xkkcIds: selectedXkkcIds.value,
|
xkkcIds: selectedXkkcIds.value,
|
||||||
jzId: getUser.jzId,
|
jzId: getUser.jzId,
|
||||||
qmFile: sign_file ? sign_file.value : "",
|
qmFile: sign_file ? sign_file : "",
|
||||||
};
|
};
|
||||||
const res = await jzXkQkjApi(params);
|
const res = await jzXkQkjApi(params);
|
||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
|
|||||||
276
src/pages/base/xk/tf/components/progressList.vue
Normal file
276
src/pages/base/xk/tf/components/progressList.vue
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
<template>
|
||||||
|
<view class="approval-progress">
|
||||||
|
<view class="progress-title">
|
||||||
|
<text class="applicant-name">审批进度</text>
|
||||||
|
</view>
|
||||||
|
<view class="divider"></view>
|
||||||
|
<view class="progress-list">
|
||||||
|
<view class="progress-item" v-for="(approver, index) in approvalList" :key="index">
|
||||||
|
<view class="progress-item-row">
|
||||||
|
<view class="item-avatar">
|
||||||
|
<image
|
||||||
|
:src="approver.avatar || '/static/base/home/11222.png'"
|
||||||
|
class="w-full h-full"
|
||||||
|
></image>
|
||||||
|
</view>
|
||||||
|
<view class="item-middle">
|
||||||
|
<text class="item-name">{{ approver.userName }}</text>
|
||||||
|
<text class="item-detail">{{ getSpTypeText(approver.spType) }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="item-right">
|
||||||
|
<text class="item-time" v-if="approver.approveTime">{{ formatTime(approver.approveTime) }}</text>
|
||||||
|
<text class="item-status" :class="getStatusClass(approver.approveStatus)">
|
||||||
|
{{ getStatusText(approver.approveStatus) }}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="progress-item-line" v-if="index < approvalList.length - 1"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { getXsQjApprovalProcessApi } from "@/api/base/xsQjApi";
|
||||||
|
|
||||||
|
// 接收外部传入属性
|
||||||
|
const props = withDefaults(defineProps<{
|
||||||
|
xkTfId: string
|
||||||
|
}>(), {
|
||||||
|
xkTfId: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 审批流程数据
|
||||||
|
const approvalList = ref<any[]>([]);
|
||||||
|
|
||||||
|
// 获取审批流程
|
||||||
|
const loadApprovalProcess = async () => {
|
||||||
|
if (!props.xkTfId) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 调用后端API获取审批流程数据
|
||||||
|
const res = await getXsQjApprovalProcessApi(props.xkTfId, 'XK_TF');
|
||||||
|
|
||||||
|
if (res.resultCode === 1 && res.result) {
|
||||||
|
// 转换为前端显示格式(后端已按sort字段排序)
|
||||||
|
approvalList.value = res.result.map((item: any) => ({
|
||||||
|
userName: item.userName || getDefaultUserName(item.spType),
|
||||||
|
spType: item.spType,
|
||||||
|
approveStatus: item.approveStatus,
|
||||||
|
approveTime: item.approveTime,
|
||||||
|
approveRemark: item.approveRemark,
|
||||||
|
avatar: item.avatar || '/static/base/home/11222.png'
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
loadMockData();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取审批流程失败:', error);
|
||||||
|
// 如果API调用失败,使用模拟数据
|
||||||
|
loadMockData();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取默认用户名
|
||||||
|
const getDefaultUserName = (spType: string) => {
|
||||||
|
switch (spType) {
|
||||||
|
case 'SQ': return '学生';
|
||||||
|
case 'SP': return '班主任';
|
||||||
|
case 'CC': return '家长';
|
||||||
|
default: return '未知';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载模拟数据(备用方案)
|
||||||
|
const loadMockData = () => {
|
||||||
|
const mockData = [
|
||||||
|
{
|
||||||
|
userName: '学生',
|
||||||
|
spType: 'SQ',
|
||||||
|
approveStatus: 'approved',
|
||||||
|
approveTime: new Date(),
|
||||||
|
approveRemark: '申请人提交',
|
||||||
|
avatar: '/static/base/home/11222.png'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
userName: '班主任',
|
||||||
|
spType: 'SP',
|
||||||
|
approveStatus: 'pending',
|
||||||
|
approveTime: null,
|
||||||
|
approveRemark: '待审批',
|
||||||
|
avatar: '/static/base/home/11222.png'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
approvalList.value = mockData;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取审批类型文本
|
||||||
|
const getSpTypeText = (spType: string) => {
|
||||||
|
switch (spType) {
|
||||||
|
case 'SQ': return '申请人';
|
||||||
|
case 'SP': return '审批人';
|
||||||
|
case 'CC': return '抄送人';
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取状态文本
|
||||||
|
const getStatusText = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case 'apply': return '已申请';
|
||||||
|
case 'pending': return '待处理';
|
||||||
|
case 'approved': return '已同意';
|
||||||
|
case 'rejected': return '已拒绝';
|
||||||
|
case 'cc_sent': return '已抄送';
|
||||||
|
default: return '未知';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取状态样式类
|
||||||
|
const getStatusClass = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case 'pending': return 'status-pending';
|
||||||
|
case 'approved': return 'status-approved';
|
||||||
|
case 'rejected': return 'status-rejected';
|
||||||
|
case 'cc_sent': return 'status-cc';
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 格式化时间
|
||||||
|
const formatTime = (time: string | Date) => {
|
||||||
|
if (!time) return '';
|
||||||
|
return dayjs(time).format('YYYY-MM-DD HH:mm');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听xkTfId变化
|
||||||
|
watch(() => props.xkTfId, (newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
loadApprovalProcess();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
if (props.xkTfId) {
|
||||||
|
loadApprovalProcess();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.approval-progress {
|
||||||
|
margin: 15px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 15px;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
|
.progress-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.applicant-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
height: 1px;
|
||||||
|
background-color: #eee;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.progress-item {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.progress-item-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px 0;
|
||||||
|
|
||||||
|
.item-avatar {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 12px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-middle {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.item-name {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-detail {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-right {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
|
|
||||||
|
.item-time {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-status {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
border-radius: 10px;
|
||||||
|
|
||||||
|
&.status-pending {
|
||||||
|
background-color: #fff7e6;
|
||||||
|
color: #fa8c16;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.status-approved {
|
||||||
|
background-color: #f6ffed;
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.status-rejected {
|
||||||
|
background-color: #fff2f0;
|
||||||
|
color: #ff4d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.status-cc {
|
||||||
|
background-color: #f0f5ff;
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-item-line {
|
||||||
|
height: 20px;
|
||||||
|
width: 2px;
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
margin-left: 19px;
|
||||||
|
margin-top: -10px;
|
||||||
|
margin-bottom: -10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
128
src/pages/base/xk/tf/detail.vue
Normal file
128
src/pages/base/xk/tf/detail.vue
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
<template>
|
||||||
|
<BasicLayout>
|
||||||
|
<view class="xkTf-info">
|
||||||
|
<!-- 学生信息卡片 -->
|
||||||
|
<XkPayXs />
|
||||||
|
|
||||||
|
<!-- 课程信息卡片 -->
|
||||||
|
<XkPaySuccessXkkc :dataList="xkTfQdList" />
|
||||||
|
|
||||||
|
<!-- 退费信息卡片 -->
|
||||||
|
<view class="xkTf-card">
|
||||||
|
<view class="card-body">
|
||||||
|
<view class="info-column">
|
||||||
|
<text class="label">退费说明:</text>
|
||||||
|
<text class="value">{{ xkTf.tfSm }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-column">
|
||||||
|
<text class="label">缴费凭证:</text>
|
||||||
|
<text class="value">
|
||||||
|
<PreviewImage :image-list="jfPzList" empty-text="无缴费凭证" />
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 审批流程 -->
|
||||||
|
<ProgressList :qjId="xkTf.id" />
|
||||||
|
</view>
|
||||||
|
<template #bottom>
|
||||||
|
<view class="white-bg-color py-5">
|
||||||
|
<view class="flex-row items-center pb-10 pt-5">
|
||||||
|
<u-button text="返回" class="ml-15 mr-7" :plain="true" @click="navigateBack" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</BasicLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
|
import { navigateBack } from "@/utils/uniapp";
|
||||||
|
import { useDataStore } from "@/store/modules/data";
|
||||||
|
import { imagUrl } from "@/utils";
|
||||||
|
import XkPayXs from "@/pages/base/xk/components/XkPayXs/index.vue"
|
||||||
|
import XkPaySuccessXkkc from "@/pages/base/xk/components/XkPaySuccessXkkc/index.vue"
|
||||||
|
import ProgressList from "./components/progressList.vue";
|
||||||
|
import PreviewImage from "@/components/PreviewImage/index.vue";
|
||||||
|
const { getTf } = useDataStore();
|
||||||
|
|
||||||
|
const xkTf = ref<any>({});
|
||||||
|
const xkTfQdList = ref<any>([]);
|
||||||
|
const jfPzList = ref<any>([]);
|
||||||
|
|
||||||
|
// 初始化数据
|
||||||
|
const initData = (tf: any, tfQdList: any[]) => {
|
||||||
|
xkTf.value = tf;
|
||||||
|
xkTfQdList.value = tfQdList;
|
||||||
|
const jfPz = tf.jfPz || '';
|
||||||
|
// 缴费凭证逗号分隔
|
||||||
|
jfPzList.value = jfPz.split(',') || [];
|
||||||
|
};
|
||||||
|
|
||||||
|
onLoad((options: any) => {
|
||||||
|
// 表示包含了退费信息
|
||||||
|
if (getTf && getTf.xkTf) {
|
||||||
|
initData(getTf.xkTf, getTf.xkTfQdList);
|
||||||
|
} else if (options.xkTfId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.xkTf-info {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
|
||||||
|
.xkTf-card {
|
||||||
|
margin: 15px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 15px;
|
||||||
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
|
.card-body {
|
||||||
|
|
||||||
|
.info-row {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #bbb;
|
||||||
|
width: 70px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #bbb;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 8px;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
flex: 1;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
197
src/pages/base/xk/tf/sq.vue
Normal file
197
src/pages/base/xk/tf/sq.vue
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
<template>
|
||||||
|
<BasicLayout>
|
||||||
|
<view class="xkTf-info">
|
||||||
|
|
||||||
|
<!-- 学生信息卡片 -->
|
||||||
|
<XkPayXs />
|
||||||
|
|
||||||
|
<!-- 课程信息卡片 -->
|
||||||
|
<XkPaySuccessXkkc :dataList="dataList" :can-selected="true" ref="xkQdRef" />
|
||||||
|
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<template #bottom>
|
||||||
|
<view class="white-bg-color py-5">
|
||||||
|
<!-- 表单卡片 -->
|
||||||
|
<view class="form-card">
|
||||||
|
|
||||||
|
<BasicForm @register="register" />
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<view class="flex-row items-center pb-10 pt-5">
|
||||||
|
<u-button
|
||||||
|
text="返回"
|
||||||
|
class="ml-15 mr-7"
|
||||||
|
:plain="true"
|
||||||
|
@click="goBack"
|
||||||
|
/>
|
||||||
|
<u-button
|
||||||
|
:text="isSubmitting ? '申请中...' : '提交申请'"
|
||||||
|
class="ml-7 mr-15"
|
||||||
|
type="primary"
|
||||||
|
:plain="true"
|
||||||
|
@click="submit"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</BasicLayout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import { useForm } from "@/components/BasicForm/hooks/useForm";
|
||||||
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
|
import XkPayXs from "@/pages/base/xk/components/XkPayXs/index.vue"
|
||||||
|
import XkPaySuccessXkkc from "@/pages/base/xk/components/XkPaySuccessXkkc/index.vue"
|
||||||
|
import { checkXkTfApi, xkTfSqApi } from "@/api/base/xkApi";
|
||||||
|
import { useUserStore } from "@/store/modules/user";
|
||||||
|
import { useDataStore } from "@/store/modules/data";
|
||||||
|
import { useDebounce } from "@/utils/debounce";
|
||||||
|
|
||||||
|
const { getCurXs, getUser } = useUserStore();
|
||||||
|
const { getTf, getFile } = useDataStore();
|
||||||
|
const { sign_file } = getFile;
|
||||||
|
|
||||||
|
// 替换 isSubmitting 状态为 useDebounce
|
||||||
|
const { isProcessing: isSubmitting, debounce } = useDebounce(2000);
|
||||||
|
|
||||||
|
const dataList = ref<any>([]);
|
||||||
|
const xkQdRef = ref<any>(null);
|
||||||
|
|
||||||
|
const [register, { getValue, setValue }] = useForm({
|
||||||
|
schema: [
|
||||||
|
{
|
||||||
|
field: "tfSm",
|
||||||
|
label: "退费说明",
|
||||||
|
component: "BasicInput",
|
||||||
|
required: true,
|
||||||
|
itemProps: {
|
||||||
|
labelPosition: "top",
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
type: "textarea",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: "jfPz",
|
||||||
|
label: "缴费凭证",
|
||||||
|
component: "BasicUpload",
|
||||||
|
required: true,
|
||||||
|
itemProps: {
|
||||||
|
labelPosition: "top",
|
||||||
|
},
|
||||||
|
componentProps: {
|
||||||
|
maxSize: 1024 * 1024 * 5,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 返回首页
|
||||||
|
const goBack = () => {
|
||||||
|
uni.reLaunch({ url: "/pages/base/home/index" });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提交退费
|
||||||
|
const submit = debounce(async () => {
|
||||||
|
const selectedList = xkQdRef.value.getSelectedList();
|
||||||
|
if (selectedList.length <= 0) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "请选择退费课程",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const fd = await getValue();
|
||||||
|
const params = {
|
||||||
|
...fd,
|
||||||
|
xsId: getCurXs.id,
|
||||||
|
jzId: getUser.jzId,
|
||||||
|
qmFile: sign_file ? sign_file : "",
|
||||||
|
xkId: selectedList[0].xkId,
|
||||||
|
xkqdIdList: selectedList.map((item:any) => item.id),
|
||||||
|
}
|
||||||
|
uni.showLoading({
|
||||||
|
title: "提交中...",
|
||||||
|
});
|
||||||
|
const res = await xkTfSqApi(params);
|
||||||
|
if (res.resultCode === 1) {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.showToast({
|
||||||
|
title: "退费申请成功!",
|
||||||
|
icon: "none",
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
uni.reLaunch({
|
||||||
|
url: "/pages/base/home/index",
|
||||||
|
});
|
||||||
|
uni.hideLoading();
|
||||||
|
} else {
|
||||||
|
uni.hideLoading();
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.showToast({
|
||||||
|
title: res.message,
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const loadYxXkList = async (xklxId:string) => {
|
||||||
|
const res = await checkXkTfApi({
|
||||||
|
xsId: getCurXs.id,
|
||||||
|
njmcId: getCurXs.njmcId,
|
||||||
|
xklxId: xklxId,
|
||||||
|
});
|
||||||
|
const result = res.result || {};
|
||||||
|
dataList.value = result.xkqdList || [];
|
||||||
|
};
|
||||||
|
|
||||||
|
onLoad((options:any) => {
|
||||||
|
dataList.value = getTf.xkqdList || [];
|
||||||
|
if(!dataList.value.length) {
|
||||||
|
loadYxXkList(options.xklxId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.xkTf-info {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 15px;
|
||||||
|
height: 44px;
|
||||||
|
background-color: #2879ff;
|
||||||
|
|
||||||
|
.nav-left {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-right {
|
||||||
|
width: 40px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-card {
|
||||||
|
margin: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@ -38,12 +38,23 @@ const initGlobalData = (data: any) => {
|
|||||||
switch (gData.type + '') {
|
switch (gData.type + '') {
|
||||||
case "1":
|
case "1":
|
||||||
lxId = '962488654';
|
lxId = '962488654';
|
||||||
|
gData.action = "jf";
|
||||||
break;
|
break;
|
||||||
case "2":
|
case "2":
|
||||||
lxId = '816059832';
|
lxId = '816059832';
|
||||||
|
gData.action = "jf";
|
||||||
break;
|
break;
|
||||||
case "3":
|
case "3":
|
||||||
lxId = 'JC';
|
lxId = 'jf';
|
||||||
|
gData.action = "jf";
|
||||||
|
break;
|
||||||
|
case "4":
|
||||||
|
lxId = '962488654';
|
||||||
|
gData.action = "tf";
|
||||||
|
break;
|
||||||
|
case "5":
|
||||||
|
lxId = '816059832';
|
||||||
|
gData.action = "tf";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,7 +83,7 @@ onLoad(async (data: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 直接跳转到首页,关注检查在首页进行
|
// 直接跳转到首页,关注检查在首页进行
|
||||||
PageUtils.toHome(gData.lxId);
|
PageUtils.toHome(gData.lxId, gData.action);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@ -309,7 +309,7 @@ async function submit() {
|
|||||||
refreshPermissionCache(currentPermissions, res.result.changeTime);
|
refreshPermissionCache(currentPermissions, res.result.changeTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PageUtils.toHome(getGlobal.lxId);
|
PageUtils.toHome(getGlobal.lxId, getGlobal.action);
|
||||||
} else {
|
} else {
|
||||||
showToast({ title: res.message || "提交失败", icon: "none" });
|
showToast({ title: res.message || "提交失败", icon: "none" });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,8 @@ export const useDataStore = defineStore({
|
|||||||
file: {},
|
file: {},
|
||||||
params: {},
|
params: {},
|
||||||
appCode: "JZ",
|
appCode: "JZ",
|
||||||
qk: {}
|
qk: {},
|
||||||
|
tf: {}
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
getData(): any {
|
getData(): any {
|
||||||
@ -36,6 +37,9 @@ export const useDataStore = defineStore({
|
|||||||
},
|
},
|
||||||
getQk(): any {
|
getQk(): any {
|
||||||
return this.qk;
|
return this.qk;
|
||||||
|
},
|
||||||
|
getTf(): any {
|
||||||
|
return this.tf;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
@ -47,6 +51,7 @@ export const useDataStore = defineStore({
|
|||||||
this.file = {};
|
this.file = {};
|
||||||
this.params = {};
|
this.params = {};
|
||||||
this.qk = {};
|
this.qk = {};
|
||||||
|
this.tf = {};
|
||||||
},
|
},
|
||||||
setData(data: any) {
|
setData(data: any) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
@ -69,6 +74,9 @@ export const useDataStore = defineStore({
|
|||||||
setQk(data: any) {
|
setQk(data: any) {
|
||||||
this.qk = data;
|
this.qk = data;
|
||||||
},
|
},
|
||||||
|
setTf(data: any) {
|
||||||
|
this.tf = data;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
persist: {
|
persist: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { checkXsXkApi } from "@/api/base/xkApi";
|
import { checkXsXkApi, checkXkTfApi } from "@/api/base/xkApi";
|
||||||
import { checkXsJcApi } from "@/api/base/jcApi";
|
import { checkXsJcApi } from "@/api/base/jcApi";
|
||||||
import { useUserStore } from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
import { useDataStore } from "@/store/modules/data";
|
import { useDataStore } from "@/store/modules/data";
|
||||||
@ -15,8 +15,9 @@ export const PageUtils = {
|
|||||||
/**
|
/**
|
||||||
* 跳转逻辑
|
* 跳转逻辑
|
||||||
* @param lxId 类型( JC: 就餐,816059832: 俱乐部,962488654: 兴趣课)
|
* @param lxId 类型( JC: 就餐,816059832: 俱乐部,962488654: 兴趣课)
|
||||||
|
* @param action 动作(jf: 缴费,tf: 退费)
|
||||||
*/
|
*/
|
||||||
async toHome(lxId?: string) {
|
async toHome(lxId: string, action: string) {
|
||||||
// 没有类型,则跳转首页
|
// 没有类型,则跳转首页
|
||||||
if (!lxId) {
|
if (!lxId) {
|
||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
@ -38,12 +39,12 @@ export const PageUtils = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 判断业务逻辑,并跳转界面
|
// 判断业务逻辑,并跳转界面
|
||||||
await this.checkLogicPage(lxId);
|
await this.checkLogicPage(lxId, action);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* 判断业务逻辑,并跳转界面
|
* 判断业务逻辑,并跳转界面
|
||||||
*/
|
*/
|
||||||
async checkLogicPage(lxId: string) {
|
async checkLogicPage(lxId: string, action: string) {
|
||||||
switch (lxId) {
|
switch (lxId) {
|
||||||
// 就餐逻辑单独处理
|
// 就餐逻辑单独处理
|
||||||
case "JC": {
|
case "JC": {
|
||||||
@ -51,7 +52,11 @@ export const PageUtils = {
|
|||||||
} break;
|
} break;
|
||||||
// 默认当作 选课的选课类型ID(xkLxId)处理
|
// 默认当作 选课的选课类型ID(xkLxId)处理
|
||||||
default: {
|
default: {
|
||||||
|
if (action === "jf") {
|
||||||
await this.checkQkLogic(lxId);
|
await this.checkQkLogic(lxId);
|
||||||
|
} else if (action === "tf") {
|
||||||
|
await this.checkXkTfLogic(lxId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -113,5 +118,43 @@ export const PageUtils = {
|
|||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 判断退费页面切换逻辑
|
||||||
|
async checkXkTfLogic(xklxId: string) {
|
||||||
|
const res = await checkXkTfApi({
|
||||||
|
xsId: userStore.getCurXs.id,
|
||||||
|
njmcId: userStore.getCurXs.njmcId,
|
||||||
|
xklxId: xklxId,
|
||||||
|
});
|
||||||
|
console.log('checkXkTfLogic', res);
|
||||||
|
if (res.resultCode != 1) {
|
||||||
|
uni.showToast({
|
||||||
|
title: res.message,
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
uni.reLaunch({
|
||||||
|
url: "/pages/base/home/index",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const result = res.result || {};
|
||||||
|
// 记录到缓存数据中
|
||||||
|
dataStore.setTf(result);
|
||||||
|
// 状态判断
|
||||||
|
switch (result.status) {
|
||||||
|
case 'KTF': { // KTF可退费
|
||||||
|
uni.reLaunch({
|
||||||
|
url: "/pages/base/gzs/tf?lxId=" + xklxId,
|
||||||
|
});
|
||||||
|
} break;
|
||||||
|
case 'TFZ': { // TFZ退费中
|
||||||
|
uni.reLaunch({
|
||||||
|
url: "/pages/base/xk/tf/detail?xklxId=" + xklxId,
|
||||||
|
});
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user