SAAS模式调整
This commit is contained in:
parent
73515ab6a5
commit
e7a726af56
@ -8,6 +8,13 @@ export const checkXsXkApi = async (params: any) => {
|
|||||||
return await get("/mobile/jz/checkXsXk", params);
|
return await get("/mobile/jz/checkXsXk", params);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验学生选课并附带告知书内容(聚合接口,KQK 时一次返回选课状态与告知书,减少二次请求)
|
||||||
|
*/
|
||||||
|
export const checkXsXkWithGzsApi = async (params: any) => {
|
||||||
|
return await get("/mobile/jz/checkXsXkWithGzs", params);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 学生已选课程列表
|
* 学生已选课程列表
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,22 +1,32 @@
|
|||||||
const ip: string = "127.0.0.1:8897";
|
// 测试环境 / 正式环境:开发时用测试地址,打包时用正式地址
|
||||||
const fwqip: string = "127.0.0.1:8897";
|
const isDev = process.env.NODE_ENV === "development";
|
||||||
//const ip: string = "lzcxsx.cn";
|
const ip: string = isDev ? "127.0.0.1:8897" : "lzcxsx.cn";
|
||||||
//const fwqip: string = "lzcxsx.cn";
|
const fwqip: string = isDev ? "127.0.0.1:8897" : "lzcxsx.cn";
|
||||||
|
|
||||||
//const ip: string = "zhxy.yufangzc.com";
|
//const ip: string = "zhxy.yufangzc.com";
|
||||||
//const fwqip: string = "zhxy.yufangzc.com";
|
//const fwqip: string = "zhxy.yufangzc.com";
|
||||||
|
//const ip: string = "lzcxsx.cn";
|
||||||
|
//const fwqip: string = "lzcxsx.cn";
|
||||||
|
|
||||||
//打包服务器接口代理标识
|
//打包服务器接口代理标识
|
||||||
const SERVERAGENT: string = "/jzd-api";
|
const SERVERAGENT: string = "/jzd-api";
|
||||||
//本地代理url地址,配置了就启动代理,没配置就不启动代理
|
//本地代理url地址,配置了就启动代理,没配置就不启动代理
|
||||||
export const HOMEAGENT: string = "";
|
export const HOMEAGENT: string = "";
|
||||||
|
// 开发环境下,手机/平板访问时(非localhost)使用当前页面 host,避免 127.0.0.1 指向设备自身导致请求失败
|
||||||
|
function getDevBaseUrl(): string {
|
||||||
|
if (typeof window !== "undefined" && window.location?.hostname && window.location.hostname !== "localhost" && window.location.hostname !== "127.0.0.1") {
|
||||||
|
return `http://${window.location.hostname}:8897/zhxy`;
|
||||||
|
}
|
||||||
|
return `http://${ip}/zhxy`;
|
||||||
|
}
|
||||||
// 接口地址
|
// 接口地址
|
||||||
export const BASE_URL: string =
|
export const BASE_URL: string =
|
||||||
process.env.NODE_ENV == "development" ? `http://${ip}/zhxy` : SERVERAGENT;
|
process.env.NODE_ENV == "development" ? getDevBaseUrl() : SERVERAGENT;
|
||||||
// WebSocket地址
|
// WebSocket地址:开发环境用 ws(无 SSL),正式环境用 wss
|
||||||
export const BASE_WS_URL: string =
|
export const BASE_WS_URL: string = isDev ? `ws://${ip}` : `wss://${ip}`;
|
||||||
process.env.NODE_ENV == "development" ? `ws://${ip}` : `wss://${fwqip}`;
|
|
||||||
//图片地址
|
//图片地址
|
||||||
// export const BASE_IMAGE_URL: string = process.env.NODE_ENV == "development" ? `https://${ip}` : `http://${fwqip}`;
|
// export const BASE_IMAGE_URL: string = process.env.NODE_ENV == "development" ? `https://${ip}` : `https://${fwqip}`;
|
||||||
export const BASE_IMAGE_URL: string = `http://${fwqip}`;
|
export const BASE_IMAGE_URL: string = `https://${fwqip}`;
|
||||||
// kkFileView预览服务地址
|
// kkFileView预览服务地址
|
||||||
export const KK_FILE_VIEW_URL: string = `https://${fwqip}/kkpro`;
|
export const KK_FILE_VIEW_URL: string = `https://${fwqip}/kkpro`;
|
||||||
//存token的key
|
//存token的key
|
||||||
@ -33,3 +43,6 @@ export const WHITELIST: WhiteList = [];
|
|||||||
export const THEMECOLOR: string = "#35468C";
|
export const THEMECOLOR: string = "#35468C";
|
||||||
// 启动vconsole
|
// 启动vconsole
|
||||||
export const ENABLE_VCONSOLE: boolean = false; // process.env.NODE_ENV != "development";
|
export const ENABLE_VCONSOLE: boolean = false; // process.env.NODE_ENV != "development";
|
||||||
|
|
||||||
|
/** 就餐报名成功后跳转的支付链接(后续可改为接口/动态配置) */
|
||||||
|
export const JC_PAY_REDIRECT_URL: string = "https://app.xiaoyuan.ccb.com/LHECRESM/V6/JFPAGENEW/index.html#/?schoolId=213245500";
|
||||||
|
|||||||
@ -25,13 +25,15 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { xkgzsApi } from "@/api/base/server";
|
import { xkgzsApi } from "@/api/base/server";
|
||||||
import { useDataStore } from "@/store/modules/data";
|
import { useDataStore } from "@/store/modules/data";
|
||||||
|
|
||||||
|
const dataStore = useDataStore();
|
||||||
import { showLoading } from "@/utils/uniapp";
|
import { showLoading } from "@/utils/uniapp";
|
||||||
import { onLoad } from "@dcloudio/uni-app";
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
import RichTextContent from "@/components/RichTextContent/RichTextContent.vue";
|
import RichTextContent from "@/components/RichTextContent/RichTextContent.vue";
|
||||||
|
|
||||||
const signCompRef = ref<any>(null);
|
const signCompRef = ref<any>(null);
|
||||||
const sign_file = ref<any>(null);
|
const sign_file = ref<any>(null);
|
||||||
const { setFile } = useDataStore();
|
const { setFile } = dataStore;
|
||||||
|
|
||||||
const notice = ref("");
|
const notice = ref("");
|
||||||
const lxId = ref("");
|
const lxId = ref("");
|
||||||
@ -54,6 +56,12 @@ onLoad(async (options: any) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 若聚合接口已返回告知书内容,直接使用,避免二次请求
|
||||||
|
const cachedGzs = dataStore.getQk?.gzsContent;
|
||||||
|
if (cachedGzs && (lxId.value === "816059832" || lxId.value === "962488654")) {
|
||||||
|
notice.value = cachedGzs;
|
||||||
|
return;
|
||||||
|
}
|
||||||
showLoading({ title: "加载中..." });
|
showLoading({ title: "加载中..." });
|
||||||
const res = await xkgzsApi({ kcLx: kcLx });
|
const res = await xkgzsApi({ kcLx: kcLx });
|
||||||
notice.value = res.rows?.[0]?.content || "";
|
notice.value = res.rows?.[0]?.content || "";
|
||||||
@ -73,12 +81,12 @@ async function submit() {
|
|||||||
});
|
});
|
||||||
switch (lxId.value) {
|
switch (lxId.value) {
|
||||||
case "JC": {
|
case "JC": {
|
||||||
uni.reLaunch({
|
uni.navigateTo({
|
||||||
url: "/pages/base/jc/pay/qrcode",
|
url: "/pages/base/jc/pay/qrcode",
|
||||||
});
|
});
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
uni.reLaunch({
|
uni.navigateTo({
|
||||||
url: "/pages/base/xk/qk/index?xklxId=" + lxId.value,
|
url: "/pages/base/xk/qk/index?xklxId=" + lxId.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -97,11 +97,11 @@ interface HomeMenuItem {
|
|||||||
|
|
||||||
/** 家长端特殊菜单:选课/退费/缴费需 lxId + action,后端 auth_code 映射 */
|
/** 家长端特殊菜单:选课/退费/缴费需 lxId + action,后端 auth_code 映射 */
|
||||||
const JZD_SPECIAL_MENU: Record<string, { lxId: string; action: string }> = {
|
const JZD_SPECIAL_MENU: Record<string, { lxId: string; action: string }> = {
|
||||||
"school-xqkxk": { lxId: "962488654", action: "jf" }, // 兴趣课选课
|
"910010": { lxId: "962488654", action: "jf" }, // 兴趣课选课
|
||||||
"school-jlbxk": { lxId: "816059832", action: "jf" }, // 俱乐部选课
|
"910011": { lxId: "816059832", action: "jf" }, // 俱乐部选课
|
||||||
"school-jcjf": { lxId: "JC", action: "jf" }, // 就餐报名
|
"910012": { lxId: "JC", action: "jf" }, // 就餐报名
|
||||||
"school-xqk-tf": { lxId: "962488654", action: "tf" }, // 兴趣课退费
|
"910013": { lxId: "962488654", action: "tf" }, // 兴趣课退费
|
||||||
"school-jlb-tf": { lxId: "816059832", action: "tf" }, // 俱乐部退费
|
"910014": { lxId: "816059832", action: "tf" }, // 俱乐部退费
|
||||||
};
|
};
|
||||||
|
|
||||||
// 将菜单树扁平化为家长端结构
|
// 将菜单树扁平化为家长端结构
|
||||||
@ -113,7 +113,7 @@ function flattenMenuToItems(nodes: MobileMenuTreeNode[]): HomeMenuItem[] {
|
|||||||
const icon = (node.normalCss && /^[a-zA-Z0-9_-]+$/.test(node.normalCss))
|
const icon = (node.normalCss && /^[a-zA-Z0-9_-]+$/.test(node.normalCss))
|
||||||
? `/static/base/home/${node.normalCss}.png`
|
? `/static/base/home/${node.normalCss}.png`
|
||||||
: "/static/base/home/file-text-line.png";
|
: "/static/base/home/file-text-line.png";
|
||||||
const authCode = node.authCode || "";
|
const authCode = node.id + "";
|
||||||
const special = authCode ? JZD_SPECIAL_MENU[authCode] : undefined;
|
const special = authCode ? JZD_SPECIAL_MENU[authCode] : undefined;
|
||||||
items.push({
|
items.push({
|
||||||
id: node.id,
|
id: node.id,
|
||||||
@ -160,7 +160,13 @@ 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' });
|
setGlobal({ lxId: item.lxId, action: item.action, from: 'home' });
|
||||||
PageUtils.toHome(item.lxId, item.action);
|
uni.showLoading({ title: "加载中...", mask: true });
|
||||||
|
try {
|
||||||
|
await PageUtils.toHome(item.lxId, item.action);
|
||||||
|
uni.hideLoading();
|
||||||
|
} catch (error) {
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: item.path,
|
url: item.path,
|
||||||
|
|||||||
@ -77,6 +77,7 @@ import BasicSign from "@/components/BasicSign/Sign.vue"
|
|||||||
import { useUserStore } from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
import { useDataStore } from "@/store/modules/data";
|
import { useDataStore } from "@/store/modules/data";
|
||||||
import { checkXsJcBmApi, jcXsBmJcApi } from "@/api/base/jcApi";
|
import { checkXsJcBmApi, jcXsBmJcApi } from "@/api/base/jcApi";
|
||||||
|
import { JC_PAY_REDIRECT_URL } from "@/config";
|
||||||
|
|
||||||
const signCompRef = ref<any>(null);
|
const signCompRef = ref<any>(null);
|
||||||
|
|
||||||
@ -171,14 +172,19 @@ const handleJcBzClick = (jcBz: any) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 跳转到收款码页面
|
// 跳转到支付链接(已报名未缴费时)
|
||||||
const navigateToPayment = (jcBz: any) => {
|
const navigateToPayment = (jcBz: any) => {
|
||||||
// 保存当前选中的标准到store
|
setJcBz(jcBz);
|
||||||
setJcBz(jcBz);
|
const payUrl = JC_PAY_REDIRECT_URL;
|
||||||
// 跳转到收款码预览页面
|
try {
|
||||||
uni.navigateTo({
|
if (typeof (window as any).plus !== 'undefined' && (window as any).plus.runtime?.openURL) {
|
||||||
url: "/pages/base/jc/pay/qrcode",
|
(window as any).plus.runtime.openURL(payUrl);
|
||||||
});
|
} else {
|
||||||
|
window.location.href = payUrl;
|
||||||
|
}
|
||||||
|
} catch (_e) {
|
||||||
|
window.location.href = payUrl;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 跳转到收款码页面
|
// 跳转到收款码页面
|
||||||
@ -221,10 +227,17 @@ const goToQrCode = async (jcBz: any) => {
|
|||||||
jcBz.paidStatus = 'unpaid';
|
jcBz.paidStatus = 'unpaid';
|
||||||
// 保存当前选中的标准到store
|
// 保存当前选中的标准到store
|
||||||
setJcBz(jcBz);
|
setJcBz(jcBz);
|
||||||
// 跳转到告知书页面
|
// 报名成功后直接跳转支付链接(链接后续可改为动态配置)
|
||||||
uni.navigateTo({
|
const payUrl = JC_PAY_REDIRECT_URL;
|
||||||
url: '/pages/base/jc/pay/qrcode'
|
try {
|
||||||
});
|
if (typeof (window as any).plus !== 'undefined' && (window as any).plus.runtime?.openURL) {
|
||||||
|
(window as any).plus.runtime.openURL(payUrl);
|
||||||
|
} else {
|
||||||
|
window.location.href = payUrl;
|
||||||
|
}
|
||||||
|
} catch (_e) {
|
||||||
|
window.location.href = payUrl;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
uni.hideLoading();
|
uni.hideLoading();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -246,11 +259,14 @@ const goToQrCode = async (jcBz: any) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 返回首页
|
// 返回(有页面栈则返回上一页,否则回首页)
|
||||||
const goHome = () => {
|
const goHome = () => {
|
||||||
uni.reLaunch({
|
const pages = getCurrentPages();
|
||||||
url: '/pages/base/home/index'
|
if (pages.length > 1) {
|
||||||
});
|
uni.navigateBack();
|
||||||
|
} else {
|
||||||
|
uni.reLaunch({ url: '/pages/base/home/index' });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 页面卸载前清除定时器
|
// 页面卸载前清除定时器
|
||||||
|
|||||||
@ -47,7 +47,8 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch } from "vue";
|
||||||
import { checkXsXkApi, getXsXkListApi } from "@/api/base/xkApi";
|
import dayjs from "dayjs";
|
||||||
|
import { getXsXkListApi } from "@/api/base/xkApi";
|
||||||
import { useUserStore } from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
import { useDataStore } from "@/store/modules/data";
|
import { useDataStore } from "@/store/modules/data";
|
||||||
|
|
||||||
@ -83,6 +84,23 @@ const goToWks = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从多个选课中优先选择处于选课时间段的(xkkstime <= now < xkjstime)
|
||||||
|
* @param list 选课列表
|
||||||
|
* @returns 优先选中的选课,若无则返回第一个
|
||||||
|
*/
|
||||||
|
const pickPreferredXk = (list: any[]): any => {
|
||||||
|
if (!list || list.length === 0) return null;
|
||||||
|
if (list.length === 1) return list[0];
|
||||||
|
const now = dayjs().valueOf();
|
||||||
|
const inRange = list.find((xk: any) => {
|
||||||
|
const xkkstime = xk?.xkkstime ? dayjs(xk.xkkstime).valueOf() : 0;
|
||||||
|
const xkjstime = xk?.xkjstime ? dayjs(xk.xkjstime).valueOf() : Infinity;
|
||||||
|
return now >= xkkstime && now < xkjstime;
|
||||||
|
});
|
||||||
|
return inRange ?? list[0];
|
||||||
|
};
|
||||||
|
|
||||||
// 加载选课列表
|
// 加载选课列表
|
||||||
const loadXkList = async () => {
|
const loadXkList = async () => {
|
||||||
uni.showLoading({
|
uni.showLoading({
|
||||||
@ -97,7 +115,8 @@ const loadXkList = async () => {
|
|||||||
const res = await getXsXkListApi(params);
|
const res = await getXsXkListApi(params);
|
||||||
if (res.resultCode === 1 && res.result && res.result.length) {
|
if (res.resultCode === 1 && res.result && res.result.length) {
|
||||||
xkList.value = res.result;
|
xkList.value = res.result;
|
||||||
switchXk(res.result[0]);
|
const preferred = pickPreferredXk(res.result);
|
||||||
|
switchXk(preferred ?? res.result[0]);
|
||||||
} else {
|
} else {
|
||||||
xkList.value = [];
|
xkList.value = [];
|
||||||
switchXk({});
|
switchXk({});
|
||||||
@ -113,10 +132,10 @@ const loadXkList = async () => {
|
|||||||
if (res.resultCode === 1) {
|
if (res.resultCode === 1) {
|
||||||
const result = res.result || {};
|
const result = res.result || {};
|
||||||
if (result.type === 1) {
|
if (result.type === 1) {
|
||||||
// 有待支付的选课,跳转到支付页面
|
// 有待支付的选课,跳转到支付页面(navigateTo 保留页面栈,支持浏览器返回)
|
||||||
setData(result);
|
setData(result);
|
||||||
uni.reLaunch({
|
uni.navigateTo({
|
||||||
url: "/pages/base/xk/pay/index",
|
url: "/pages/base/xk/pay/index?xklxId=" + props.xklxId,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
} else if (result.type === 2 || result.type === 3) {
|
} else if (result.type === 2 || result.type === 3) {
|
||||||
@ -134,7 +153,8 @@ const loadXkList = async () => {
|
|||||||
|
|
||||||
const initXkList = (list: any) => {
|
const initXkList = (list: any) => {
|
||||||
xkList.value = list;
|
xkList.value = list;
|
||||||
switchXk(xkList.value[0]);
|
const preferred = pickPreferredXk(list);
|
||||||
|
switchXk(preferred ?? list[0] ?? {});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="register-info">
|
<view class="register-info">
|
||||||
<text>报名情况:</text>
|
<text>报名情况:</text>
|
||||||
<text class="register-count">{{ xkkc.hasNum || 0 }}</text>
|
<text class="register-count">{{ getDisplayHasNum(xkkc) }}</text>
|
||||||
<text> | {{ xkkc.maxNum || 0 }}</text>
|
<text> | {{ xkkc.maxNum || 0 }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="study-time-info" v-if="xkkc.studyTime">
|
<view class="study-time-info" v-if="xkkc.studyTime">
|
||||||
@ -45,10 +45,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch, computed } from "vue";
|
||||||
import { useDataStore } from "@/store/modules/data";
|
import { useDataStore } from "@/store/modules/data";
|
||||||
const { setKcData, getQk } = useDataStore();
|
const { setKcData, getQk } = useDataStore();
|
||||||
|
|
||||||
|
// 选课开始时间未到时,hasNum 显示为 0
|
||||||
|
const isXkStarted = computed(() => {
|
||||||
|
const xkkstime = props.xk?.xkkstime;
|
||||||
|
if (!xkkstime) return true;
|
||||||
|
return new Date().getTime() >= new Date(xkkstime).getTime();
|
||||||
|
});
|
||||||
|
const getDisplayHasNum = (xkkc: any) => (isXkStarted.value ? (xkkc?.hasNum ?? 0) : 0);
|
||||||
|
const getEffectiveHasNum = (xkkc: any) => (isXkStarted.value ? (xkkc?.hasNum ?? 0) : 0);
|
||||||
|
|
||||||
// 接收外部传入属性并设置默认值
|
// 接收外部传入属性并设置默认值
|
||||||
const props = withDefaults(defineProps<{
|
const props = withDefaults(defineProps<{
|
||||||
xk: any,
|
xk: any,
|
||||||
@ -80,9 +89,9 @@ const toggleSelection = (xkkc: any) => {
|
|||||||
(id: string) => id !== xkkc.id
|
(id: string) => id !== xkkc.id
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// 选择课程时的验证逻辑
|
// 选择课程时的验证逻辑(选课未开始前 hasNum 按 0 处理)
|
||||||
const maxNum = xkkc.maxNum || 0;
|
const maxNum = xkkc.maxNum || 0;
|
||||||
const hasNum = xkkc.hasNum || 0;
|
const hasNum = getEffectiveHasNum(xkkc);
|
||||||
|
|
||||||
if (maxNum <= hasNum) {
|
if (maxNum <= hasNum) {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
|
|||||||
@ -75,13 +75,14 @@
|
|||||||
<view class="divider"></view>
|
<view class="divider"></view>
|
||||||
|
|
||||||
<view class="content-section">
|
<view class="content-section">
|
||||||
<template v-if="teachingPlan && teachingPlan.length > 0">
|
<template v-if="teachingPlanList.length > 0">
|
||||||
<view
|
<view
|
||||||
v-for="(phase, index) in teachingPlan"
|
v-for="(phase, index) in teachingPlanList"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="teaching-phase"
|
class="teaching-phase"
|
||||||
>
|
>
|
||||||
<text>{{ phase }}</text>
|
<text class="phase-title">{{ phase.jhjd }}</text>
|
||||||
|
<rich-text v-if="phase.jhnr" :nodes="phase.jhnr" class="phase-content"></rich-text>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@ -92,6 +93,24 @@
|
|||||||
</template>
|
</template>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 相关教学附件 -->
|
||||||
|
<view class="info-card" v-if="attachmentList.length > 0">
|
||||||
|
<view class="card-title">相关教学附件</view>
|
||||||
|
<view class="divider"></view>
|
||||||
|
<view class="attachment-list">
|
||||||
|
<view
|
||||||
|
v-for="(att, index) in attachmentList"
|
||||||
|
:key="index"
|
||||||
|
class="attachment-item"
|
||||||
|
@click="openAttachment(att)"
|
||||||
|
>
|
||||||
|
<u-icon name="file-text" size="20" color="#2879ff"></u-icon>
|
||||||
|
<text class="attachment-name">{{ att.name }}</text>
|
||||||
|
<u-icon name="arrow-right" size="14" color="#c0c4cc"></u-icon>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<template #bottom>
|
<template #bottom>
|
||||||
<view class="white-bg-color py-5">
|
<view class="white-bg-color py-5">
|
||||||
@ -111,14 +130,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed } from "vue";
|
import { ref, computed, onMounted } from "vue";
|
||||||
import { navigateBack } from "@/utils/uniapp";
|
import { navigateBack } from "@/utils/uniapp";
|
||||||
import { useDataStore } from "@/store/modules/data";
|
import { useDataStore } from "@/store/modules/data";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { imagUrl } from "@/utils";
|
import { imagUrl } from "@/utils";
|
||||||
import { kcjhFindKcjhByKcIdApi } from "@/api/base/server";
|
import { getXkkcDetailByIdApi } from "@/api/base/xkApi";
|
||||||
|
|
||||||
// 定义课程数据类型
|
// 定义课程数据类型(yfzc_xkkc 表字段)
|
||||||
interface CourseData {
|
interface CourseData {
|
||||||
id?: string;
|
id?: string;
|
||||||
kcmc?: string;
|
kcmc?: string;
|
||||||
@ -128,33 +147,76 @@ interface CourseData {
|
|||||||
studyTime?: string;
|
studyTime?: string;
|
||||||
kcjsms?: string;
|
kcjsms?: string;
|
||||||
jxll?: string;
|
jxll?: string;
|
||||||
|
jxjh?: string;
|
||||||
|
fileUrl?: string;
|
||||||
|
fileName?: string;
|
||||||
|
fileFormat?: string;
|
||||||
remark?: string;
|
remark?: string;
|
||||||
lxtp?: string;
|
lxtp?: string;
|
||||||
[key: string]: any; // 允许其他字段
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useData = useDataStore();
|
const useData = useDataStore();
|
||||||
const { kcData } = storeToRefs(useData);
|
const { kcData } = storeToRefs(useData);
|
||||||
|
|
||||||
// 教学计划 - 此处假设没有具体教学计划字段,将备注内容拆分为教学计划
|
// 从 getXkkcDetailById 接口获取的完整 xkkc 数据
|
||||||
const teachingPlan = ref<string[]>([]);
|
const xkkcDetail = ref<CourseData>({});
|
||||||
|
|
||||||
const courseData = kcData.value as CourseData;
|
// 将 HTML 中 img 的 src 转为完整 URL,供 rich-text 正确加载图片
|
||||||
if (courseData && courseData.id) {
|
const processHtmlForRichText = (html: string): string => {
|
||||||
kcjhFindKcjhByKcIdApi({
|
if (!html) return "";
|
||||||
xkkcId: courseData.id,
|
return html.replace(/<img\s+([^>]*?)src=["']([^"']+)["']([^>]*)>/gi, (_, before, src, after) => {
|
||||||
}).then((res) => {
|
const fullSrc = imagUrl(src);
|
||||||
if (res.resultCode == 1) {
|
const style = 'style="max-width:100%;height:auto"';
|
||||||
teachingPlan.value = res.result.map(
|
return `<img ${before}src="${fullSrc}" ${style}${after}>`;
|
||||||
(item: any) => item.jhjd + ":" + item.jhms
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// 教学计划 - 从 xkkc.jxjh 解析,保留 HTML(含图片)用 rich-text 展示
|
||||||
|
// 格式: [{"value":{"jhjd":"第1次课","jhnr":"<p><img src=\"...\">内容</p>"}}, ...]
|
||||||
|
const teachingPlanList = computed(() => {
|
||||||
|
const jxjh = xkkcDetail.value.jxjh;
|
||||||
|
if (!jxjh) return [];
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(jxjh);
|
||||||
|
if (Array.isArray(parsed)) {
|
||||||
|
return parsed
|
||||||
|
.map((item: any) => {
|
||||||
|
const v = item?.value ?? item;
|
||||||
|
const jhjd = v.jhjd || "";
|
||||||
|
const rawJhnr = v.jhnr || v.jhms || "";
|
||||||
|
const jhnr = rawJhnr ? processHtmlForRichText(rawJhnr) : "";
|
||||||
|
return { jhjd, jhnr };
|
||||||
|
})
|
||||||
|
.filter((p: { jhjd: string; jhnr: string }) => p.jhjd || p.jhnr);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// 非 JSON,忽略
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
|
||||||
|
// 教学相关附件 - 从 xkkc.fileUrl、fileName、fileFormat 解析
|
||||||
|
const attachmentList = computed(() => {
|
||||||
|
const fileUrl = xkkcDetail.value.fileUrl || "";
|
||||||
|
const fileName = xkkcDetail.value.fileName || "";
|
||||||
|
const urls = fileUrl.split(",").map((s) => s.trim()).filter(Boolean);
|
||||||
|
const names = fileName.split(";").map((s) => s.trim());
|
||||||
|
return urls.map((url, i) => ({ url, name: names[i] || `附件${i + 1}` }));
|
||||||
|
});
|
||||||
|
|
||||||
|
// 打开附件(通过 webView 打开或下载)
|
||||||
|
const openAttachment = (att: { url: string; name: string }) => {
|
||||||
|
const fullUrl = imagUrl(att.url);
|
||||||
|
if (!fullUrl) return;
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/system/webView/webView?url=" + encodeURIComponent(fullUrl),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// 课程详情数据
|
// 课程详情数据
|
||||||
const courseDetail = computed(() => {
|
const courseDetail = computed(() => {
|
||||||
const data = (kcData.value as CourseData) || {};
|
const data = xkkcDetail.value || {};
|
||||||
return {
|
return {
|
||||||
id: data.id || "",
|
id: data.id || "",
|
||||||
title: data.kcmc || "暂无课程名称",
|
title: data.kcmc || "暂无课程名称",
|
||||||
@ -162,28 +224,41 @@ const courseDetail = computed(() => {
|
|||||||
location: data.kcdd || "暂无地点信息",
|
location: data.kcdd || "暂无地点信息",
|
||||||
price: data.kcje || 0,
|
price: data.kcje || 0,
|
||||||
studyTime: data.studyTime || "暂无上课时间",
|
studyTime: data.studyTime || "暂无上课时间",
|
||||||
lxtp: imagUrl(data.lxtp || ''), // 使用imagUrl处理图片路径
|
lxtp: imagUrl(data.lxtp || ""),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// 教师信息
|
// 教师信息
|
||||||
const teacherInfo = computed(() => {
|
const teacherInfo = computed(() => {
|
||||||
const data = (kcData.value as CourseData) || {};
|
const data = xkkcDetail.value || {};
|
||||||
|
const teacherAvatars = data.jstx ? data.jstx.split(",").map((a: string) => a.trim()) : [];
|
||||||
// 处理多个教师头像的情况
|
|
||||||
const teacherAvatars = data.jstx ? data.jstx.split(',').map((avatar: string) => avatar.trim()) : [];
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: data.jsName || "暂无教师信息",
|
name: data.jsName || "暂无教师信息",
|
||||||
avatar: teacherAvatars.length > 0 ? imagUrl(teacherAvatars[0]) : '', // 只取第一个头像
|
avatar: teacherAvatars.length > 0 ? imagUrl(teacherAvatars[0]) : "",
|
||||||
introduction: data.kcjsms || "暂无教师介绍",
|
introduction: data.kcjsms || "暂无教师介绍",
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// 教学理念
|
// 教学理念 - 从 xkkc.jxll
|
||||||
const teachingPhilosophy = computed(() => {
|
const teachingPhilosophy = computed(() => xkkcDetail.value.jxll || "暂无教学理念信息");
|
||||||
const data = (kcData.value as CourseData) || {};
|
|
||||||
return data.jxll || "暂无教学理念信息";
|
// 进入详情页时,通过 getXkkcDetailById 获取完整 xkkc(含 jxll、jxjh、fileUrl 等)
|
||||||
|
onMounted(() => {
|
||||||
|
const data = kcData.value as CourseData;
|
||||||
|
const id = data?.id;
|
||||||
|
if (id) {
|
||||||
|
getXkkcDetailByIdApi(id).then((res) => {
|
||||||
|
if (res.resultCode === 1 && res.result) {
|
||||||
|
xkkcDetail.value = res.result;
|
||||||
|
} else {
|
||||||
|
xkkcDetail.value = { ...data };
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
xkkcDetail.value = { ...data };
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
xkkcDetail.value = { ...data } || {};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -351,12 +426,26 @@ const teachingPhilosophy = computed(() => {
|
|||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
|
|
||||||
.teaching-phase {
|
.teaching-phase {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.phase-title {
|
||||||
|
display: block;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phase-content {
|
||||||
|
display: block;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
.empty-data {
|
.empty-data {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -372,6 +461,26 @@ const teachingPhilosophy = computed(() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.attachment-list {
|
||||||
|
.attachment-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 0;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.attachment-name {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.bottom-action {
|
.bottom-action {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
|
|||||||
@ -30,8 +30,8 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="action-buttons">
|
<view class="action-buttons">
|
||||||
<view class="cancel-btn" @click="cancelRegistration">
|
<view class="cancel-btn" @click="goBack">
|
||||||
取消报名
|
返回
|
||||||
</view>
|
</view>
|
||||||
<view class="pay-btn" :class="{ 'pay-btn--disabled': isPaySubmitting }" @click="payNow">
|
<view class="pay-btn" :class="{ 'pay-btn--disabled': isPaySubmitting }" @click="payNow">
|
||||||
{{ isPaySubmitting ? '支付中...' : '立即支付' }}
|
{{ isPaySubmitting ? '支付中...' : '立即支付' }}
|
||||||
@ -54,9 +54,6 @@ const { getQk } = useDataStore();
|
|||||||
// 为支付按钮创建防抖函数和状态
|
// 为支付按钮创建防抖函数和状态
|
||||||
const { isProcessing: isPaySubmitting, debounce: payDebounce } = useDebounce(2000);
|
const { isProcessing: isPaySubmitting, debounce: payDebounce } = useDebounce(2000);
|
||||||
|
|
||||||
// 为取消报名按钮创建防抖函数和状态
|
|
||||||
const { isProcessing: isCancelSubmitting, debounce: cancelDebounce } = useDebounce(2000);
|
|
||||||
|
|
||||||
const qk = ref<any>({});
|
const qk = ref<any>({});
|
||||||
// 总金额
|
// 总金额
|
||||||
const totalJe = ref(0);
|
const totalJe = ref(0);
|
||||||
@ -168,40 +165,13 @@ const startCountdown = () => {
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 返回上一页
|
// 返回首页
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
url: '/pages/base/home/index'
|
url: '/pages/base/home/index'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 取消报名
|
|
||||||
const cancelRegistration = () => {
|
|
||||||
uni.showModal({
|
|
||||||
title: "取消报名",
|
|
||||||
content: "确定要取消报名吗?",
|
|
||||||
success: cancelDebounce(async (res) => {
|
|
||||||
if (res.confirm) {
|
|
||||||
try {
|
|
||||||
const res = await jzXkCancelApi({
|
|
||||||
xsId: qk.value.xsId,
|
|
||||||
xkId: qk.value.xkId
|
|
||||||
});
|
|
||||||
if (res.resultCode === 1) {
|
|
||||||
uni.showLoading({ title: "取消报名中,请稍后..." });
|
|
||||||
} else {
|
|
||||||
uni.showToast({ title: res.message, icon: "none" });
|
|
||||||
goBack();
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
goBack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 立即支付
|
// 立即支付
|
||||||
const payNow = payDebounce(async () => {
|
const payNow = payDebounce(async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -74,9 +74,12 @@ const checkEnrollmentStatus = (xk: any) => {
|
|||||||
const endTime = new Date(xk.xkjstime).getTime();
|
const endTime = new Date(xk.xkjstime).getTime();
|
||||||
|
|
||||||
if (now > endTime) {
|
if (now > endTime) {
|
||||||
// 选课已结束,跳转到结束页面
|
// 选课已结束,用 redirectTo 替换当前页,避免浏览器返回时回到选课页
|
||||||
|
console.log('[qk/index] 跳转 yjz,xk 数据:', xk);
|
||||||
|
console.log('[qk/index] xk 字段:', { xkmc: xk?.xkmc, xkkstime: xk?.xkkstime, xkjstime: xk?.xkjstime });
|
||||||
const courseInfo = encodeURIComponent(JSON.stringify(xk));
|
const courseInfo = encodeURIComponent(JSON.stringify(xk));
|
||||||
uni.navigateTo({
|
console.log('[qk/index] courseInfo 长度:', courseInfo.length);
|
||||||
|
uni.redirectTo({
|
||||||
url: `/pages/base/xk/qk/yjz?courseInfo=${courseInfo}`
|
url: `/pages/base/xk/qk/yjz?courseInfo=${courseInfo}`
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
@ -119,11 +122,14 @@ const changeXkkc = (ids: any) => {
|
|||||||
selectedXkkcIds.value = ids;
|
selectedXkkcIds.value = ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 回到首页
|
// 返回(有页面栈则返回上一页,否则回首页)
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
uni.reLaunch({
|
const pages = getCurrentPages();
|
||||||
url: '/pages/base/home/index'
|
if (pages.length > 1) {
|
||||||
});
|
uni.navigateBack();
|
||||||
|
} else {
|
||||||
|
uni.reLaunch({ url: '/pages/base/home/index' });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提交选课
|
// 提交选课
|
||||||
|
|||||||
@ -59,9 +59,11 @@ const checkEnrollmentStatus = (xk: any) => {
|
|||||||
const endTime = new Date(xk.xkjstime).getTime();
|
const endTime = new Date(xk.xkjstime).getTime();
|
||||||
|
|
||||||
if (now > endTime) {
|
if (now > endTime) {
|
||||||
// 选课已结束,跳转到结束页面
|
// 选课已结束,用 redirectTo 替换当前页,避免浏览器返回时回到选课页
|
||||||
|
console.log('[qk/jlb] 跳转yjz,传入的xk:', xk);
|
||||||
|
console.log('[qk/jlb] xk.xkmc:', xk?.xkmc, 'xk.xkkstime:', xk?.xkkstime, 'xk.xkjstime:', xk?.xkjstime);
|
||||||
const courseInfo = encodeURIComponent(JSON.stringify(xk));
|
const courseInfo = encodeURIComponent(JSON.stringify(xk));
|
||||||
uni.navigateTo({
|
uni.redirectTo({
|
||||||
url: `/pages/base/xk/qk/yjz?courseInfo=${courseInfo}`
|
url: `/pages/base/xk/qk/yjz?courseInfo=${courseInfo}`
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -53,11 +53,14 @@ const { getData } = useDataStore();
|
|||||||
|
|
||||||
const title = ref("");
|
const title = ref("");
|
||||||
|
|
||||||
// 返回首页
|
// 返回(有页面栈则返回上一页,否则回首页)
|
||||||
const goHome = () => {
|
const goHome = () => {
|
||||||
uni.reLaunch({
|
const pages = getCurrentPages();
|
||||||
url: "/pages/base/home/index"
|
if (pages.length > 1) {
|
||||||
});
|
uni.navigateBack();
|
||||||
|
} else {
|
||||||
|
uni.reLaunch({ url: "/pages/base/home/index" });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onLoad((options:any) => {
|
onLoad((options:any) => {
|
||||||
|
|||||||
@ -60,7 +60,10 @@ const checkEnrollmentStatus = (xk: any) => {
|
|||||||
|
|
||||||
if (now > endTime) {
|
if (now > endTime) {
|
||||||
// 选课已结束,跳转到结束页面
|
// 选课已结束,跳转到结束页面
|
||||||
|
console.log('[qk/xqk] 跳转 yjz,xk 数据:', xk);
|
||||||
|
console.log('[qk/xqk] xk 字段:', { xkmc: xk?.xkmc, xkkstime: xk?.xkkstime, xkjstime: xk?.xkjstime });
|
||||||
const courseInfo = encodeURIComponent(JSON.stringify(xk));
|
const courseInfo = encodeURIComponent(JSON.stringify(xk));
|
||||||
|
console.log('[qk/xqk] courseInfo 长度:', courseInfo.length);
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/base/xk/qk/yjz?courseInfo=${courseInfo}`
|
url: `/pages/base/xk/qk/yjz?courseInfo=${courseInfo}`
|
||||||
});
|
});
|
||||||
|
|||||||
@ -72,8 +72,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted, onUnmounted } from 'vue';
|
||||||
import { onLoad } from '@dcloudio/uni-app';
|
import { onLoad, onBackPress } from '@dcloudio/uni-app';
|
||||||
|
|
||||||
// 页面参数
|
// 页面参数
|
||||||
const courseInfo = ref<any>(null);
|
const courseInfo = ref<any>(null);
|
||||||
@ -81,14 +81,46 @@ const courseInfo = ref<any>(null);
|
|||||||
onLoad((options) => {
|
onLoad((options) => {
|
||||||
// 接收传递过来的选课信息
|
// 接收传递过来的选课信息
|
||||||
if (options?.courseInfo) {
|
if (options?.courseInfo) {
|
||||||
|
const raw = options.courseInfo;
|
||||||
try {
|
try {
|
||||||
courseInfo.value = JSON.parse(decodeURIComponent(options.courseInfo));
|
// 框架可能已对 URL 参数自动解码,先尝试直接解析(避免 decodeURIComponent 对已解码字符串报 URI malformed)
|
||||||
} catch (error) {
|
courseInfo.value = JSON.parse(raw);
|
||||||
console.error('解析选课信息失败:', error);
|
} catch (_e1) {
|
||||||
|
try {
|
||||||
|
courseInfo.value = JSON.parse(decodeURIComponent(raw));
|
||||||
|
} catch (e2) {
|
||||||
|
console.error('解析选课信息失败:', e2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 返回(始终回到首页,避免返回到选课界面陷入循环)
|
||||||
|
const goBack = () => {
|
||||||
|
uni.reLaunch({ url: '/pages/base/home/index' });
|
||||||
|
};
|
||||||
|
|
||||||
|
// 拦截导航栏返回、App 物理返回键
|
||||||
|
onBackPress(() => {
|
||||||
|
goBack();
|
||||||
|
return true; // 阻止默认返回
|
||||||
|
});
|
||||||
|
|
||||||
|
// H5:拦截浏览器返回键(onBackPress 在 H5 不支持浏览器返回)
|
||||||
|
let popstateHandler: (() => void) | null = null;
|
||||||
|
onMounted(() => {
|
||||||
|
if (typeof window !== 'undefined' && window.history?.pushState) {
|
||||||
|
popstateHandler = () => goBack();
|
||||||
|
window.history.pushState(null, '', document.URL);
|
||||||
|
window.addEventListener('popstate', popstateHandler);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (typeof window !== 'undefined' && popstateHandler) {
|
||||||
|
window.removeEventListener('popstate', popstateHandler);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 格式化时间
|
// 格式化时间
|
||||||
const formatTime = (time: string) => {
|
const formatTime = (time: string) => {
|
||||||
if (!time) return '未设置';
|
if (!time) return '未设置';
|
||||||
@ -102,13 +134,6 @@ const formatTime = (time: string) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 返回首页
|
|
||||||
const goBack = () => {
|
|
||||||
uni.reLaunch({
|
|
||||||
url: '/pages/base/home/index'
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 刷新页面
|
// 刷新页面
|
||||||
const refreshPage = () => {
|
const refreshPage = () => {
|
||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
|
|||||||
@ -32,11 +32,12 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 附件预览 -->
|
<!-- 附件预览 -->
|
||||||
<view v-if="taskInfo.fileUrl && taskInfo.fileName" class="file-preview mt-15">
|
<view v-if="taskInfo.fileUrl" class="file-preview mt-15">
|
||||||
<view class="file-preview-item">
|
<BasicFilePreview
|
||||||
<text class="file-label">附件:</text>
|
:file-url="taskInfo.fileUrl"
|
||||||
<text class="file-name" @click="previewFile(taskInfo.fileUrl)">{{ taskInfo.fileName }}</text>
|
:file-name="taskInfo.fileName"
|
||||||
</view>
|
:file-format="taskInfo.fileFormat"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@ -77,7 +78,7 @@
|
|||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted } from 'vue';
|
||||||
import { onLoad } from '@dcloudio/uni-app';
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
import { zpFindDetailByIdApi } from "@/api/base/server";
|
import { zpFindDetailByIdApi } from "@/api/base/server";
|
||||||
import { imagUrl } from "@/utils";
|
import BasicFilePreview from "@/components/BasicFile/preview.vue";
|
||||||
|
|
||||||
interface TaskInfo {
|
interface TaskInfo {
|
||||||
id?: string;
|
id?: string;
|
||||||
@ -87,6 +88,7 @@ interface TaskInfo {
|
|||||||
zpjstime?: string;
|
zpjstime?: string;
|
||||||
fileUrl?: string;
|
fileUrl?: string;
|
||||||
fileName?: string;
|
fileName?: string;
|
||||||
|
fileFormat?: string;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,21 +191,6 @@ const getTaskTypeText = (type?: string) => {
|
|||||||
};
|
};
|
||||||
return typeMap[type || ''] || '未知类型';
|
return typeMap[type || ''] || '未知类型';
|
||||||
};
|
};
|
||||||
|
|
||||||
// 预览文件
|
|
||||||
const previewFile = (fileUrl: string) => {
|
|
||||||
if (!fileUrl) return;
|
|
||||||
const fullUrl = imagUrl(fileUrl);
|
|
||||||
const fileExt = fileUrl.split('.').pop()?.toLowerCase();
|
|
||||||
if (['jpg', 'jpeg', 'png', 'gif', 'webp'].includes(fileExt || '')) {
|
|
||||||
uni.previewImage({
|
|
||||||
urls: [fullUrl],
|
|
||||||
current: fullUrl
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
uni.showToast({ title: '请下载查看', icon: 'none' });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@ -391,36 +378,11 @@ const previewFile = (fileUrl: string) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 文件预览样式
|
// 文件预览样式(BasicFilePreview 组件内部样式,此处仅保留外层容器)
|
||||||
.file-preview {
|
.file-preview {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
background: #f8f9fa;
|
background: #f8f9fa;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
border: 1px solid #e9ecef;
|
border: 1px solid #e9ecef;
|
||||||
|
|
||||||
.file-preview-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.file-label {
|
|
||||||
color: #666;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-right: 8px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-name {
|
|
||||||
color: #4e73df;
|
|
||||||
font-size: 14px;
|
|
||||||
text-decoration: underline;
|
|
||||||
cursor: pointer;
|
|
||||||
word-break: break-all;
|
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
color: #2e59d9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -354,7 +354,7 @@ const generateFormSchema = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if (zplx.zpfl === "scsp") {
|
} else if (zplx.zpfl === "scsp") {
|
||||||
// 上传视频
|
// 上传视频(视频大小限制 50MB)
|
||||||
componentConfig = {
|
componentConfig = {
|
||||||
component: "ImageVideoUpload",
|
component: "ImageVideoUpload",
|
||||||
componentProps: {
|
componentProps: {
|
||||||
@ -363,7 +363,13 @@ const generateFormSchema = () => {
|
|||||||
enableFile: false,
|
enableFile: false,
|
||||||
maxVideoCount: 30,
|
maxVideoCount: 30,
|
||||||
uploadApi: attachmentUpload,
|
uploadApi: attachmentUpload,
|
||||||
compressConfig: COMPRESS_PRESETS.medium,
|
compressConfig: {
|
||||||
|
...COMPRESS_PRESETS.medium,
|
||||||
|
video: {
|
||||||
|
...COMPRESS_PRESETS.medium.video,
|
||||||
|
maxSize: 50 * 1024 * 1024
|
||||||
|
}
|
||||||
|
},
|
||||||
videoList: formData.value[fieldName] || [],
|
videoList: formData.value[fieldName] || [],
|
||||||
showSectionTitle: false
|
showSectionTitle: false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import { defineStore } from "pinia";
|
|||||||
import type { MobileMenuTreeNode } from "@/api/system/menu";
|
import type { MobileMenuTreeNode } from "@/api/system/menu";
|
||||||
|
|
||||||
export const useMenuStore = defineStore({
|
export const useMenuStore = defineStore({
|
||||||
id: "app-Menu",
|
id: "app-Menu-jzd",
|
||||||
state: () => ({
|
state: () => ({
|
||||||
/** 树形菜单数据,持久化到 localStorage key: app-Menu */
|
/** 树形菜单数据,持久化到 localStorage key: app-Menu-jzd(家长端,与教师端 app-Menu-jsd 区分,避免同域下菜单互相覆盖) */
|
||||||
mobileMenu: [] as MobileMenuTreeNode[],
|
mobileMenu: [] as MobileMenuTreeNode[],
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { checkXsXkApi, checkXkTfApi } from "@/api/base/xkApi";
|
import { checkXsXkWithGzsApi, checkXkTfApi } from "@/api/base/xkApi";
|
||||||
import { useUserStore } from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
import { useDataStore } from "@/store/modules/data";
|
import { useDataStore } from "@/store/modules/data";
|
||||||
const userStore = useUserStore();
|
const userStore = useUserStore();
|
||||||
@ -75,7 +75,7 @@ export const PageUtils = {
|
|||||||
* @param xklxId
|
* @param xklxId
|
||||||
*/
|
*/
|
||||||
async checkQkLogic(xklxId: string) {
|
async checkQkLogic(xklxId: string) {
|
||||||
const res: any = await checkXsXkApi({
|
const res: any = await checkXsXkWithGzsApi({
|
||||||
xsId: userStore.getCurXs.id,
|
xsId: userStore.getCurXs.id,
|
||||||
njmcId: userStore.getCurXs.njmcId,
|
njmcId: userStore.getCurXs.njmcId,
|
||||||
xklxId: xklxId,
|
xklxId: xklxId,
|
||||||
@ -94,35 +94,35 @@ export const PageUtils = {
|
|||||||
const result = res.result || {};
|
const result = res.result || {};
|
||||||
// 记录到缓存数据中
|
// 记录到缓存数据中
|
||||||
dataStore.setQk(result);
|
dataStore.setQk(result);
|
||||||
// 状态判断
|
// 状态判断(使用 navigateTo 保留页面栈,支持浏览器返回)
|
||||||
switch (result.xsXkStatus) {
|
switch (result.xsXkStatus) {
|
||||||
case 'WFB': { // KQK可抢课
|
case 'WFB': { // 未开放
|
||||||
uni.reLaunch({
|
uni.navigateTo({
|
||||||
url: "/pages/base/xk/qk/wks?xklxId=" + xklxId,
|
url: "/pages/base/xk/qk/wks?xklxId=" + xklxId,
|
||||||
});
|
});
|
||||||
} break;
|
} break;
|
||||||
case 'KQK': { // KQK可抢课
|
case 'KQK': { // 可抢课-告知书
|
||||||
uni.reLaunch({
|
uni.navigateTo({
|
||||||
url: "/pages/base/gzs/index?lxId=" + xklxId,
|
url: "/pages/base/gzs/index?lxId=" + xklxId,
|
||||||
});
|
});
|
||||||
} break;
|
} break;
|
||||||
case 'QKZ': { // QKZ抢课中
|
case 'QKZ': { // 抢课中
|
||||||
uni.reLaunch({
|
uni.navigateTo({
|
||||||
url: "/pages/base/xk/qk/index?xklxId=" + xklxId,
|
url: "/pages/base/xk/qk/index?xklxId=" + xklxId,
|
||||||
});
|
});
|
||||||
} break;
|
} break;
|
||||||
case 'YQK': { // YQK已选课
|
case 'YQK': { // 已选课
|
||||||
uni.reLaunch({
|
uni.navigateTo({
|
||||||
url: "/pages/base/xk/pay/index?xklxId=" + xklxId,
|
url: "/pages/base/xk/pay/index?xklxId=" + xklxId,
|
||||||
});
|
});
|
||||||
} break;
|
} break;
|
||||||
case 'DZF': { // DZF待支付
|
case 'DZF': { // 待支付
|
||||||
uni.reLaunch({
|
uni.navigateTo({
|
||||||
url: "/pages/base/xk/pay/index?xklxId=" + xklxId,
|
url: "/pages/base/xk/pay/index?xklxId=" + xklxId,
|
||||||
});
|
});
|
||||||
} break;
|
} break;
|
||||||
case 'YZF': { // YZF已支付
|
case 'YZF': { // 已支付
|
||||||
uni.reLaunch({
|
uni.navigateTo({
|
||||||
url: "/pages/base/xk/pay/success?xklxId=" + xklxId,
|
url: "/pages/base/xk/pay/success?xklxId=" + xklxId,
|
||||||
});
|
});
|
||||||
} break;
|
} break;
|
||||||
@ -166,9 +166,9 @@ export const PageUtils = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 判断就餐逻辑
|
// 判断就餐逻辑(使用 navigateTo 保留页面栈,支持浏览器返回)
|
||||||
async checkJcLogic() {
|
async checkJcLogic() {
|
||||||
uni.reLaunch({
|
uni.navigateTo({
|
||||||
url: "/pages/base/jc/bm",
|
url: "/pages/base/jc/bm",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@ -120,14 +120,14 @@ export function get<T = any>(
|
|||||||
} else {
|
} else {
|
||||||
if (res.resultCode) {
|
if (res.resultCode) {
|
||||||
if (res.resultCode != RESULT_CODE_NOT_LOGIN) {
|
if (res.resultCode != RESULT_CODE_NOT_LOGIN) {
|
||||||
showToast(res.message || "接口异常");
|
showToast(res.message || "接口异常1");
|
||||||
reject(res);
|
reject(res);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (res.rows) {
|
if (res.rows) {
|
||||||
resolve(res);
|
resolve(res);
|
||||||
} else {
|
} else {
|
||||||
showToast(res.message || "接口异常");
|
showToast(res.message || "接口异常2");
|
||||||
reject(res);
|
reject(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,14 +169,14 @@ export function post<T = any>(
|
|||||||
} else {
|
} else {
|
||||||
if (res.resultCode) {
|
if (res.resultCode) {
|
||||||
if (res.resultCode != RESULT_CODE_NOT_LOGIN) {
|
if (res.resultCode != RESULT_CODE_NOT_LOGIN) {
|
||||||
showToast(res.message || "接口异常");
|
showToast(res.message || "接口异常3");
|
||||||
reject(res);
|
reject(res);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (res.rows) {
|
if (res.rows) {
|
||||||
resolve(res);
|
resolve(res);
|
||||||
} else {
|
} else {
|
||||||
showToast(res.message || "接口异常");
|
showToast(res.message || "接口异常4");
|
||||||
reject(res);
|
reject(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,14 +216,14 @@ export function file(
|
|||||||
} else {
|
} else {
|
||||||
if (res.resultCode) {
|
if (res.resultCode) {
|
||||||
if (res.resultCode != RESULT_CODE_NOT_LOGIN) {
|
if (res.resultCode != RESULT_CODE_NOT_LOGIN) {
|
||||||
showToast(res.message || "接口异常");
|
showToast(res.message || "接口异常5");
|
||||||
reject(res);
|
reject(res);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (res.rows) {
|
if (res.rows) {
|
||||||
resolve(res);
|
resolve(res);
|
||||||
} else {
|
} else {
|
||||||
showToast(res.message || "接口异常");
|
showToast(res.message || "接口异常6");
|
||||||
reject(res);
|
reject(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user