Compare commits
90
Commits
36cda41b14
..
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7dbbfda16 | ||
|
|
fd78b504a6 | ||
|
|
a26fc1a4a7 | ||
|
|
5d31c3658b | ||
|
|
5f9a346960 | ||
|
|
7180e176eb | ||
|
|
e3a852cb43 | ||
|
|
0a51901807 | ||
|
|
8a879df4b4 | ||
|
|
18c7f7386d | ||
|
|
b5cc11ddd3 | ||
|
|
4a22470f38 | ||
|
|
6cdd8b90db | ||
|
|
cbc427e41c | ||
|
|
45a9478790 | ||
|
|
c6ce198c31 | ||
|
|
f4fe516224 | ||
|
|
80772749b2 | ||
|
|
0fa310e422 | ||
|
|
761a8fdaa4 | ||
|
|
ca69dfbe4b | ||
|
|
4042df6762 | ||
|
|
4e3a30b863 | ||
|
|
2831de027c | ||
|
|
08e3ba22c5 | ||
|
|
40f5ddf4a5 | ||
|
|
1fa822ed72 | ||
|
|
89848ba321 | ||
|
|
7fb1200528 | ||
|
|
b833a00d65 | ||
|
|
e8e9c84cdf | ||
|
|
1e99b3a082 | ||
|
|
efcc7d9603 | ||
|
|
54f8132cee | ||
|
|
ddbfac11c3 | ||
|
|
1de18aa228 | ||
|
|
799471090f | ||
|
|
ae9a961a42 | ||
|
|
db9ca707ae | ||
|
|
a7b2a673a9 | ||
|
|
d06ee397cf | ||
|
|
034744959f | ||
|
|
cf6df28e8c | ||
|
|
00d0ec8a9b | ||
|
|
56c645a75c | ||
|
|
8025b2abab | ||
|
|
c86aa03f01 | ||
|
|
22104881f1 | ||
|
|
f4c8df1950 | ||
|
|
1785e9309e | ||
|
|
da3659412d | ||
|
|
51367c48c9 | ||
|
|
41079458dc | ||
|
|
60531b339e | ||
|
|
9788e723a2 | ||
|
|
91726b87c5 | ||
|
|
6b37f0899d | ||
|
|
f4b1ef932d | ||
|
|
76e619b85d | ||
|
|
2cfc225b55 | ||
|
|
2cfa4bdc53 | ||
|
|
9e0a5d2512 | ||
|
|
589092ec62 | ||
|
|
1255ce8aa5 | ||
|
|
4dca51b0a3 | ||
|
|
8d9ad1ca51 | ||
|
|
e7cebcb00c | ||
|
|
dcade02e47 | ||
|
|
f7d44b9c27 | ||
|
|
d1a4f610d3 | ||
|
|
6b238c2d33 | ||
|
|
7c46a3487a | ||
|
|
38d13d33ce | ||
|
|
5d2d8cc9ff | ||
|
|
5af6f8c906 | ||
|
|
1e134f236c | ||
|
|
4816054b96 | ||
|
|
ea320f4e54 | ||
|
|
d44cd1516a | ||
|
|
2a1f4a2405 | ||
|
|
2532aa055c | ||
|
|
b16601baa6 | ||
|
|
8b1e9bcb41 | ||
|
|
dd9b2984b2 | ||
|
|
65b2d269c5 | ||
|
|
570e47698c | ||
|
|
71136a03a6 | ||
|
|
053063dc88 | ||
|
|
4703b22d25 | ||
|
|
df4d95993a |
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
changed 1 package, and audited 42 packages in 5s
|
||||||
|
|
||||||
|
7 packages are looking for funding
|
||||||
|
run `npm fund` for details
|
||||||
|
|
||||||
|
3 high severity vulnerabilities
|
||||||
|
|
||||||
|
Some issues need review, and may require choosing
|
||||||
|
a different dependency.
|
||||||
|
|
||||||
|
Run `npm audit` for details.
|
||||||
@@ -1,459 +1,264 @@
|
|||||||
<script >
|
<script>
|
||||||
import RootStore from "@xkit-yx/im-store-v2";
|
import version from '@/utils/version.js'
|
||||||
/** esm 版本 */
|
|
||||||
//@ts-ignore
|
|
||||||
// import { V2NIMConst, NIM } from './esmNim.js'
|
|
||||||
/** 常规版本*/
|
|
||||||
import NIM from "nim-web-sdk-ng/dist/v2/NIM_UNIAPP_SDK";
|
|
||||||
import { V2NIMConst } from "nim-web-sdk-ng/dist/esm/nim";
|
|
||||||
|
|
||||||
|
|
||||||
import {
|
|
||||||
customRedirectTo,
|
|
||||||
customReLaunch,
|
|
||||||
customSwitchTab,
|
|
||||||
} from "@/utils/im/customNavigate";
|
|
||||||
import { getMsgContentTipByType } from "@/utils/im/msg";
|
|
||||||
import { STORAGE_KEY } from "@/utils/im/constants";
|
|
||||||
import { isWxApp } from "@/utils/im/index";
|
|
||||||
/** 国际化*/
|
|
||||||
import { setLanguage } from "@/utils/im/i18n";
|
|
||||||
import BASE_URL from "@/utils/config.js"
|
|
||||||
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
/** 推送插件 */
|
|
||||||
const nimPushPlugin = uni.requireNativePlugin("NIMUniPlugin-PluginModule");
|
|
||||||
/** 音视频通话插件 */
|
|
||||||
const nimCallKit = (uni.$UIKitCallKit =
|
|
||||||
uni.requireNativePlugin("netease-CallKit"));
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
let startByNotificationId = "";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
onLaunch() {
|
globalData: {
|
||||||
// #ifdef APP-PLUS
|
plAd: true,
|
||||||
/** 关闭启动画面,锁定竖屏 */
|
dotNumber: {},
|
||||||
plus.navigator.closeSplashscreen();
|
apiHost: "https://dev-app.igandan.com/app",
|
||||||
plus.screen.lockOrientation("portrait-primary");
|
//BASE_URL='https://dev-app.igandan.com/app'
|
||||||
// #endif
|
},
|
||||||
|
onLaunch(options) {
|
||||||
/** 设置语言 (此处为了方便demo切换语言,将其存到本地,实际需根据业务情况设置)*/
|
//uni.setStorageSync('apiHost', 'value')
|
||||||
setLanguage(
|
console.log("打印options");
|
||||||
uni.getStorageSync("switchToEnglishFlag") == "en" ? "en" : "zh"
|
console.log(options);
|
||||||
);
|
|
||||||
/** 已经登录了 不用走初始化逻辑*/
|
|
||||||
if (
|
if (
|
||||||
uni?.$UIKitStore?.connectStore?.connectStatus ===
|
options &&
|
||||||
V2NIMConst.V2NIMConnectStatus.V2NIM_CONNECT_STATUS_CONNECTED
|
options.referrerInfo.extraData &&
|
||||||
|
options.referrerInfo.extraData.token
|
||||||
) {
|
) {
|
||||||
return;
|
uni.setStorageSync(
|
||||||
|
"AUTH_TOKEN_App",
|
||||||
|
options.referrerInfo.extraData.token
|
||||||
|
);
|
||||||
|
uni.setStorageSync("userInfo", options.referrerInfo.extraData.userInfo);
|
||||||
|
if(process.env.UNI_PLATFORM =="mp-weixin"){
|
||||||
|
uni.setStorageSync("app_version",version);
|
||||||
|
}else{
|
||||||
|
let app_version=options.referrerInfo.extraData.app_version?options.referrerInfo.extraData.app_version:version;
|
||||||
|
uni.setStorageSync("app_version",app_version);
|
||||||
|
};
|
||||||
|
|
||||||
|
//getApp({allowDefault: true}).globalData.apiHost = options.referrerInfo.extraData.apiHost;
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
let storage_token='';
|
options &&
|
||||||
let storage_accid='';
|
options.referrerInfo.extraData &&
|
||||||
if (process.env.UNI_PLATFORM == "h5") {
|
options.referrerInfo.extraData.targetPath
|
||||||
if (window.location.href.indexOf('dev') > -1) {
|
) {
|
||||||
storage_accid=uni.getStorageSync('AUTH_YX_ACCID_App');
|
let src=options.referrerInfo.extraData.targetPath
|
||||||
storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App');
|
|
||||||
} else {
|
if(src.indexOf('downLoadVideo') > -1 ){
|
||||||
storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App');
|
uni.navigateTo({
|
||||||
storage_token=uni.getStorageSync('DEV_AUTH_YX_TOKEN_App');
|
url: src+'?from=mine',
|
||||||
}
|
});
|
||||||
} else if(process.env.UNI_PLATFORM == "mp-weixin") {
|
}else{
|
||||||
const {
|
uni.navigateTo({
|
||||||
envVersion
|
url: src,
|
||||||
} = uni.getAccountInfoSync().miniProgram;
|
});
|
||||||
if (envVersion == "release") {
|
}
|
||||||
storage_accid=uni.getStorageSync('AUTH_YX_ACCID_App');
|
}
|
||||||
storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App');
|
|
||||||
} else {
|
console.log("app传递登录信息onLaunch-------------------");
|
||||||
storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App');
|
try {
|
||||||
storage_token=uni.getStorageSync('DEV_AUTH_YX_TOKEN_App');
|
// #ifdef APP
|
||||||
}
|
uni.onNativeEventReceive((event, data) => {
|
||||||
}else{
|
console.log("event", event);
|
||||||
if (BASE_URL.indexOf('dev') == -1) {
|
console.log("data", data);
|
||||||
storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App');
|
if (event.indexOf("clearToken") > -1) {
|
||||||
storage_token=uni.getStorageSync('DEV_AUTH_YX_TOKEN_App');
|
uni.setStorageSync("AUTH_TOKEN_App", "");
|
||||||
|
plus.runtime.quit();
|
||||||
} else {
|
}
|
||||||
storage_accid=uni.getStorageSync('AUTH_YX_ACCID_App');
|
if(event.indexOf("goPage") > -1){
|
||||||
storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App');
|
if(data.indexOf('downLoadVideo') > -1){
|
||||||
}
|
uni.navigateTo({
|
||||||
}
|
url: data+'?from=mine'
|
||||||
const account =storage_accid;
|
});
|
||||||
const token = storage_token;
|
}else{
|
||||||
const imOptions = {
|
uni.navigateTo({
|
||||||
appkey: "885dea390870814acf3ba8558c717572", // 请填写你的appkey
|
url: data,
|
||||||
account: account,//"9ufkll2xo57km6224xe", // 请填写你的account
|
});
|
||||||
token: token//"4918605da57e573cff93209df56f351d", // 请填写你的token
|
}
|
||||||
};
|
}
|
||||||
if (imOptions) {
|
if(event.indexOf('paySuccess') > -1){
|
||||||
this.initNim(imOptions);
|
console.log('app.vue监听到成功支付');
|
||||||
} else {
|
if(data.type=='GandanFile'){
|
||||||
/** 未登录 跳转登录页 */
|
uni.$emit('paySuccess',{
|
||||||
// customRedirectTo({
|
type:'GandanFile',
|
||||||
// url: isWxApp ? "/pages/index/index" : "/pages/Login/index",
|
});
|
||||||
// });
|
}else if(data.type=='BuyPoint'){
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
} catch (error) {
|
||||||
|
console.log("app传递登录信息error-------------------");
|
||||||
|
console.log(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
// #ifdef APP-PLUS
|
try {
|
||||||
uni?.$UIKitNIM?.V2NIMSettingService?.setAppBackground(false);
|
// #ifdef APP
|
||||||
|
let checkTokenCallBackFlag = false;
|
||||||
|
console.log("执行onshow");
|
||||||
|
|
||||||
// 点击通知栏推送监听
|
uni.sendNativeEvent(
|
||||||
nimPushPlugin.addOpenNotificationListener((res) => {
|
"checkToken",
|
||||||
if (typeof res == "object" && res?.sessionId && res?.sessionType) {
|
|
||||||
// 当前登录账号id 具体获取根据您的业务逻辑调整
|
|
||||||
const imOptions = uni.getStorageSync(STORAGE_KEY);
|
|
||||||
// 会话类型
|
|
||||||
const type = res?.sessionType;
|
|
||||||
// 拼装会话ID
|
|
||||||
startByNotificationId = `${imOptions.account}|${type}|${res?.sessionId}`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #endif
|
|
||||||
},
|
|
||||||
onHide() {
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
uni?.$UIKitNIM?.V2NIMSettingService?.setAppBackground(true);
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// 重置推送 startByNotificationId
|
|
||||||
startByNotificationId = "";
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
initNim(opts) {
|
|
||||||
/** 保存登录信息 demo 层逻辑 具体根据您的业务调整*/
|
|
||||||
uni.setStorage({
|
|
||||||
key: STORAGE_KEY,
|
|
||||||
data: opts,
|
|
||||||
});
|
|
||||||
|
|
||||||
/** 是否开启云端会话(此处为了方便demo切换云端/本地会话,将其存到本地,实际需根据业务情况设置)*/
|
|
||||||
const enableV2CloudConversation =
|
|
||||||
uni.getStorageSync("enableV2CloudConversation") === "on";
|
|
||||||
|
|
||||||
/** 初始化 nim sdk */
|
|
||||||
//@ts-ignore
|
|
||||||
const nim = (uni.$UIKitNIM = NIM.getInstance(
|
|
||||||
{
|
{
|
||||||
appkey: opts.appkey,
|
msg: "checkToken",
|
||||||
needReconnect: true,
|
|
||||||
debugLevel: "debug",
|
|
||||||
apiVersion: "v2",
|
|
||||||
enableV2CloudConversation: enableV2CloudConversation,
|
|
||||||
},
|
},
|
||||||
{
|
(ret) => {
|
||||||
V2NIMLoginServiceConfig: {
|
checkTokenCallBackFlag = true;
|
||||||
/**
|
console.log("check回调");
|
||||||
* 微信小程序需要使用单独的lbsUrls和linkUrl
|
console.log(ret);
|
||||||
*/
|
if (ret.code == 0) {
|
||||||
lbsUrls: isWxApp
|
uni.showModal({
|
||||||
? ["https://lbs.netease.im/lbs/wxwebconf.jsp"]
|
title: "提示",
|
||||||
: ["https://lbs.netease.im/lbs/webconf.jsp"],
|
showCancel: false,
|
||||||
linkUrl: isWxApp ? "wlnimsc0.netease.im" : "weblink.netease.im",
|
content: "您已退出登录!",
|
||||||
/**
|
success: function (res) {
|
||||||
* 使用固定设备ID,
|
if (res.confirm) {
|
||||||
*/
|
uni.sendNativeEvent(
|
||||||
isFixedDeviceId: true,
|
"goTabbarPage",
|
||||||
},
|
{
|
||||||
}
|
msg: "home",
|
||||||
));
|
|
||||||
|
|
||||||
/** 初始化 im store */
|
|
||||||
// @ts-ignore
|
|
||||||
const store = (uni.$UIKitStore = new RootStore(
|
|
||||||
// @ts-ignore
|
|
||||||
nim,
|
|
||||||
{
|
|
||||||
// 添加好友是否需要验证
|
|
||||||
addFriendNeedVerify: true,
|
|
||||||
// 是否需要显示 p2p 消息、p2p会话列表消息已读未读,默认 false
|
|
||||||
p2pMsgReceiptVisible: true,
|
|
||||||
// 是否需要显示群组消息已读未读,默认 false
|
|
||||||
teamMsgReceiptVisible: true,
|
|
||||||
// 是否显示在线离线
|
|
||||||
loginStateVisible: true,
|
|
||||||
// 群组被邀请模式,默认需要验证
|
|
||||||
teamAgreeMode:
|
|
||||||
V2NIMConst.V2NIMTeamAgreeMode.V2NIM_TEAM_AGREE_MODE_NO_AUTH,
|
|
||||||
// 发送消息前回调, 可对消息体进行修改,添加自定义参数
|
|
||||||
// @ts-ignore
|
|
||||||
sendMsgBefore: async (options) => {
|
|
||||||
const pushContent = getMsgContentTipByType({
|
|
||||||
text: options.msg.text,
|
|
||||||
messageType: options.msg.messageType,
|
|
||||||
});
|
|
||||||
const yxAitMsg = options.serverExtension
|
|
||||||
? options.serverExtension.yxAitMsg
|
|
||||||
: { forcePushIDsList: "[]", needForcePush: false };
|
|
||||||
|
|
||||||
// 如果是 at 消息,需要走离线强推
|
|
||||||
// @ts-ignore
|
|
||||||
const { forcePushIDsList, needForcePush } = yxAitMsg
|
|
||||||
? // @ts-ignore
|
|
||||||
store.msgStore._formatExtAitToPushInfo(
|
|
||||||
yxAitMsg,
|
|
||||||
options.msg.text
|
|
||||||
)
|
|
||||||
: { forcePushIDsList: "[]", needForcePush: false };
|
|
||||||
|
|
||||||
const { conversationId } = options;
|
|
||||||
const conversationType =
|
|
||||||
nim.V2NIMConversationIdUtil.parseConversationType(conversationId);
|
|
||||||
const targetId =
|
|
||||||
nim.V2NIMConversationIdUtil.parseConversationTargetId(
|
|
||||||
conversationId
|
|
||||||
);
|
|
||||||
|
|
||||||
// 设置离线强推,厂商相关推送在此处配置
|
|
||||||
// 具体参考文档 https://doc.yunxin.163.com/messaging2/guide/zc4MTg5MDY?platform=client#%E7%AC%AC%E4%B8%80%E6%AD%A5%E4%B8%8A%E4%BC%A0%E6%8E%A8%E9%80%81%E8%AF%81%E4%B9%A6
|
|
||||||
const pushPayload = JSON.stringify({
|
|
||||||
pushTitle: "", // 必填,推送消息标题
|
|
||||||
notify_effect: "2", //可选项,预定义通知栏消息的点击行为。1:通知栏点击后打开app的Launcher Activity,2:通知栏点击后打开app的任一Activity(开发者还需要传入intent_uri),3:通知栏点击后打开网页(开发者还需要传入web_uri)
|
|
||||||
intent_uri:
|
|
||||||
"intent:#Intent;action=com.netease.nimlib.uniapp.push.NotificationClickActivity;component=com.netease.nim.demo/com.netease.nimlib.uniapp.push.NotificationClickActivity;launchFlags=0x04000000;i.sessionType=0;S.sessionId=cs1;end", //可选项,打开当前app的任一组件。
|
|
||||||
hwField: {
|
|
||||||
click_action: {
|
|
||||||
//必填,消息点击行为
|
|
||||||
type: 1, //必填,消息点击行为类型,取值如下:1:打开应用自定义页面 2:点击后打开特定URL 3:点击后打开应用
|
|
||||||
// 自定义页面中intent的实现,请参见指定intent参数。当type为1时,字段intent和action至少二选一。scheme方式和指定activity方式都可以
|
|
||||||
intent:
|
|
||||||
"intent:#Intent;action=com.netease.nimlib.uniapp.push.NotificationClickActivity;component=com.netease.nim.demo/com.netease.nimlib.uniapp.push.NotificationClickActivity;launchFlags=0x04000000;i.sessionType=0;S.sessionId=cs1;end",
|
|
||||||
},
|
|
||||||
androidConfig: {
|
|
||||||
category: "IM", //可选项,标识消息类型,用于标识高优先级透传场景,详见官方文档 AndroidConfig.category
|
|
||||||
},
|
|
||||||
},
|
|
||||||
honorField: {
|
|
||||||
notification: {
|
|
||||||
// AndroidNotification
|
|
||||||
clickAction: {
|
|
||||||
//必填,消息点击行为
|
|
||||||
type: 1, //必填,消息点击行为类型,取值如下:1:打开应用自定义页面 2:点击后打开特定URL 3:点击后打开应用
|
|
||||||
//自定义页面中intent的实现,请参见指定intent参数。当type为1时,字段intent和action至少二选一。
|
|
||||||
intent: "",
|
|
||||||
},
|
|
||||||
importance: "NORMAL", //可选项,Android通知消息分类,决定用户设备消息通知行为,取值如下:LOW:资讯营销类消息 NORMAL:服务与通讯类消息
|
|
||||||
},
|
|
||||||
},
|
|
||||||
vivoField: {
|
|
||||||
skipType: "4", //必填,点击跳转类型 1:打开APP首页 2:打开链接 3:自定义 4:打开app内指定页面,默认为1
|
|
||||||
skipContent: "",
|
|
||||||
classification: "1", //可选项,消息类型 0:运营类消息,1:系统类消息。默认为0
|
|
||||||
category: "IM", // 可选项,二级分类
|
|
||||||
},
|
|
||||||
oppoField: {
|
|
||||||
channel_id: "", //可选项,指定下发的通道ID
|
|
||||||
category: "IM", //可选项,通道类别名
|
|
||||||
notify_level: 2, //通知栏消息提醒等级,1-通知栏;2-通知栏+锁屏;16-通知栏+锁屏+横幅+震动+铃声
|
|
||||||
click_action_type: "1", //点击通知栏后触发的动作类型。0(默认0.启动应用;1.跳转指定应用内页(action标签名);2.跳转网页;4.跳转指定应用内页(全路径类名);5.跳转Intent scheme URL: "",
|
|
||||||
click_action_activity: "",
|
|
||||||
action_parameters: "",
|
|
||||||
},
|
|
||||||
fcmFieldV1: {
|
|
||||||
message: {
|
|
||||||
android: {
|
|
||||||
priority: "",
|
|
||||||
data: {
|
|
||||||
sessionType: "0",
|
|
||||||
sessionId: "cs1",
|
|
||||||
},
|
},
|
||||||
notification: {
|
(ret) => {
|
||||||
click_action: "",
|
console.log(ret);
|
||||||
},
|
}
|
||||||
},
|
);
|
||||||
},
|
plus.runtime.quit();
|
||||||
},
|
} else if (res.cancel) {
|
||||||
|
console.log("用户点击取消");
|
||||||
// IOS apns
|
|
||||||
sessionId:
|
|
||||||
conversationType == 1
|
|
||||||
? uni.$UIKitStore.userStore.myUserInfo.accountId
|
|
||||||
: targetId,
|
|
||||||
sessionType: conversationType,
|
|
||||||
});
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
const pushConfig = {
|
|
||||||
pushEnabled: true,
|
|
||||||
pushNickEnabled: true,
|
|
||||||
forcePush: needForcePush,
|
|
||||||
forcePushContent: pushContent,
|
|
||||||
forcePushAccountIds: forcePushIDsList,
|
|
||||||
pushPayload,
|
|
||||||
pushContent,
|
|
||||||
};
|
|
||||||
|
|
||||||
return { ...options, pushConfig };
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"UniApp"
|
|
||||||
));
|
|
||||||
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
/** 注册推送 实际根据您在推送厂商申请的证书进行配置,具体参考文档 https://doc.yunxin.163.com/messaging2/guide/zc4MTg5MDY?platform=client#%E7%AC%AC%E4%B8%80%E6%AD%A5%E4%B8%8A%E4%BC%A0%E6%8E%A8%E9%80%81%E8%AF%81%E4%B9%A6
|
|
||||||
*/
|
|
||||||
nim.V2NIMSettingService.setOfflinePushConfig(nimPushPlugin, {
|
|
||||||
// miPush: {
|
|
||||||
// appId: "",
|
|
||||||
// appKey: "",
|
|
||||||
// certificateName: "",
|
|
||||||
// },
|
|
||||||
// hwPush: {
|
|
||||||
// appId: "",
|
|
||||||
// certificateName: "",
|
|
||||||
// },
|
|
||||||
// oppoPush: {
|
|
||||||
// appId: "",
|
|
||||||
// appKey: "",
|
|
||||||
// certificateName: "",
|
|
||||||
// secret: "",
|
|
||||||
// },
|
|
||||||
// vivoPush: {
|
|
||||||
// appId: "",
|
|
||||||
// appKey: "",
|
|
||||||
// certificateName: "",
|
|
||||||
// },
|
|
||||||
// fcmPush: {
|
|
||||||
// certificateName: "",
|
|
||||||
// },
|
|
||||||
// mzPush: {
|
|
||||||
// appId: "",
|
|
||||||
// appKey: "",
|
|
||||||
// certificateName: "",
|
|
||||||
// },
|
|
||||||
// apns: {
|
|
||||||
// certificateName: "",
|
|
||||||
// },
|
|
||||||
});
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
/** nim sdk 登录 */
|
|
||||||
nim.V2NIMLoginService.login(opts.account, opts.token).then(async () => {
|
|
||||||
console.log("登录成功");
|
|
||||||
nim.V2NIMLoginService.on('onKickedOffline', (res) => {
|
|
||||||
console.log("被踢下线", res);
|
|
||||||
});
|
|
||||||
// #ifdef APP-PLUS
|
|
||||||
/** 初始化音视频通话插件*/
|
|
||||||
nimCallKit.initConfig(
|
|
||||||
{
|
|
||||||
appKey: opts.appkey, // 请填写你的appkey
|
|
||||||
account: opts.account, // 请填写你的account
|
|
||||||
token: opts.token, // 请填写你的token
|
|
||||||
apnsCername: "",
|
|
||||||
pkCername: "",
|
|
||||||
},
|
|
||||||
(ret) => {
|
|
||||||
if (ret.code != 200) {
|
|
||||||
// callkit init失败
|
|
||||||
} else {
|
|
||||||
|
|
||||||
nimCallKit.login(
|
|
||||||
{
|
|
||||||
account: opts.account,
|
|
||||||
token: opts.token,
|
|
||||||
},
|
|
||||||
function (ret) {
|
|
||||||
if (ret.code != 200) {
|
|
||||||
// 登录失败
|
|
||||||
} else {
|
|
||||||
// 登录成功
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
},
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// #endif
|
|
||||||
// 判断时手动点击唤起 还是 点击推送通知栏唤起,点击通知栏唤起直接跳转到聊天页面
|
|
||||||
if (!startByNotificationId) {
|
|
||||||
// customSwitchTab({
|
|
||||||
// url: "/pages/Conversation/index",
|
|
||||||
// });
|
|
||||||
} else {
|
|
||||||
if (startByNotificationId) {
|
|
||||||
await uni.$UIKitStore.uiStore.selectConversation(
|
|
||||||
startByNotificationId
|
|
||||||
);
|
|
||||||
|
|
||||||
uni.navigateTo({
|
|
||||||
url: `/pages/Chat/index?conversationId=${startByNotificationId}`,
|
|
||||||
});
|
});
|
||||||
startByNotificationId = "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
},
|
|
||||||
logout() {
|
// setTimeout(function(){
|
||||||
uni.removeStorageSync(STORAGE_KEY);
|
// console.log("执行 setTimeout")
|
||||||
try {
|
// if(!checkTokenCallBackFlag){
|
||||||
nimCallKit.logout({}, (ret) => {
|
// uni.showModal({
|
||||||
if (ret.code != 200) {
|
// title: '提示',
|
||||||
console.log("音视频通话插件退出失败");
|
// showCancel: false,
|
||||||
} else {
|
// content: '您已退出登录',
|
||||||
console.log("音视频通话插件退出成功");
|
// success: function (res) {
|
||||||
}
|
// if (res.confirm) {
|
||||||
});
|
// uni.sendNativeEvent('goTabbarPage', {
|
||||||
} catch (error) {
|
// msg: 'home'
|
||||||
console.log("音视频通话插件退出失败", error);
|
// }, ret => {
|
||||||
}
|
// console.log(ret);
|
||||||
// 退出登录
|
// })
|
||||||
uni.$UIKitNIM.V2NIMLoginService.logout().then((res) => {
|
// } else if (res.cancel) {
|
||||||
console.log("退出登录", res);
|
// console.log('用户点击取消');
|
||||||
uni.$UIKitStore.destroy();
|
// }
|
||||||
customReLaunch({
|
// }
|
||||||
url: "/pages/Login/index",
|
// });
|
||||||
});
|
// }
|
||||||
});
|
// }, 1000)
|
||||||
},
|
|
||||||
|
|
||||||
|
let main = plus.android.runtimeMainActivity();
|
||||||
|
//为了防止快速点按返回键导致程序退出重写quit方法改为隐藏至后台
|
||||||
|
plus.runtime.quit = function () {
|
||||||
|
main.moveTaskToBack(false);
|
||||||
|
};
|
||||||
|
//重写toast方法如果内容为 ‘再按一次退出应用’ 就隐藏应用,其他正常toast
|
||||||
|
plus.nativeUI.toast = function (str) {
|
||||||
|
if (str == "再按一次退出应用") {
|
||||||
|
main.moveTaskToBack(false);
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: str,
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// uni.onNativeEventReceive((event, data) => {
|
||||||
|
// console.log("app传递登录信息onshow-------------------");
|
||||||
|
// console.log("event", event);
|
||||||
|
// console.log("data", data);
|
||||||
|
// if (event == "loginInfo") {
|
||||||
|
// uni.setStorageSync("DEV_AUTH_YX_TOKEN_App", data.token);
|
||||||
|
// uni.setStorageSync("userInfo", data.userInfo);
|
||||||
|
// }else if(event == "showRedDot"){
|
||||||
|
// console.log("showRedDot");
|
||||||
|
// console.log(data);
|
||||||
|
// getApp().globalData.dotNumber=data;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// #endif
|
||||||
|
} catch (error) {
|
||||||
|
console.log("error");
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
onHide() {},
|
||||||
|
methods: {},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<template>
|
||||||
|
<GlobalDialog />
|
||||||
/*每个页面公共css */
|
</template>
|
||||||
@import '@/uni_modules/uni-scss/index.scss';
|
|
||||||
/* #ifndef APP-NVUE */
|
|
||||||
@import '@/static/customicons.css';
|
|
||||||
// 设置整个项目的背景色
|
|
||||||
page {
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #endif */
|
<style lang="scss">
|
||||||
.uni-nav-bar-text{
|
/*每个页面公共css */
|
||||||
font-weight: bold;
|
@import "@/uni_modules/uni-scss/index.scss";
|
||||||
font-size: 34rpx!important;
|
/* #ifndef APP-NVUE */
|
||||||
}
|
@import "@/static/customicons.css";
|
||||||
.example-info {
|
|
||||||
font-size: 14px;
|
// 设置整个项目的背景色
|
||||||
color: #333;
|
page {
|
||||||
padding: 10px;
|
background-color: #f5f5f5;
|
||||||
}
|
}
|
||||||
.twoline{
|
|
||||||
display: -webkit-box;
|
.uni-navbar__header-btns-right {
|
||||||
-webkit-box-orient: vertical;
|
min-width: 120rpx;
|
||||||
-webkit-line-clamp: 2;
|
width: auto !important;
|
||||||
overflow: hidden;
|
}
|
||||||
}
|
|
||||||
|
/* #endif */
|
||||||
.oneline{
|
.uni-nav-bar-text {
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
font-size: 40rpx !important;
|
||||||
text-overflow: ellipsis;
|
}
|
||||||
}
|
|
||||||
.uni-navbar .uniui-left{
|
.example-info {
|
||||||
font-weight: bold;
|
font-size: 14px;
|
||||||
font-size: 50rpx!important;
|
color: #333;
|
||||||
}
|
padding: 10px;
|
||||||
::-webkit-scrollbar { display: none; }
|
}
|
||||||
.nav-right{
|
|
||||||
margin-top: -20px;
|
.twoline {
|
||||||
}
|
display: -webkit-box;
|
||||||
</style>
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.oneline {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-navbar .uniui-left {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 50rpx !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status_bar {
|
||||||
|
height: var(--status-bar-height);
|
||||||
|
background-color: #eeeeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbox {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: calc(var(--status-bar-height) + 44px);
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
.share-content .share-item:last-child{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"prompt" : "none"
|
||||||
|
}
|
||||||
+182
-6
@@ -1,4 +1,5 @@
|
|||||||
import {request} from '@/utils/request.js'
|
import {request} from '@/utils/request.js'
|
||||||
|
|
||||||
const api = {
|
const api = {
|
||||||
|
|
||||||
expertWxLogin(jscode){
|
expertWxLogin(jscode){
|
||||||
@@ -119,11 +120,11 @@ const api = {
|
|||||||
},
|
},
|
||||||
// 积分支付列表
|
// 积分支付列表
|
||||||
bonusPointsPayList(data) {
|
bonusPointsPayList(data) {
|
||||||
return request('/expertAPI/bonusPointsPayList', data, 'post', false);
|
return request('/expertAPI/bonusPointsPayList', data, 'post', true);
|
||||||
},
|
},
|
||||||
// 积分列表
|
// 积分列表
|
||||||
bonusPointsList(data) {
|
bonusPointsList(data) {
|
||||||
return request('/expertAPI/bonusPointsList', data, 'post', false);
|
return request('/expertAPI/bonusPointsList', data, 'post', true);
|
||||||
},
|
},
|
||||||
|
|
||||||
getWelfarePage(data) {
|
getWelfarePage(data) {
|
||||||
@@ -335,6 +336,9 @@ const api = {
|
|||||||
applyList(data){
|
applyList(data){
|
||||||
return request('/expertAPI/applyList', data, 'post', false);
|
return request('/expertAPI/applyList', data, 'post', false);
|
||||||
},
|
},
|
||||||
|
patientListByGBKPage(data){
|
||||||
|
return request('/expertAPI/patientListByGBKPage', data, 'post', false);
|
||||||
|
},
|
||||||
patientListByGBK(data){
|
patientListByGBK(data){
|
||||||
return request('/expertAPI/patientListByGBK', data, 'post', false);
|
return request('/expertAPI/patientListByGBK', data, 'post', false);
|
||||||
},
|
},
|
||||||
@@ -411,6 +415,10 @@ const api = {
|
|||||||
bankCardList(data){
|
bankCardList(data){
|
||||||
return request('/expertPay/bankCardList', data, 'post', false);
|
return request('/expertPay/bankCardList', data, 'post', false);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
deleteBankCard(data){
|
||||||
|
return request('/expertPay/deleteBankCard', data, 'post', false);
|
||||||
|
},
|
||||||
getIncomeTax(data){
|
getIncomeTax(data){
|
||||||
return request('/expertPay/getIncomeTax', data, 'post', false);
|
return request('/expertPay/getIncomeTax', data, 'post', false);
|
||||||
},
|
},
|
||||||
@@ -446,10 +454,10 @@ const api = {
|
|||||||
return request('/expertAPI/consultListHis', data, 'post', false);
|
return request('/expertAPI/consultListHis', data, 'post', false);
|
||||||
},
|
},
|
||||||
listNewInterrogation(data){
|
listNewInterrogation(data){
|
||||||
return request('/expertAPI/listNewInterrogation', data, 'post', false);
|
return request('/expertAPI/listNewInterrogation', data, 'post', true);
|
||||||
},
|
},
|
||||||
listMyAnsweredInterrogation(data){
|
listMyAnsweredInterrogation(data){
|
||||||
return request('/expertAPI/listMyAnsweredInterrogation', data, 'post', false);
|
return request('/expertAPI/listMyAnsweredInterrogation', data, 'post', true);
|
||||||
},
|
},
|
||||||
getInterrogation(data){
|
getInterrogation(data){
|
||||||
return request('/expertAPI/getInterrogation', data, 'post', false);
|
return request('/expertAPI/getInterrogation', data, 'post', false);
|
||||||
@@ -458,10 +466,10 @@ const api = {
|
|||||||
return request('/expertAPI/InterrogationPatientInfo', data, 'post', false);
|
return request('/expertAPI/InterrogationPatientInfo', data, 'post', false);
|
||||||
},
|
},
|
||||||
updateInterrogationAnswer(data){
|
updateInterrogationAnswer(data){
|
||||||
return request('/expertAPI/updateInterrogationAnswer', data, 'post', false);
|
return request('/expertAPI/updateInterrogationAnswerU', data, 'post', true);
|
||||||
},
|
},
|
||||||
addInterrogationAnswer(data){
|
addInterrogationAnswer(data){
|
||||||
return request('/expertAPI/addInterrogationAnswer', data, 'post', false);
|
return request('/expertAPI/addInterrogationAnswerU', data, 'post', true);
|
||||||
},
|
},
|
||||||
videoDetail(data){
|
videoDetail(data){
|
||||||
return request('/expertAPI/videoDetail', data, 'post', false);
|
return request('/expertAPI/videoDetail', data, 'post', false);
|
||||||
@@ -556,6 +564,174 @@ const api = {
|
|||||||
toAddNickname(data){
|
toAddNickname(data){
|
||||||
return request('/expertAPI/toAddNickname', data, 'post', false);
|
return request('/expertAPI/toAddNickname', data, 'post', false);
|
||||||
},
|
},
|
||||||
|
caseDetail(data){
|
||||||
|
return request('/expertAPI/caseDetail', data, 'post', false);
|
||||||
|
},
|
||||||
|
conditionRecordList(data){
|
||||||
|
return request('/expertAPI/conditionRecordList', data, 'post', false);
|
||||||
|
},
|
||||||
|
addConditionRecord(data){
|
||||||
|
return request('/expertAPI/addConditionRecord', data, 'post', false);
|
||||||
|
},
|
||||||
|
updateConditionRecord(data){
|
||||||
|
return request('/expertAPI/upConditionRecord', data, 'post', false);
|
||||||
|
},
|
||||||
|
deleteConditionRecord(data){
|
||||||
|
return request('/expertAPI/delConditionRecord', data, 'post', false);
|
||||||
|
},
|
||||||
|
consultDetail(data){
|
||||||
|
return request('/expertAPI/consultDetail', data, 'post', false);
|
||||||
|
},
|
||||||
|
isConsultIng(data){
|
||||||
|
return request('/expertAPI/isConsultIng', data, 'post', false);
|
||||||
|
},
|
||||||
|
resConsult(data){
|
||||||
|
return request('/expertAPI/resConsult', data, 'post', false);
|
||||||
|
},
|
||||||
|
countConsult(data){
|
||||||
|
return request('/expertAPI/countConsult', data, 'post', false);
|
||||||
|
},
|
||||||
|
closeConsult(data){
|
||||||
|
return request('/expertAPI/closeConsult', data, 'post', false);
|
||||||
|
},
|
||||||
|
checkUser(data){
|
||||||
|
return request('/expertAPI/checkUser', data, 'post', false);
|
||||||
|
},
|
||||||
|
ganDanFileDetials(data){
|
||||||
|
return request('/expertAPI/ganDanFileDetials', data, 'post', false);
|
||||||
|
},
|
||||||
|
createGanDanFileOrder(data){
|
||||||
|
return request('/expertPay/createGanDanFileOrder', data, 'post', false);
|
||||||
|
},
|
||||||
|
getOrderStatus(data){
|
||||||
|
return request('/expertPay/getOrderStatus', data, 'post', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
getOrderStatus(data){
|
||||||
|
return request('/expertPay/getOrderStatus', data, 'post', false);
|
||||||
|
},
|
||||||
|
getBalance(data){
|
||||||
|
return request('/expertPay/getBalance', data, 'post', false);
|
||||||
|
},
|
||||||
|
payGanDanFile(data){
|
||||||
|
return request('/expertPay/payGanDanFileOrder', data, 'post', false);
|
||||||
|
},
|
||||||
|
// discollection(data){
|
||||||
|
// return request('/expert/discollection', data, 'post', false);
|
||||||
|
// },
|
||||||
|
// collection(data){
|
||||||
|
// return request('/expert/collection', data, 'post', false);
|
||||||
|
// },
|
||||||
|
getTypeUuidByName(data){
|
||||||
|
return request('/expertAPI/getTypeUuidByName', data, 'post', false);
|
||||||
|
},
|
||||||
|
videoByTypeNew(data){
|
||||||
|
return request('/expertAPI/videoByTypeNew', data, 'post', false);
|
||||||
|
},
|
||||||
|
meetingHistoryList(data){
|
||||||
|
return request('/expertAPI/meetingHistoryList', data, 'post', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 扫码登录相关API
|
||||||
|
// 确认扫码登录
|
||||||
|
confirmScanLogin(data){
|
||||||
|
return request('/expertAPI/confirmScanLogin', data, 'post', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 取消扫码登录
|
||||||
|
cancelScanLogin(data){
|
||||||
|
return request('/expertAPI/cancelScanLogin', data, 'post', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取扫码登录状态
|
||||||
|
getScanLoginStatus(data){
|
||||||
|
return request('/expertAPI/getScanLoginStatus', data, 'post', false);
|
||||||
|
},
|
||||||
|
gethonorDetail(data){
|
||||||
|
return request('/expertAPI/gethonorDetail', data, 'post', false);
|
||||||
|
},
|
||||||
|
checkVersion(data){
|
||||||
|
return request('/expertAPI/checkVersion', data, 'post', false);
|
||||||
|
},
|
||||||
|
getIsAccount(data){
|
||||||
|
return request('/expertAPI/getIsAccount', data, 'post', false);
|
||||||
|
},
|
||||||
|
patientVideoByJingHuaNew(data){
|
||||||
|
return request('/expertAPI/patientVideoByJingHuaNew', data, 'post', false);
|
||||||
|
},
|
||||||
|
useWelfareNum(data){
|
||||||
|
return request('/expertAPI/useWelfareNum', data, 'post', false);
|
||||||
|
},
|
||||||
|
deleteComment(data){
|
||||||
|
return request('/expertAPI/deleteComment', data, 'post', false);
|
||||||
|
},
|
||||||
|
downloadGanDanFile(data){
|
||||||
|
return request('/expertAPI/downloadGanDanFile', data, 'post', false,'application/json',{},'arraybuffer');
|
||||||
|
},
|
||||||
|
downloadGanDanFileV2(data){
|
||||||
|
return request('/expertAPI/downloadGanDanFileV2', data, 'post', false);
|
||||||
|
},
|
||||||
|
feedBack(data){
|
||||||
|
return request('/expertAPI/addFeedBack', data, 'post', false);
|
||||||
|
},
|
||||||
|
getPointUnitPrice(data){
|
||||||
|
return request('/expertAPI/getPointUnitPrice', data, 'post', false);
|
||||||
|
},
|
||||||
|
welfareList(data){
|
||||||
|
return request('/expertAPI/welfareList', data, 'post', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
getUGoods(data){
|
||||||
|
return request('/expertAPI/getGoodsDetailU', data, 'post', false);
|
||||||
|
},
|
||||||
|
createGoodsOrder(data){
|
||||||
|
return request('/expertAPI/createGoodsOrder', data, 'post', false);
|
||||||
|
},
|
||||||
|
useWelfareNum(data){
|
||||||
|
return request('/expertAPI/useWelfareNum', data, 'post', false);
|
||||||
|
},
|
||||||
|
createBointsOrder(data){
|
||||||
|
return request('/expertPay/createBointsOrder', data, 'post', false);
|
||||||
|
},
|
||||||
|
receiveWelfare(data){
|
||||||
|
return request('/expertAPI/receiveWelfare', data, 'post', false);
|
||||||
|
},
|
||||||
|
getKePuCollection(data){
|
||||||
|
return request('/expertAPI/getKePuCollection', data, 'post', false);
|
||||||
|
},
|
||||||
|
getRead(data){
|
||||||
|
return request('/expertAPI/read', data, 'post', false);
|
||||||
|
},
|
||||||
|
getOutRead(data){
|
||||||
|
return request('/expertAPI/outread', data, 'post', false);
|
||||||
|
},
|
||||||
|
getAgree(data){
|
||||||
|
return request('/expertAPI/agree', data, 'post', false);
|
||||||
|
},
|
||||||
|
getDisagree(data){
|
||||||
|
return request('/expertAPI/disagree', data, 'post', false);
|
||||||
|
},
|
||||||
|
getCollect(data){
|
||||||
|
return request('/expertAPI/collection', data, 'post', false);
|
||||||
|
},
|
||||||
|
getDiscollect(data){
|
||||||
|
return request('/expertAPI/discollection', data, 'post', false);
|
||||||
|
},
|
||||||
|
getGanDanFileOrder(data){
|
||||||
|
return request('/expertPay/getGanDanFileOrder', data, 'post', false);
|
||||||
|
},
|
||||||
|
publishOutPatient(data){
|
||||||
|
return request('/expertAPI/addGroupSendMsg4YunXin', data, 'post', false);
|
||||||
|
},
|
||||||
|
polularScienceArticleListIndexNew(data){
|
||||||
|
return request('/expertAPI/polularScienceArticleListIndexNew', data, 'post', false);
|
||||||
|
},
|
||||||
|
getNewsDetail(data){
|
||||||
|
return request('/expertAPI/newsDetial', data, 'post', false);
|
||||||
|
},
|
||||||
|
|
||||||
|
//https://dev-app.igandan.com/app/expertPay/getGanDanFileOrder
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default api
|
export default api
|
||||||
+16
-2
@@ -23,11 +23,25 @@ const goods_api = {
|
|||||||
createGoodsOrder(data) {
|
createGoodsOrder(data) {
|
||||||
return request('/expertAPI/createGoodsOrder', data, 'post', true);
|
return request('/expertAPI/createGoodsOrder', data, 'post', true);
|
||||||
},
|
},
|
||||||
|
payGoodsOrder(data) {
|
||||||
|
return request('/expertAPI/payGoodsOrder', data, 'post', true);
|
||||||
|
},
|
||||||
getGoodsOrderList(data) {
|
getGoodsOrderList(data) {
|
||||||
return request('/expertAPI/goodsOrderList', data, 'post', true);
|
return request('/expertAPI/goodsOrderList', data, 'post', true);
|
||||||
|
},
|
||||||
|
getUpanWelfareCount(data){
|
||||||
|
return request('/expertAPI/getUpanWelfareCount', data, 'post', false);
|
||||||
|
},
|
||||||
|
getGoodsOrderDetail(data) {
|
||||||
|
return request('/expertAPI/getGoodsOrder', data, 'post', true);
|
||||||
|
},
|
||||||
|
getOrderTrack(data) {
|
||||||
|
return request('/expertAPI/getOrderTrack', data, 'post', true);
|
||||||
|
},
|
||||||
|
cancelGoodsOrder(data) {
|
||||||
|
return request('/expertAPI/cancleGoodsOrder', data, 'post', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default goods_api;
|
export default goods_api;
|
||||||
@@ -14,6 +14,17 @@ const my_api = {
|
|||||||
|
|
||||||
expertWxLogin(data,header) {
|
expertWxLogin(data,header) {
|
||||||
return request('/expertAPI/wechatLogin', data, 'post', true,'application/json',header);
|
return request('/expertAPI/wechatLogin', data, 'post', true,'application/json',header);
|
||||||
|
},
|
||||||
|
|
||||||
|
checkVersion(data) {
|
||||||
|
return request('/expertAPI/checkVersion', data, 'post', true);
|
||||||
|
},
|
||||||
|
|
||||||
|
startpage() {
|
||||||
|
return request('/expertAPI/startpage', {}, 'post', true);
|
||||||
|
},
|
||||||
|
addUniappCid(data) {
|
||||||
|
return request('/expertAPI/addUniappCid', data, 'post', true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
:lazy-load="true"
|
:lazy-load="true"
|
||||||
class="avatar-img"
|
class="avatar-img"
|
||||||
v-if="avatarUrl"
|
v-if="avatarUrl"
|
||||||
:src="docUrl+avatarUrl.replaceAll('null','')"
|
:src="docUrl+avatarUrl.replace('null','')"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
/>
|
/>
|
||||||
<image
|
<image
|
||||||
|
|||||||
@@ -0,0 +1,169 @@
|
|||||||
|
<template>
|
||||||
|
<view v-show="visible" class="gd-mask" :class="alignClass" :style="maskStyle">
|
||||||
|
<view
|
||||||
|
class="gd-dialog"
|
||||||
|
@touchstart="onTouchStart"
|
||||||
|
@touchmove="onTouchMove"
|
||||||
|
@touchend="onTouchEnd"
|
||||||
|
>
|
||||||
|
<view class="gd-title">{{ title }}</view>
|
||||||
|
<scroll-view class="gd-content" scroll-y>
|
||||||
|
<text class="gd-text">{{ content }}</text>
|
||||||
|
</scroll-view>
|
||||||
|
<!-- <view class="gd-footer">
|
||||||
|
<view class="gd-btn gd-confirm" @click="handleConfirm">{{ confirmText }}</view>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, onBeforeUnmount, computed } from 'vue'
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
const title = ref('消息通知')
|
||||||
|
const content = ref('')
|
||||||
|
const confirmText = ref('我知道了')
|
||||||
|
const position = ref('center') // 'center' | 'top'
|
||||||
|
const offsetTop = ref('20rpx')
|
||||||
|
const autoHideTimer = ref(null)
|
||||||
|
|
||||||
|
const startY = ref(0)
|
||||||
|
const hasSwipedUp = ref(false)
|
||||||
|
|
||||||
|
const emit = defineEmits(['confirm'])
|
||||||
|
|
||||||
|
function handleConfirm(){
|
||||||
|
visible.value = false
|
||||||
|
emit('confirm')
|
||||||
|
}
|
||||||
|
|
||||||
|
function show(payload = {}){
|
||||||
|
title.value = payload.title || '消息通知'
|
||||||
|
content.value = payload.content || ''
|
||||||
|
confirmText.value = payload.confirmText || '我知道了'
|
||||||
|
position.value = payload.position === 'top' ? 'top' : 'center'
|
||||||
|
offsetTop.value = payload.offsetTop || '20rpx'
|
||||||
|
visible.value = true
|
||||||
|
// 自动 5 秒后消失
|
||||||
|
if (autoHideTimer.value) clearTimeout(autoHideTimer.value)
|
||||||
|
autoHideTimer.value = setTimeout(() => {
|
||||||
|
hide()
|
||||||
|
}, 5000)
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide(){
|
||||||
|
visible.value = false
|
||||||
|
if (autoHideTimer.value) {
|
||||||
|
clearTimeout(autoHideTimer.value)
|
||||||
|
autoHideTimer.value = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onTouchStart(e){
|
||||||
|
const touch = e.changedTouches ? e.changedTouches[0] : (e.touches ? e.touches[0] : null)
|
||||||
|
if (!touch) return
|
||||||
|
startY.value = touch.clientY || touch.pageY || 0
|
||||||
|
hasSwipedUp.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function onTouchMove(e){
|
||||||
|
const touch = e.changedTouches ? e.changedTouches[0] : (e.touches ? e.touches[0] : null)
|
||||||
|
if (!touch) return
|
||||||
|
const currentY = touch.clientY || touch.pageY || 0
|
||||||
|
const deltaY = currentY - startY.value
|
||||||
|
if (deltaY < -60) {
|
||||||
|
hasSwipedUp.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onTouchEnd(){
|
||||||
|
if (hasSwipedUp.value) {
|
||||||
|
hide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
console.log('[GlobalDialog] mounted')
|
||||||
|
uni.$on('global-dialog:show', show)
|
||||||
|
uni.$on('global-dialog:hide', hide)
|
||||||
|
// 便于全局手动触发测试
|
||||||
|
// @ts-ignore
|
||||||
|
uni.$showGlobalDialog = (payload = {}) => {
|
||||||
|
console.log('[GlobalDialog] uni.$showGlobalDialog called', payload)
|
||||||
|
uni.$emit('global-dialog:show', payload)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
uni.$off('global-dialog:show', show)
|
||||||
|
uni.$off('global-dialog:hide', hide)
|
||||||
|
})
|
||||||
|
|
||||||
|
const alignClass = computed(() => position.value === 'top' ? 'is-top' : 'is-center')
|
||||||
|
const maskStyle = computed(() => position.value === 'top' ? { paddingTop: offsetTop.value } : {})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.gd-mask{
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
display: none;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
// 非模态:容器不截获事件
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.gd-mask.is-top{
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.gd-dialog{
|
||||||
|
width: 600rpx;
|
||||||
|
max-width: 90%;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
// 允许对话框自己接收事件(容器为非模态)
|
||||||
|
pointer-events: auto;
|
||||||
|
// 轻微上滑消失的过渡体验
|
||||||
|
transition: transform 0.2s ease, opacity 0.2s ease;
|
||||||
|
}
|
||||||
|
.gd-title{
|
||||||
|
padding: 28rpx 32rpx 12rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #111;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.gd-content{
|
||||||
|
max-height: 420rpx;
|
||||||
|
padding: 0 32rpx 24rpx;
|
||||||
|
}
|
||||||
|
.gd-text{
|
||||||
|
font-size: 28rpx;
|
||||||
|
line-height: 1.7;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.gd-footer{
|
||||||
|
padding: 16rpx 24rpx 24rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.gd-btn{
|
||||||
|
min-width: 200rpx;
|
||||||
|
padding: 20rpx 24rpx;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
.gd-confirm{
|
||||||
|
background: #2979ff;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
<template>
|
||||||
|
<!-- domId 是要截图的容器 id -->
|
||||||
|
<view class="my-html2canvas" :prop="domId" :change:prop="h2cRender.watchDomId">
|
||||||
|
<!-- 用于触发 renderjs 截图 -->
|
||||||
|
<text :prop="expOver" :change:prop="h2cRender.watchExpOver"></text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
domId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
expOver: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 业务层调用这个方法开始截图
|
||||||
|
h2cRenderDom() {
|
||||||
|
// #ifdef H5
|
||||||
|
// H5 直接在当前环境(有 DOM)里跑 renderDom
|
||||||
|
this.$emit('renderDomInH5')
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifndef H5
|
||||||
|
// 非 H5(APP 等)通过 expOver 触发 renderjs 中的截图逻辑
|
||||||
|
this.expOver++
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
// renderjs 截图完成后会 callMethod 回调到这里
|
||||||
|
renderOver(base64) {
|
||||||
|
this.$emit('renderOver', base64)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- renderjs 只能内联 -->
|
||||||
|
<script module="h2cRender" lang="renderjs">
|
||||||
|
import html2canvas from 'html2canvas'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
domIdValue: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async renderDom() {
|
||||||
|
try {
|
||||||
|
const el = document.getElementById(this.domIdValue)
|
||||||
|
if (!el) {
|
||||||
|
console.error('[MyHtml2canvas] dom 未找到,请检查 domId:', this.domIdValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const canvas = await html2canvas(el, {
|
||||||
|
width: el.offsetWidth,
|
||||||
|
height: el.offsetHeight,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
useCORS: true,
|
||||||
|
scale: 2
|
||||||
|
})
|
||||||
|
const base64 = canvas.toDataURL('image/png', 1)
|
||||||
|
this.$ownerInstance.callMethod('renderOver', base64)
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[MyHtml2canvas] html2canvas 失败:', err && err.message)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// script 部分通过 :prop 传入 domId
|
||||||
|
watchDomId(newVal) {
|
||||||
|
this.domIdValue = newVal
|
||||||
|
},
|
||||||
|
// expOver 变化时触发渲染
|
||||||
|
watchExpOver(newVal) {
|
||||||
|
if (newVal !== 0) {
|
||||||
|
this.renderDom()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.my-html2canvas {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<!-- 当父组件传递的prop属性数据发生变化的时候 ,生成海报图片-->
|
||||||
|
<view :prop="domId" :change:prop="html2canvas.emitData" class="html2canvas">
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { base64ToPath } from '@/utils/image-tools.js';
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
domId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted:function(){
|
||||||
|
console.log("组件加载完成");
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
// 接收renderjs发回的数据
|
||||||
|
async receiveRenderData(imgData) {
|
||||||
|
let posterHeight=imgData.height;
|
||||||
|
let posterWidth=imgData.width;
|
||||||
|
let imgPath =await base64ToPath(imgData.imgVal, '.jpeg');
|
||||||
|
this.$emit('renderFinish', {"posterPath":imgPath,"posterHeight":posterHeight,"posterWidth":posterWidth});
|
||||||
|
uni.hideLoading();
|
||||||
|
},
|
||||||
|
showLoading() {
|
||||||
|
uni.showLoading({
|
||||||
|
title: "正在生成导出",
|
||||||
|
icon: "none",
|
||||||
|
mask: true,
|
||||||
|
duration: 3000
|
||||||
|
})
|
||||||
|
},
|
||||||
|
hideLoading() {
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<script module="html2canvas" lang="renderjs">
|
||||||
|
import html2canvas from 'html2canvas';
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted:function(){
|
||||||
|
console.log("视图层渲染完成");
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 发送数据到逻辑层,下面这里最好是加一个settimeout延迟,因为主界面数据还没加载渲染完成
|
||||||
|
emitData(domId) {
|
||||||
|
this.$ownerInstance.callMethod('showLoading', true);
|
||||||
|
const dom = document.getElementById('poster');
|
||||||
|
console.log("dom",dom);
|
||||||
|
let width= dom.offsetWidth;
|
||||||
|
let height=dom.offsetHeight;
|
||||||
|
let windowHeight= uni.getSystemInfoSync().windowHeight;
|
||||||
|
let windowWidth=uni.getSystemInfoSync().windowWidth;
|
||||||
|
html2canvas(dom, {
|
||||||
|
width:width,
|
||||||
|
height:height,
|
||||||
|
//scale:2.5, // 缩放倍数
|
||||||
|
scrollY: 0, // html2canvas默认绘制视图内的页面,需要把scrollY,scrollX设置为0
|
||||||
|
scrollX: 0,
|
||||||
|
x:0,
|
||||||
|
y:0,
|
||||||
|
windowWidth:windowWidth,
|
||||||
|
windowHeight:windowHeight,
|
||||||
|
useCORS: true, //支持跨域,但好像没什么用
|
||||||
|
}).then((canvas) => {
|
||||||
|
let imgVal= canvas.toDataURL('image/png');
|
||||||
|
this.$ownerInstance.callMethod('receiveRenderData',{imgVal:imgVal,height:height,width:width});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<!-- 当父组件传递的prop属性数据发生变化的时候 ,生成海报图片-->
|
||||||
|
<view :prop="domId" :change:prop="html2canvas.emitData" class="html2canvas">
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { base64ToPath } from '@/utils/image-tools.js';
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
domId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted:function(){
|
||||||
|
console.log("组件加载完成");
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
// 接收renderjs发回的数据
|
||||||
|
async receiveRenderData(imgData) {
|
||||||
|
let posterHeight=imgData.height;
|
||||||
|
let posterWidth=imgData.width;
|
||||||
|
let imgPath =await base64ToPath(imgData.imgVal, '.jpeg');
|
||||||
|
this.$emit('renderFinish', {"posterPath":imgPath,"posterHeight":posterHeight,"posterWidth":posterWidth});
|
||||||
|
uni.hideLoading();
|
||||||
|
},
|
||||||
|
showLoading() {
|
||||||
|
uni.showLoading({
|
||||||
|
title: "正在生成导出",
|
||||||
|
icon: "none",
|
||||||
|
mask: true,
|
||||||
|
duration: 3000
|
||||||
|
})
|
||||||
|
},
|
||||||
|
hideLoading() {
|
||||||
|
uni.hideLoading();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<script module="html2canvas" lang="renderjs">
|
||||||
|
import html2canvas from 'html2canvas';
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted:function(){
|
||||||
|
console.log("视图层渲染完成");
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 发送数据到逻辑层,下面这里最好是加一个settimeout延迟,因为主界面数据还没加载渲染完成
|
||||||
|
emitData(domId) {
|
||||||
|
this.$ownerInstance.callMethod('showLoading', true);
|
||||||
|
const dom = document.getElementById('poster');
|
||||||
|
console.log("dom",dom);
|
||||||
|
let width= dom.offsetWidth;
|
||||||
|
let height=dom.offsetHeight;
|
||||||
|
let windowHeight= uni.getSystemInfoSync().windowHeight;
|
||||||
|
let windowWidth=uni.getSystemInfoSync().windowWidth;
|
||||||
|
html2canvas(dom, {
|
||||||
|
width:width,
|
||||||
|
height:height,
|
||||||
|
//scale:2.5, // 缩放倍数
|
||||||
|
scrollY: 0, // html2canvas默认绘制视图内的页面,需要把scrollY,scrollX设置为0
|
||||||
|
scrollX: 0,
|
||||||
|
x:0,
|
||||||
|
y:0,
|
||||||
|
windowWidth:windowWidth,
|
||||||
|
windowHeight:windowHeight,
|
||||||
|
useCORS: true, //支持跨域,但好像没什么用
|
||||||
|
}).then((canvas) => {
|
||||||
|
let imgVal= canvas.toDataURL('image/png');
|
||||||
|
this.$ownerInstance.callMethod('receiveRenderData',{imgVal:imgVal,height:height,width:width});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<view class="dialog-container" @click.stop>
|
<view class="dialog-container" @click.stop>
|
||||||
<!-- 弹窗标题 -->
|
<!-- 弹窗标题 -->
|
||||||
<view class="dialog-header">
|
<view class="dialog-header">
|
||||||
<text class="dialog-title">{{ title }}</text>
|
<text class="dialog-title" :style="{ color: titleColor }">{{ title }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 弹窗内容 -->
|
<!-- 弹窗内容 -->
|
||||||
@@ -42,13 +42,13 @@
|
|||||||
|
|
||||||
@click="oncancel"
|
@click="oncancel"
|
||||||
>
|
>
|
||||||
<text class="btn-text">取消</text>
|
<text class="btn-text">{{ cancelText }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view
|
||||||
class="dialog-btn confirm"
|
class="dialog-btn confirm"
|
||||||
@click="onconfirm"
|
@click="onconfirm"
|
||||||
>
|
>
|
||||||
<text class="btn-text">确定</text>
|
<text class="btn-text">{{ confirmText }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -63,6 +63,10 @@
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
|
titleColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#8B2316'
|
||||||
|
},
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '温馨提示'
|
default: '温馨提示'
|
||||||
@@ -130,6 +134,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dialog-container {
|
.dialog-container {
|
||||||
|
position: relative;
|
||||||
|
z-index:100;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border-radius: 20rpx;
|
border-radius: 20rpx;
|
||||||
width: 92%;
|
width: 92%;
|
||||||
|
|||||||
@@ -1,14 +1,68 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="emptybox">
|
<view class="emptybox">
|
||||||
<up-image :src="emptyImg" width="176rpx" height="204rpx" ></up-image>
|
<view class="empty-image-wrap" :style="imageWrapStyle">
|
||||||
<text class="empty-text">暂无数据</text>
|
<up-image
|
||||||
|
:src="emptyImage || emptyImg"
|
||||||
|
:width="renderWidth"
|
||||||
|
:height="renderHeight"
|
||||||
|
:mode="imgMode"
|
||||||
|
></up-image>
|
||||||
|
</view>
|
||||||
|
<text class="empty-text">{{ emptyDesc }}</text>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { onShow } from "@dcloudio/uni-app";
|
|
||||||
import emptyImg from "@/static/icon_empty.png"
|
import emptyImg from "@/static/icon_empty.png"
|
||||||
|
const props = defineProps({
|
||||||
|
emptyImage: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
imgWidth: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
imgHeight: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
emptyDesc: {
|
||||||
|
type: String,
|
||||||
|
default: '暂无数据'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const normalizeSize = (size) => {
|
||||||
|
if (size === '' || size === null || size === undefined) return '';
|
||||||
|
// 直传字符串(如 50%、206rpx、120px),数字交给 up-image 按组件规则处理
|
||||||
|
return typeof size === 'string' ? size.trim() : size;
|
||||||
|
};
|
||||||
|
const isPercentSize = (size) => typeof size === 'string' && size.endsWith('%');
|
||||||
|
|
||||||
|
const imgWidth = computed(() => {
|
||||||
|
const width = normalizeSize(props.imgWidth);
|
||||||
|
const height = normalizeSize(props.imgHeight);
|
||||||
|
if (width !== '') return width;
|
||||||
|
if (height === '') return '206rpx';
|
||||||
|
return '';
|
||||||
|
});
|
||||||
|
const imgHeight = computed(() => normalizeSize(props.imgHeight));
|
||||||
|
const renderWidth = computed(() => (isPercentSize(imgWidth.value) ? '100%' : imgWidth.value));
|
||||||
|
const renderHeight = computed(() => (isPercentSize(imgHeight.value) ? '100%' : imgHeight.value));
|
||||||
|
const imageWrapStyle = computed(() => {
|
||||||
|
const style = {};
|
||||||
|
if (isPercentSize(imgWidth.value)) style.width = imgWidth.value;
|
||||||
|
if (isPercentSize(imgHeight.value)) style.height = imgHeight.value;
|
||||||
|
return style;
|
||||||
|
});
|
||||||
|
const imgMode = computed(() => {
|
||||||
|
// 只传宽/高时按比例缩放,避免图片被拉伸
|
||||||
|
if (imgWidth.value && !imgHeight.value) return 'widthFix';
|
||||||
|
if (!imgWidth.value && imgHeight.value) return 'heightFix';
|
||||||
|
return 'aspectFit';
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@@ -21,6 +75,11 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
.empty-image-wrap{
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
.empty-text{
|
.empty-text{
|
||||||
font-size: 30rpx;
|
font-size: 30rpx;
|
||||||
color:#999;
|
color:#999;
|
||||||
|
|||||||
@@ -1,21 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- 顶部导航栏 -->
|
<!-- 顶部导航栏 -->
|
||||||
<uni-nav-bar
|
<view class="navbox">
|
||||||
left-icon="left"
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
|
:left-icon="showLeft?'left':''"
|
||||||
:title="title"
|
:title="title"
|
||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
/>
|
/>
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { onShow } from "@dcloudio/uni-app";
|
import { onShow } from "@dcloudio/uni-app";
|
||||||
const props=defineProps({
|
const props=defineProps({
|
||||||
|
showLeft:{
|
||||||
|
type:Boolean,
|
||||||
|
default:true
|
||||||
|
},
|
||||||
|
noticeBack:{
|
||||||
|
type:Boolean,
|
||||||
|
default:false
|
||||||
|
},
|
||||||
title:{
|
title:{
|
||||||
type:String,
|
type:String,
|
||||||
default:''
|
default:''
|
||||||
@@ -29,10 +38,21 @@
|
|||||||
url: '/pages/index/index'
|
url: '/pages/index/index'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.navbox{
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height:(var(--status-bar-height)+44px);
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
.status_bar{
|
||||||
|
height: var(--status-bar-height);
|
||||||
|
background-color: #eeeeee;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
* @file 拖动进度提示组件
|
||||||
|
*/
|
||||||
|
<template>
|
||||||
|
<view class="plv-player-drag-tips">
|
||||||
|
<view class="plv-player-drag-tips__box">
|
||||||
|
<image class="plv-player-drag-tips__direction-img" :src="imgSrc"
|
||||||
|
@error="imageError">
|
||||||
|
</image>
|
||||||
|
<text class="plv-player-drag-tips__time">
|
||||||
|
{{changeTimeFormat}} / {{durationFormat}}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import utils from '@/common/util.js';
|
||||||
|
import backImg from '@/static/skin/back.png';
|
||||||
|
import forwardImg from '@/static/skin/forward.png'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
currentTime: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
|
||||||
|
duration: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
|
||||||
|
changeTime: {
|
||||||
|
type: Number
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isForward: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
changeTime(newValue, oldValue){
|
||||||
|
this.isForward = newValue > oldValue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
timeFormatType() {
|
||||||
|
this.duration >= 3600 ? 2 : 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
changeTimeFormat() {
|
||||||
|
return utils.formatTimeByDuration(this.changeTime, this.timeFormatType);
|
||||||
|
},
|
||||||
|
|
||||||
|
durationFormat() {
|
||||||
|
return utils.formatTimeByDuration(this.duration, this.timeFormatType)
|
||||||
|
},
|
||||||
|
|
||||||
|
imgSrc() {
|
||||||
|
return this.isForward ? forwardImg : backImg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.plv-player-drag-tips {
|
||||||
|
width: 250rpx;
|
||||||
|
height: 160rpx;
|
||||||
|
background: rgba(0,0,0,.7);
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plv-player-drag-tips__box {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plv-player-drag-tips__direction-img {
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plv-player-drag-tips__time {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,271 @@
|
|||||||
|
<template>
|
||||||
|
<view class="plv-player-gesture"
|
||||||
|
@touchstart="touchstart"
|
||||||
|
@touchmove="touchmove"
|
||||||
|
@longpress="handleLongPress"
|
||||||
|
@touchcancel="handleTouchCancel"
|
||||||
|
@touchend="touchend">
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 屏幕宽度(物理像素)
|
||||||
|
holeWidth: Number,
|
||||||
|
// 视频总时长
|
||||||
|
duration: Number,
|
||||||
|
// 视频当前播放时间
|
||||||
|
currentTime: Number
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
halfWidth() {
|
||||||
|
return parseInt(this.holeWidth / 2);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 是否在左区域按下手势
|
||||||
|
downLeft: false,
|
||||||
|
// 滑动方向
|
||||||
|
swipeDir: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.addHandler();
|
||||||
|
},
|
||||||
|
|
||||||
|
methods:{
|
||||||
|
addHandler() {
|
||||||
|
// 增加父容器左右滑动监听
|
||||||
|
let finalTime = -1;
|
||||||
|
// 计算左右滑动seek进度
|
||||||
|
const countTime = (position) => {
|
||||||
|
const { holeWidth, duration, currentTime } = this;
|
||||||
|
const precent = Math.abs(position) / holeWidth;
|
||||||
|
const nowTime = currentTime || 0;
|
||||||
|
const constSecond = duration < 60 ? duration : 60;
|
||||||
|
let plusTime = parseInt(Math.abs(precent * constSecond));
|
||||||
|
if (position < 0) plusTime = plusTime * -1;
|
||||||
|
finalTime = nowTime + plusTime;
|
||||||
|
finalTime = this.limit(finalTime, 0, duration);
|
||||||
|
return finalTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.addGesture((type, position) => {
|
||||||
|
switch (type) {
|
||||||
|
// 下滑
|
||||||
|
case -1:
|
||||||
|
// console.log('//下滑');
|
||||||
|
this.$emit('onGestureEvent', {
|
||||||
|
type: this.downLeft ? 'LEFT_DOWN' : 'RIGHT_DOWN',
|
||||||
|
position
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
// 上滑
|
||||||
|
case -2:
|
||||||
|
// console.log('//上滑');
|
||||||
|
this.$emit('onGestureEvent', {
|
||||||
|
type: this.downLeft ? 'LEFT_UP' : 'RIGHT_UP',
|
||||||
|
position
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
// 左滑
|
||||||
|
case 0:
|
||||||
|
// console.log('//左滑');
|
||||||
|
this.swipeDir = type;
|
||||||
|
countTime(position);
|
||||||
|
this.$emit('onGestureEvent', {
|
||||||
|
type: 'SEEK_TIME_UPDATE',
|
||||||
|
finalTime
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
// 右滑
|
||||||
|
case 1:
|
||||||
|
// console.log('//右滑');
|
||||||
|
this.swipeDir = type;
|
||||||
|
countTime(position);
|
||||||
|
this.$emit('onGestureEvent', {
|
||||||
|
type: 'SEEK_TIME_UPDATE',
|
||||||
|
finalTime
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
// touchend for swipe
|
||||||
|
case 3:
|
||||||
|
if (this.swipeDir > -1) {
|
||||||
|
this.$emit('onGestureEvent', {
|
||||||
|
type: this.swipeDir ? 'SWIPE_RIGHT' : 'SWIPE_LEFT'
|
||||||
|
});
|
||||||
|
this.swipeDir = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finalTime > -1) {
|
||||||
|
this.$emit('onGestureSeekTo', finalTime);
|
||||||
|
finalTime = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// doubleTap
|
||||||
|
case 4:
|
||||||
|
// console.log('>>>> 双击');
|
||||||
|
this.$emit('onGestureEvent', {
|
||||||
|
type: 'DOUBLE_CLICK'
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
// tap
|
||||||
|
case 5:
|
||||||
|
// console.log('>>>> 单击');
|
||||||
|
this.handleClick();
|
||||||
|
break;
|
||||||
|
// longTap
|
||||||
|
case 6:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
addGesture(callback) {
|
||||||
|
const { options } = this;
|
||||||
|
let startX, startY, moveEndX, moveEndY, X, Y, position, hasType;
|
||||||
|
let T, lastTap, isJustTouch = true;
|
||||||
|
|
||||||
|
|
||||||
|
const excuteCb = (type) => {
|
||||||
|
// type 手势类型 -2 上滑 -1 下滑 0 左滑 1 右滑 2 just touch 3 touchend 4 doubleTap 5 tap 6 longTap
|
||||||
|
if (callback && typeof callback === 'function')
|
||||||
|
callback(type, position);
|
||||||
|
};
|
||||||
|
|
||||||
|
const YPlus = 20;
|
||||||
|
const YReduce = YPlus * -1;
|
||||||
|
const XPlus = 50;
|
||||||
|
const XReduce = XPlus * -1;
|
||||||
|
|
||||||
|
const isXchange = () => {
|
||||||
|
if (X > XPlus || X < XReduce) {
|
||||||
|
position = X;
|
||||||
|
hasType = 'X';
|
||||||
|
isJustTouch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (X > XPlus) excuteCb(1);
|
||||||
|
// 左滑
|
||||||
|
else if (X < XReduce) excuteCb(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isYchange = () => {
|
||||||
|
if (Y > YPlus || Y < YReduce) {
|
||||||
|
position = Y;
|
||||||
|
hasType = 'Y';
|
||||||
|
isJustTouch = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Y > YPlus) excuteCb(-1);
|
||||||
|
// 上滑
|
||||||
|
else if (Y < YReduce) excuteCb(-2);
|
||||||
|
};
|
||||||
|
|
||||||
|
const countDirect = () => {
|
||||||
|
if (hasType) {
|
||||||
|
hasType === 'X' ? isXchange() : isYchange();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isXchange();
|
||||||
|
isYchange();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.handleTouch = (type, e) => {
|
||||||
|
switch(type) {
|
||||||
|
case 'start':
|
||||||
|
startX = e.changedTouches[0].pageX;
|
||||||
|
startY = e.changedTouches[0].pageY;
|
||||||
|
T = Date.now();
|
||||||
|
hasType = '';
|
||||||
|
isJustTouch = true;
|
||||||
|
this.downLeft = startX < this.halfWidth ? true : false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'move':
|
||||||
|
moveEndX = e.changedTouches[0].pageX;
|
||||||
|
moveEndY = e.changedTouches[0].pageY;
|
||||||
|
X = moveEndX - startX;
|
||||||
|
Y = moveEndY - startY;
|
||||||
|
countDirect();
|
||||||
|
break;
|
||||||
|
case 'end':
|
||||||
|
if (isJustTouch)
|
||||||
|
if (lastTap && Date.now() - lastTap <= 300)
|
||||||
|
excuteCb(4);
|
||||||
|
else if (Date.now() - T < 1000)
|
||||||
|
excuteCb(5);
|
||||||
|
else
|
||||||
|
excuteCb(6);
|
||||||
|
else
|
||||||
|
excuteCb(3);
|
||||||
|
|
||||||
|
lastTap = Date.now();
|
||||||
|
isJustTouch = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
handleClick() {
|
||||||
|
this.$emit('onGestureClick');
|
||||||
|
},
|
||||||
|
|
||||||
|
touchstart(e) {
|
||||||
|
this.handleTouch('start', e);
|
||||||
|
},
|
||||||
|
|
||||||
|
touchmove(e) {
|
||||||
|
this.handleTouch('move', e);
|
||||||
|
},
|
||||||
|
|
||||||
|
touchend(e) {
|
||||||
|
this.handleTouch('end', e);
|
||||||
|
this.$emit('onTouchEnd');
|
||||||
|
},
|
||||||
|
|
||||||
|
handleTouchCancel() {
|
||||||
|
this.$emit('onTouchCancel');
|
||||||
|
},
|
||||||
|
|
||||||
|
handleLongPress() {
|
||||||
|
this.$emit('onLongPress');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 控制最小值,最大值
|
||||||
|
* @param num
|
||||||
|
* @param min
|
||||||
|
* @param max
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
limit(num, min, max) {
|
||||||
|
if (num < min) return min;
|
||||||
|
if (num > max) return max;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.plv-player-gesture {
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plv-player-gesture__left {
|
||||||
|
flex: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plv-player-gesture__right {
|
||||||
|
flex: 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<template>
|
||||||
|
<view v-if="isShow" class="plv-player-icon">
|
||||||
|
<image class="plv-player-icon__img" :src="imgUrl"></image>
|
||||||
|
<text class="plv-player-icon__text">{{ precent + '%' }}</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
imgUrl: {
|
||||||
|
type: 'string',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
precent: {
|
||||||
|
type: 'Number',
|
||||||
|
default: 100,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
precent(num) {
|
||||||
|
if (!this.isShow) this.isShow = true;
|
||||||
|
this.startClock();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isShow: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
startClock() {
|
||||||
|
this.clearClock();
|
||||||
|
|
||||||
|
this.clock = setTimeout(() => {
|
||||||
|
this.isShow = false;
|
||||||
|
}, 1500);
|
||||||
|
},
|
||||||
|
|
||||||
|
clearClock() {
|
||||||
|
if (this.clock) clearTimeout(this.clock);
|
||||||
|
this.clock = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.plv-player-icon {
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plv-player-icon__img {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plv-player-icon__text {
|
||||||
|
color: #FFFFFF;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,92 @@
|
|||||||
|
<template>
|
||||||
|
<view v-if="isShow" class="plv-player-volume-wrap">
|
||||||
|
<image class="plv-player-volume__img" :src="value === 0 ? muteImgUrl : imgUrl "></image>
|
||||||
|
<view class="plv-player-volume__progress">
|
||||||
|
<view class="plv-player-volume__progress__played" :style="'flex:' + value"></view>
|
||||||
|
<view class="plv-player-volume__progress_surplus" :style="'flex:' + valueLeft"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
imgUrl: {
|
||||||
|
type: 'string',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
muteImgUrl: {
|
||||||
|
type: 'string',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: 'Number',
|
||||||
|
default: 0.5,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
value(num) {
|
||||||
|
if (!this.isShow) this.isShow = true;
|
||||||
|
this.startClock();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
valueLeft() {
|
||||||
|
return 1 - this.value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isShow: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
startClock() {
|
||||||
|
this.clearClock();
|
||||||
|
|
||||||
|
this.clock = setTimeout(() => {
|
||||||
|
this.isShow = false;
|
||||||
|
}, 1500);
|
||||||
|
},
|
||||||
|
|
||||||
|
clearClock() {
|
||||||
|
if (this.clock) clearTimeout(this.clock);
|
||||||
|
this.clock = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.plv-player-volume-wrap {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plv-player-volume__img {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plv-player-volume__progress {
|
||||||
|
width: 260rpx;
|
||||||
|
height: 8rpx;
|
||||||
|
flex-direction: row;
|
||||||
|
background-color: #09BB07;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plv-player-volume__progress__played {
|
||||||
|
background-color: #007AFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plv-player-volume__progress_surplus {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
v-for="(item, index) in tabList"
|
v-for="(item, index) in tabList"
|
||||||
:key="index"
|
:key="index"
|
||||||
@click="switchTab(index, item)"
|
@click="switchTab(index, item)"
|
||||||
:class="{ active: currentTab === index }"
|
:class="{ active: 2 === index }"
|
||||||
>
|
>
|
||||||
<!-- 图标容器 -->
|
<!-- 图标容器 -->
|
||||||
<view class="icon-container">
|
<view class="icon-container">
|
||||||
@@ -33,11 +33,13 @@
|
|||||||
<!-- <view class="active-indicator" v-if="currentTab === index"></view> -->
|
<!-- <view class="active-indicator" v-if="currentTab === index"></view> -->
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<GlobalDialog />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, onMounted, nextTick } from 'vue';
|
import { ref, reactive, onMounted, nextTick } from 'vue';
|
||||||
import { onShow, onLoad } from "@dcloudio/uni-app";
|
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||||
|
import GlobalDialog from "@/components/GlobalDialog.vue"
|
||||||
import home from '@/static/home_nor.png'
|
import home from '@/static/home_nor.png'
|
||||||
import homeOn from '@/static/home_sel.png'
|
import homeOn from '@/static/home_sel.png'
|
||||||
import classroom from "@/static/classroom.png"
|
import classroom from "@/static/classroom.png"
|
||||||
@@ -70,7 +72,7 @@
|
|||||||
activeColor: '#007aff',
|
activeColor: '#007aff',
|
||||||
badge: 0,
|
badge: 0,
|
||||||
showRedDot: false,
|
showRedDot: false,
|
||||||
pagePath: '/pages/index/index'
|
pagePath: '/pages/index/index?from=push'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: classroom,
|
icon: classroom,
|
||||||
@@ -119,32 +121,56 @@
|
|||||||
if (currentTab.value === index) return;
|
if (currentTab.value === index) return;
|
||||||
|
|
||||||
// 更新当前tab
|
// 更新当前tab
|
||||||
currentTab.value = index;
|
//currentTab.value = index;
|
||||||
|
let msg="home"
|
||||||
// 清除红点
|
if(index == 0){
|
||||||
if (item.showRedDot) {
|
msg="home"
|
||||||
item.showRedDot = false;
|
}else if(index == 1){
|
||||||
|
msg="patientClass"
|
||||||
|
}else if(index == 2){
|
||||||
|
msg="live"
|
||||||
|
}else if(index == 3){
|
||||||
|
msg="education"
|
||||||
|
}else if(index == 4){
|
||||||
|
msg="mine"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
uni.sendNativeEvent('goTabbarPage', {
|
||||||
|
msg: msg
|
||||||
|
},ret => {
|
||||||
|
|
||||||
|
console.log(ret);
|
||||||
|
})
|
||||||
|
}catch(e){
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
plus.runtime.quit()
|
||||||
|
// 清除红点
|
||||||
|
// if (item.showRedDot) {
|
||||||
|
// item.showRedDot = false;
|
||||||
|
// }
|
||||||
|
|
||||||
// 页面跳转
|
// 页面跳转
|
||||||
uni.redirectTo({
|
// uni.redirectTo({
|
||||||
url: item.pagePath,
|
// url: item.pagePath,
|
||||||
fail: () => {
|
// fail: () => {
|
||||||
// 如果页面不存在,使用navigateTo
|
// // 如果页面不存在,使用navigateTo
|
||||||
uni.navigateTo({
|
// uni.navigateTo({
|
||||||
url: item.pagePath,
|
// url: item.pagePath,
|
||||||
fail: () => {
|
// fail: () => {
|
||||||
|
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
// 触发父组件事件
|
// 触发父组件事件
|
||||||
emit('tabChange', {
|
// emit('tabChange', {
|
||||||
index,
|
// index,
|
||||||
item
|
// item
|
||||||
});
|
// });
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 设置徽章数量
|
// 设置徽章数量
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<template>
|
||||||
|
<view class="top-tip" v-if="visible">
|
||||||
|
<view class="title">{{ title }}</view>
|
||||||
|
<view class="content">
|
||||||
|
{{ content }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const open = () => {
|
||||||
|
visible.value = true
|
||||||
|
}
|
||||||
|
const close = () => {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
close
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.top-tip{
|
||||||
|
position: fixed;
|
||||||
|
top: 180rpx;
|
||||||
|
left: 40rpx;
|
||||||
|
right:40rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
background-color: rgba(0, 0, 0, 0.8);
|
||||||
|
z-index: 99999999999;
|
||||||
|
.title{
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #fff;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
}
|
||||||
|
.content{
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #fff;
|
||||||
|
text-align: left;
|
||||||
|
margin-top: 25rpx;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,273 @@
|
|||||||
|
/**
|
||||||
|
* 本模块封装了Android、iOS的应用权限判断、打开应用权限设置界面、以及位置系统服务是否开启
|
||||||
|
*/
|
||||||
|
|
||||||
|
var isIos
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
isIos = (plus.os.name == "iOS")
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// 判断推送权限是否开启
|
||||||
|
function judgeIosPermissionPush() {
|
||||||
|
var result = false;
|
||||||
|
var UIApplication = plus.ios.import("UIApplication");
|
||||||
|
var app = UIApplication.sharedApplication();
|
||||||
|
var enabledTypes = 0;
|
||||||
|
if (app.currentUserNotificationSettings) {
|
||||||
|
var settings = app.currentUserNotificationSettings();
|
||||||
|
enabledTypes = settings.plusGetAttribute("types");
|
||||||
|
console.log("enabledTypes1:" + enabledTypes);
|
||||||
|
if (enabledTypes == 0) {
|
||||||
|
console.log("推送权限没有开启");
|
||||||
|
} else {
|
||||||
|
result = true;
|
||||||
|
console.log("已经开启推送功能!")
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(settings);
|
||||||
|
} else {
|
||||||
|
enabledTypes = app.enabledRemoteNotificationTypes();
|
||||||
|
if (enabledTypes == 0) {
|
||||||
|
console.log("推送权限没有开启!");
|
||||||
|
} else {
|
||||||
|
result = true;
|
||||||
|
console.log("已经开启推送功能!")
|
||||||
|
}
|
||||||
|
console.log("enabledTypes2:" + enabledTypes);
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(app);
|
||||||
|
plus.ios.deleteObject(UIApplication);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断定位权限是否开启
|
||||||
|
function judgeIosPermissionLocation() {
|
||||||
|
var result = false;
|
||||||
|
var cllocationManger = plus.ios.import("CLLocationManager");
|
||||||
|
var status = cllocationManger.authorizationStatus();
|
||||||
|
result = (status != 2)
|
||||||
|
console.log("定位权限开启:" + result);
|
||||||
|
// 以下代码判断了手机设备的定位是否关闭,推荐另行使用方法 checkSystemEnableLocation
|
||||||
|
/* var enable = cllocationManger.locationServicesEnabled();
|
||||||
|
var status = cllocationManger.authorizationStatus();
|
||||||
|
console.log("enable:" + enable);
|
||||||
|
console.log("status:" + status);
|
||||||
|
if (enable && status != 2) {
|
||||||
|
result = true;
|
||||||
|
console.log("手机定位服务已开启且已授予定位权限");
|
||||||
|
} else {
|
||||||
|
console.log("手机系统的定位没有打开或未给予定位权限");
|
||||||
|
} */
|
||||||
|
plus.ios.deleteObject(cllocationManger);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断麦克风权限是否开启
|
||||||
|
function judgeIosPermissionRecord() {
|
||||||
|
var result = false;
|
||||||
|
var avaudiosession = plus.ios.import("AVAudioSession");
|
||||||
|
var avaudio = avaudiosession.sharedInstance();
|
||||||
|
var permissionStatus = avaudio.recordPermission();
|
||||||
|
console.log("permissionStatus:" + permissionStatus);
|
||||||
|
if (permissionStatus == 1684369017 || permissionStatus == 1970168948) {
|
||||||
|
console.log("麦克风权限没有开启");
|
||||||
|
} else {
|
||||||
|
result = true;
|
||||||
|
console.log("麦克风权限已经开启");
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(avaudiosession);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断相机权限是否开启
|
||||||
|
function judgeIosPermissionCamera() {
|
||||||
|
var result = false;
|
||||||
|
var AVCaptureDevice = plus.ios.import("AVCaptureDevice");
|
||||||
|
var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');
|
||||||
|
console.log("authStatus:" + authStatus);
|
||||||
|
if (authStatus == 3) {
|
||||||
|
result = true;
|
||||||
|
console.log("相机权限已经开启");
|
||||||
|
} else {
|
||||||
|
console.log("相机权限没有开启");
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(AVCaptureDevice);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断相册权限是否开启
|
||||||
|
function judgeIosPermissionPhotoLibrary() {
|
||||||
|
var result = false;
|
||||||
|
var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
|
||||||
|
var authStatus = PHPhotoLibrary.authorizationStatus();
|
||||||
|
console.log("authStatus:" + authStatus);
|
||||||
|
if (authStatus == 3) {
|
||||||
|
result = true;
|
||||||
|
console.log("相册权限已经开启");
|
||||||
|
} else {
|
||||||
|
console.log("相册权限没有开启");
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(PHPhotoLibrary);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断通讯录权限是否开启
|
||||||
|
function judgeIosPermissionContact() {
|
||||||
|
var result = false;
|
||||||
|
var CNContactStore = plus.ios.import("CNContactStore");
|
||||||
|
var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);
|
||||||
|
if (cnAuthStatus == 3) {
|
||||||
|
result = true;
|
||||||
|
console.log("通讯录权限已经开启");
|
||||||
|
} else {
|
||||||
|
console.log("通讯录权限没有开启");
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(CNContactStore);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断日历权限是否开启
|
||||||
|
function judgeIosPermissionCalendar() {
|
||||||
|
var result = false;
|
||||||
|
var EKEventStore = plus.ios.import("EKEventStore");
|
||||||
|
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);
|
||||||
|
if (ekAuthStatus == 3) {
|
||||||
|
result = true;
|
||||||
|
console.log("日历权限已经开启");
|
||||||
|
} else {
|
||||||
|
console.log("日历权限没有开启");
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(EKEventStore);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断备忘录权限是否开启
|
||||||
|
function judgeIosPermissionMemo() {
|
||||||
|
var result = false;
|
||||||
|
var EKEventStore = plus.ios.import("EKEventStore");
|
||||||
|
var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);
|
||||||
|
if (ekAuthStatus == 3) {
|
||||||
|
result = true;
|
||||||
|
console.log("备忘录权限已经开启");
|
||||||
|
} else {
|
||||||
|
console.log("备忘录权限没有开启");
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(EKEventStore);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Android权限查询
|
||||||
|
function requestAndroidPermission(permissionID) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
plus.android.requestPermissions(
|
||||||
|
[permissionID], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
|
||||||
|
function(resultObj) {
|
||||||
|
var result = 0;
|
||||||
|
for (var i = 0; i < resultObj.granted.length; i++) {
|
||||||
|
var grantedPermission = resultObj.granted[i];
|
||||||
|
console.log('已获取的权限:' + grantedPermission);
|
||||||
|
result = 1
|
||||||
|
}
|
||||||
|
for (var i = 0; i < resultObj.deniedPresent.length; i++) {
|
||||||
|
var deniedPresentPermission = resultObj.deniedPresent[i];
|
||||||
|
console.log('拒绝本次申请的权限:' + deniedPresentPermission);
|
||||||
|
result = 0
|
||||||
|
}
|
||||||
|
for (var i = 0; i < resultObj.deniedAlways.length; i++) {
|
||||||
|
var deniedAlwaysPermission = resultObj.deniedAlways[i];
|
||||||
|
console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
|
||||||
|
result = -1
|
||||||
|
}
|
||||||
|
resolve(result);
|
||||||
|
// 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
|
||||||
|
// if (result != 1) {
|
||||||
|
// gotoAppPermissionSetting()
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
function(error) {
|
||||||
|
console.log('申请权限错误:' + error.code + " = " + error.message);
|
||||||
|
resolve({
|
||||||
|
code: error.code,
|
||||||
|
message: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用一个方法,根据参数判断权限
|
||||||
|
function judgeIosPermission(permissionID) {
|
||||||
|
if (permissionID == "location") {
|
||||||
|
return judgeIosPermissionLocation()
|
||||||
|
} else if (permissionID == "camera") {
|
||||||
|
return judgeIosPermissionCamera()
|
||||||
|
} else if (permissionID == "photoLibrary") {
|
||||||
|
return judgeIosPermissionPhotoLibrary()
|
||||||
|
} else if (permissionID == "record") {
|
||||||
|
return judgeIosPermissionRecord()
|
||||||
|
} else if (permissionID == "push") {
|
||||||
|
return judgeIosPermissionPush()
|
||||||
|
} else if (permissionID == "contact") {
|
||||||
|
return judgeIosPermissionContact()
|
||||||
|
} else if (permissionID == "calendar") {
|
||||||
|
return judgeIosPermissionCalendar()
|
||||||
|
} else if (permissionID == "memo") {
|
||||||
|
return judgeIosPermissionMemo()
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到**应用**的权限页面
|
||||||
|
function gotoAppPermissionSetting() {
|
||||||
|
if (isIos) {
|
||||||
|
var UIApplication = plus.ios.import("UIApplication");
|
||||||
|
var application2 = UIApplication.sharedApplication();
|
||||||
|
var NSURL2 = plus.ios.import("NSURL");
|
||||||
|
// var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");
|
||||||
|
var setting2 = NSURL2.URLWithString("app-settings:");
|
||||||
|
application2.openURL(setting2);
|
||||||
|
|
||||||
|
plus.ios.deleteObject(setting2);
|
||||||
|
plus.ios.deleteObject(NSURL2);
|
||||||
|
plus.ios.deleteObject(application2);
|
||||||
|
} else {
|
||||||
|
// console.log(plus.device.vendor);
|
||||||
|
var Intent = plus.android.importClass("android.content.Intent");
|
||||||
|
var Settings = plus.android.importClass("android.provider.Settings");
|
||||||
|
var Uri = plus.android.importClass("android.net.Uri");
|
||||||
|
var mainActivity = plus.android.runtimeMainActivity();
|
||||||
|
var intent = new Intent();
|
||||||
|
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||||
|
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
|
||||||
|
intent.setData(uri);
|
||||||
|
mainActivity.startActivity(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查系统的设备服务是否开启
|
||||||
|
// var checkSystemEnableLocation = async function () {
|
||||||
|
function checkSystemEnableLocation() {
|
||||||
|
if (isIos) {
|
||||||
|
var result = false;
|
||||||
|
var cllocationManger = plus.ios.import("CLLocationManager");
|
||||||
|
var result = cllocationManger.locationServicesEnabled();
|
||||||
|
console.log("系统定位开启:" + result);
|
||||||
|
plus.ios.deleteObject(cllocationManger);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
var context = plus.android.importClass("android.content.Context");
|
||||||
|
var locationManager = plus.android.importClass("android.location.LocationManager");
|
||||||
|
var main = plus.android.runtimeMainActivity();
|
||||||
|
var mainSvr = main.getSystemService(context.LOCATION_SERVICE);
|
||||||
|
var result = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER);
|
||||||
|
console.log("系统定位开启:" + result);
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// module.exports = {
|
||||||
|
// judgeIosPermission: judgeIosPermission,
|
||||||
|
// requestAndroidPermission: requestAndroidPermission,
|
||||||
|
// checkSystemEnableLocation: checkSystemEnableLocation,
|
||||||
|
// gotoAppPermissionSetting: gotoAppPermissionSetting
|
||||||
|
// }
|
||||||
|
export default {judgeIosPermission,requestAndroidPermission,checkSystemEnableLocation,gotoAppPermissionSetting}
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
|
|
||||||
|
// ES6模块化引入
|
||||||
|
//import VConsole from 'vconsole'
|
||||||
import App from './App'
|
import App from './App'
|
||||||
import uviewPlus, { setConfig } from 'uview-plus'
|
import uviewPlus, { setConfig } from 'uview-plus'
|
||||||
|
//const vConsole = new VConsole();
|
||||||
// #ifndef VUE3
|
// #ifndef VUE3
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import './uni.promisify.adaptor'
|
import './uni.promisify.adaptor'
|
||||||
|
|||||||
+107
-26
@@ -1,12 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name" : "肝胆相照专家端",
|
"name" : "肝胆相照专家版",
|
||||||
"appid" : "__UNI__89F511F",
|
"appid" : "__UNI__89F511F",
|
||||||
"description" : "",
|
"description" : "",
|
||||||
"versionName" : "1.0.0",
|
"versionName" : "4.2.7",
|
||||||
"versionCode" : "100",
|
"versionCode" : 427,
|
||||||
"transformPx" : false,
|
"transformPx" : false,
|
||||||
"app-plus" : {
|
"app-plus" : {
|
||||||
/* 5+App特有相关 */
|
/* 5+App特有相关 */
|
||||||
|
"runmode" : "liberate",
|
||||||
"usingComponents" : true,
|
"usingComponents" : true,
|
||||||
"nvueCompiler" : "uni-app",
|
"nvueCompiler" : "uni-app",
|
||||||
"nvueStyleCompiler" : "uni-app",
|
"nvueStyleCompiler" : "uni-app",
|
||||||
@@ -16,17 +17,28 @@
|
|||||||
"autoclose" : true,
|
"autoclose" : true,
|
||||||
"delay" : 0
|
"delay" : 0
|
||||||
},
|
},
|
||||||
|
"compatible" : {
|
||||||
|
"ignoreVersion" : true
|
||||||
|
},
|
||||||
|
"useragent" : {
|
||||||
|
"value" : "gdxz",
|
||||||
|
"concatenate" : true
|
||||||
|
},
|
||||||
"modules" : {
|
"modules" : {
|
||||||
"OAuth" : {},
|
|
||||||
"Payment" : {},
|
|
||||||
"Share" : {},
|
"Share" : {},
|
||||||
"Webview-x5" : {},
|
"Webview-x5" : {},
|
||||||
"UIWebview" : {}
|
"UIWebview" : {},
|
||||||
|
"VideoPlayer" : {},
|
||||||
|
"OAuth" : {},
|
||||||
|
"Barcode" : {},
|
||||||
|
"Camera" : {},
|
||||||
|
"Payment" : {}
|
||||||
},
|
},
|
||||||
/* 模块配置 */
|
/* 模块配置 */
|
||||||
"distribute" : {
|
"distribute" : {
|
||||||
/* 应用发布信息 */
|
/* 应用发布信息 */
|
||||||
"android" : {
|
"android" : {
|
||||||
|
"hasTaskAffinity" : true,
|
||||||
/* android打包配置 */
|
/* android打包配置 */
|
||||||
"permissions" : [
|
"permissions" : [
|
||||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||||
@@ -45,19 +57,31 @@
|
|||||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||||
],
|
],
|
||||||
"abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ]
|
"abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ],
|
||||||
|
"minSdkVersion" : 21,
|
||||||
|
"targetSdkVersion" : 30
|
||||||
},
|
},
|
||||||
"ios" : {
|
"ios" : {
|
||||||
"dSYMs" : false,
|
"dSYMs" : false,
|
||||||
"idfa" : false
|
"idfa" : false,
|
||||||
|
"urlschemewhitelist" : [ "weixin", "wechat" ],
|
||||||
|
"permission" : {
|
||||||
|
"NSPhotoLibraryUsageDescription" : "需要访问相册以选择图片",
|
||||||
|
"NSCameraUsageDescription" : "需要访问相机以拍照"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/* ios打包配置 */
|
/* ios打包配置 */
|
||||||
"sdkConfigs" : {
|
"sdkConfigs" : {
|
||||||
"oauth" : {
|
"oauth" : {
|
||||||
"weixin" : {
|
"weixin" : {
|
||||||
"appid" : "wxbf3658f5e674667c",
|
"appid" : "wxbf3658f5e674667c",
|
||||||
"appsecret" : "c4505a04a9910c65efea8e11ffc93f92",
|
|
||||||
"UniversalLinks" : "https://doc.igandan.com/gdxzExpert/"
|
"UniversalLinks" : "https://doc.igandan.com/gdxzExpert/"
|
||||||
|
},
|
||||||
|
"univerify" : {},
|
||||||
|
"sina" : {
|
||||||
|
"appkey" : "2071931330",
|
||||||
|
"redirect_uri" : "http://sns.whalecloud.com/sina2/callback",
|
||||||
|
"UniversalLinks" : ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"payment" : {
|
"payment" : {
|
||||||
@@ -72,49 +96,104 @@
|
|||||||
"weixin" : {
|
"weixin" : {
|
||||||
"appid" : "wxbf3658f5e674667c",
|
"appid" : "wxbf3658f5e674667c",
|
||||||
"UniversalLinks" : "https://doc.igandan.com/gdxzExpert/"
|
"UniversalLinks" : "https://doc.igandan.com/gdxzExpert/"
|
||||||
|
},
|
||||||
|
"sina" : {
|
||||||
|
"appkey" : "2071931330",
|
||||||
|
"redirect_uri" : "http://sns.whalecloud.com/sina2/callback",
|
||||||
|
"UniversalLinks" : "https://doc.igandan.com/gdxzExpert/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"speech" : {}
|
"speech" : {},
|
||||||
|
"push" : {}
|
||||||
},
|
},
|
||||||
"splashscreen" : {
|
"splashscreen" : {
|
||||||
"androidStyle" : "common"
|
"androidStyle" : "common",
|
||||||
|
"useOriginalMsgbox" : false,
|
||||||
|
"iosStyle" : "common"
|
||||||
},
|
},
|
||||||
"icons" : {
|
"icons" : {
|
||||||
"android" : {
|
"android" : {
|
||||||
"hdpi" : "D:/haomi/Documents/WeChat Files/wxid_x5u4rycntnkq21/FileStorage/File/2025-09/专家版图标/专家版图标/72.png",
|
"hdpi" : "D:/uniapp/专家版图标/72.png",
|
||||||
"xhdpi" : "D:/haomi/Documents/WeChat Files/wxid_x5u4rycntnkq21/FileStorage/File/2025-09/专家版图标/专家版图标/96.png",
|
"xhdpi" : "D:/uniapp/专家版图标/96.png",
|
||||||
"xxhdpi" : "D:/haomi/Documents/WeChat Files/wxid_x5u4rycntnkq21/FileStorage/File/2025-09/专家版图标/专家版图标/144.png",
|
"xxhdpi" : "D:/uniapp/专家版图标/144.png",
|
||||||
"xxxhdpi" : "D:/haomi/Documents/WeChat Files/wxid_x5u4rycntnkq21/FileStorage/File/2025-09/专家版图标/专家版图标/192.png"
|
"xxxhdpi" : "D:/uniapp/专家版图标/192.png"
|
||||||
},
|
},
|
||||||
"ios" : {
|
"ios" : {
|
||||||
"appstore" : "D:/haomi/Documents/WeChat Files/wxid_x5u4rycntnkq21/FileStorage/File/2025-09/专家版图标/专家版图标/1024.png",
|
"appstore" : "D:/uniapp/专家版图标/1024.png",
|
||||||
"iphone" : {
|
"iphone" : {
|
||||||
"app@2x" : "D:/haomi/Documents/WeChat Files/wxid_x5u4rycntnkq21/FileStorage/File/2025-09/专家版图标/专家版图标/120.png",
|
"app@2x" : "D:/uniapp/专家版图标/120.png",
|
||||||
"app@3x" : "D:/haomi/Documents/WeChat Files/wxid_x5u4rycntnkq21/FileStorage/File/2025-09/专家版图标/专家版图标/180.png",
|
"app@3x" : "D:/uniapp/专家版图标/180.png",
|
||||||
"spotlight@2x" : "D:/haomi/Documents/WeChat Files/wxid_x5u4rycntnkq21/FileStorage/File/2025-09/专家版图标/专家版图标/80.png",
|
"spotlight@2x" : "D:/uniapp/专家版图标/80.png",
|
||||||
"spotlight@3x" : "D:/haomi/Documents/WeChat Files/wxid_x5u4rycntnkq21/FileStorage/File/2025-09/专家版图标/专家版图标/120.png",
|
"spotlight@3x" : "D:/uniapp/专家版图标/120.png",
|
||||||
"settings@2x" : "D:/haomi/Documents/WeChat Files/wxid_x5u4rycntnkq21/FileStorage/File/2025-09/专家版图标/专家版图标/58.png",
|
"settings@2x" : "D:/uniapp/专家版图标/58.png",
|
||||||
"settings@3x" : "D:/haomi/Documents/WeChat Files/wxid_x5u4rycntnkq21/FileStorage/File/2025-09/专家版图标/专家版图标/87.png",
|
"settings@3x" : "D:/uniapp/专家版图标/87.png",
|
||||||
"notification@2x" : "D:/haomi/Documents/WeChat Files/wxid_x5u4rycntnkq21/FileStorage/File/2025-09/专家版图标/专家版图标/40.png",
|
"notification@2x" : "D:/uniapp/专家版图标/40.png",
|
||||||
"notification@3x" : "D:/haomi/Documents/WeChat Files/wxid_x5u4rycntnkq21/FileStorage/File/2025-09/专家版图标/专家版图标/60.png"
|
"notification@3x" : "D:/uniapp/专家版图标/60.png"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"nativePlugins" : {
|
"nativePlugins" : {
|
||||||
|
"NIMUniPlugin" : {
|
||||||
|
"PUSH_VIVO_APPID" : "100034326",
|
||||||
|
"PUSH_VIVO_APPKEY" : "e789634c1f76c8f184b1def1101ce824",
|
||||||
|
"PUSH_HONOR_APPID" : "900782424",
|
||||||
|
"__plugin_info__" : {
|
||||||
|
"name" : "NIMUniPlugin",
|
||||||
|
"description" : "uni消息推送插件",
|
||||||
|
"platforms" : "Android,iOS",
|
||||||
|
"url" : "",
|
||||||
|
"android_package_name" : "",
|
||||||
|
"ios_bundle_id" : "",
|
||||||
|
"isCloud" : false,
|
||||||
|
"bought" : -1,
|
||||||
|
"pid" : "",
|
||||||
|
"parameters" : {
|
||||||
|
"PUSH_VIVO_APPID" : {
|
||||||
|
"des" : "厂商VIVO-app_id",
|
||||||
|
"key" : "com.vivo.push.app_id",
|
||||||
|
"value" : ""
|
||||||
|
},
|
||||||
|
"PUSH_VIVO_APPKEY" : {
|
||||||
|
"des" : "厂商VIVO-app_key",
|
||||||
|
"key" : "com.vivo.push.api_key",
|
||||||
|
"value" : ""
|
||||||
|
},
|
||||||
|
"PUSH_HONOR_APPID" : {
|
||||||
|
"des" : "厂商HONOR-app_id",
|
||||||
|
"key" : "com.hihonor.push.app_id",
|
||||||
|
"value" : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"PLV-MediaPlayer" : {
|
"PLV-MediaPlayer" : {
|
||||||
"__plugin_info__" : {
|
"__plugin_info__" : {
|
||||||
"name" : "Polyv播放器插件",
|
"name" : "Polyv播放器插件",
|
||||||
"description" : "该插件封装了保利威底层播放器,是云直播和云点播插件必须的附属插件",
|
"description" : "该插件封装了保利威底层播放器,是云直播和云点播插件必须的附属插件",
|
||||||
"platforms" : "Android,iOS",
|
"platforms" : "Android,iOS",
|
||||||
"url" : "https://ext.dcloud.net.cn/plugin?id=4798",
|
"url" : "https://ext.dcloud.net.cn/plugin?id=4798",
|
||||||
"android_package_name" : "",
|
"android_package_name" : "cn.shangyu.gdxzExpert",
|
||||||
"ios_bundle_id" : "cn.shangyu.gdxzExport",
|
"ios_bundle_id" : "cn.shangyu.gdxzExport",
|
||||||
"isCloud" : true,
|
"isCloud" : true,
|
||||||
"bought" : 1,
|
"bought" : 1,
|
||||||
"pid" : "4798",
|
"pid" : "4798",
|
||||||
"parameters" : {}
|
"parameters" : {}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"PLV-VodUniPlugin" : {
|
||||||
|
"__plugin_info__" : {
|
||||||
|
"name" : "polyv保利威视频云点播插件",
|
||||||
|
"description" : "polyv保利威视频云点播软件组件,支持聊天弹幕、视频加密、多码率、去广告等,还支持视频多维数据统计,适用于教学录播、产品介绍片、视频门户等",
|
||||||
|
"platforms" : "Android,iOS",
|
||||||
|
"url" : "https://ext.dcloud.net.cn/plugin?id=2802",
|
||||||
|
"android_package_name" : "cn.shangyu.gdxzExpert",
|
||||||
|
"ios_bundle_id" : "cn.shangyu.gdxzExport",
|
||||||
|
"isCloud" : true,
|
||||||
|
"bought" : 1,
|
||||||
|
"pid" : "2802",
|
||||||
|
"parameters" : {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -132,5 +211,7 @@
|
|||||||
"vueVersion" : "3",
|
"vueVersion" : "3",
|
||||||
"uniStatistics" : {
|
"uniStatistics" : {
|
||||||
"version" : "2"
|
"version" : "2"
|
||||||
}
|
},
|
||||||
|
"fallbackLocale" : "zh-Hans",
|
||||||
|
"locale" : "zh-Hans"
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -0,0 +1 @@
|
|||||||
|
{"agcgw":{"url":"connect-drcn.dbankcloud.cn","backurl":"connect-drcn.hispace.hicloud.com","websocketurl":"connect-ws-drcn.hispace.dbankcloud.cn","websocketbackurl":"connect-ws-drcn.hispace.dbankcloud.com"},"agcgw_all":{"SG":"connect-dra.dbankcloud.cn","SG_back":"connect-dra.hispace.hicloud.com","CN":"connect-drcn.dbankcloud.cn","CN_back":"connect-drcn.hispace.hicloud.com","RU":"connect-drru.hispace.dbankcloud.ru","RU_back":"connect-drru.hispace.dbankcloud.cn","DE":"connect-dre.dbankcloud.cn","DE_back":"connect-dre.hispace.hicloud.com"},"websocketgw_all":{"SG":"connect-ws-dra.hispace.dbankcloud.cn","SG_back":"connect-ws-dra.hispace.dbankcloud.com","CN":"connect-ws-drcn.hispace.dbankcloud.cn","CN_back":"connect-ws-drcn.hispace.dbankcloud.com","RU":"connect-ws-drru.hispace.dbankcloud.ru","RU_back":"connect-ws-drru.hispace.dbankcloud.cn","DE":"connect-ws-dre.hispace.dbankcloud.cn","DE_back":"connect-ws-dre.hispace.dbankcloud.com"},"client":{"cp_id":"890086000102014306","product_id":"9105163812218585677","client_id":"178572405214545024","client_secret":"B90774CD63B8A6AB5C2C587DC9D7C4C666EF53A19DBA70C4D549C6302ED6CFBE","project_id":"9105163812218585677","app_id":"10526652","api_key":"CV58Raxnpwbfazn6iLPkESUy7KoiUzZ5iTv8lFg/WuexwYZceAK6F9BjRf0HVmT+039dGKt5yecdkRdQ4FCHsmLZ1Zvh","package_name":"cn.shangyu.gdxzExpert"},"oauth_client":{"client_id":"10526652","client_type":1},"app_info":{"app_id":"10526652","package_name":"cn.shangyu.gdxzExpert"},"service":{"analytics":{"collector_url":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn","collector_url_cn":"datacollector-drcn.dt.hicloud.com,datacollector-drcn.dt.dbankcloud.cn","collector_url_de":"datacollector-dre.dt.hicloud.com,datacollector-dre.dt.dbankcloud.cn","collector_url_ru":"datacollector-drru.dt.dbankcloud.ru,datacollector-drru.dt.hicloud.com","collector_url_sg":"datacollector-dra.dt.hicloud.com,datacollector-dra.dt.dbankcloud.cn","resource_id":"p1","channel_id":""},"ml":{"mlservice_url":"ml-api-drcn.ai.dbankcloud.com,ml-api-drcn.ai.dbankcloud.cn"},"cloudstorage":{"storage_url":"https://agc-storage-drcn.platform.dbankcloud.cn","storage_url_ru":"https://agc-storage-drru.cloud.huawei.ru","storage_url_sg":"https://ops-dra.agcstorage.link","storage_url_de":"https://ops-dre.agcstorage.link","storage_url_cn":"https://agc-storage-drcn.platform.dbankcloud.cn","storage_url_ru_back":"https://agc-storage-drru.cloud.huawei.ru","storage_url_sg_back":"https://agc-storage-dra.cloud.huawei.asia","storage_url_de_back":"https://agc-storage-dre.cloud.huawei.eu","storage_url_cn_back":"https://agc-storage-drcn.cloud.huawei.com.cn"},"search":{"url":"https://search-drcn.cloud.huawei.com"},"edukit":{"edu_url":"edukit.cloud.huawei.com.cn","dh_url":"edukit.cloud.huawei.com.cn"}},"region":"CN","configuration_version":"3.0","appInfos":[{"package_name":"cn.shangyu.gdxzExpert","client":{"app_id":"10526652"},"app_info":{"package_name":"cn.shangyu.gdxzExpert","app_id":"10526652"},"oauth_client":{"client_type":1,"client_id":"10526652"}}]}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"developer_id":"109999967097",
|
||||||
|
"app_id":"900782424",
|
||||||
|
"package_name":"cn.shangyu.gdxzExpert",
|
||||||
|
"version":"1.0"
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,101 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>files</key>
|
||||||
|
<dict>
|
||||||
|
<key>Info.plist</key>
|
||||||
|
<data>
|
||||||
|
MxazSmkOgOArGHG40O8L+mZ4ULU=
|
||||||
|
</data>
|
||||||
|
</dict>
|
||||||
|
<key>files2</key>
|
||||||
|
<dict/>
|
||||||
|
<key>rules</key>
|
||||||
|
<dict>
|
||||||
|
<key>^.*</key>
|
||||||
|
<true/>
|
||||||
|
<key>^.*\.lproj/</key>
|
||||||
|
<dict>
|
||||||
|
<key>optional</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1000</real>
|
||||||
|
</dict>
|
||||||
|
<key>^.*\.lproj/locversion.plist$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1100</real>
|
||||||
|
</dict>
|
||||||
|
<key>^Base\.lproj/</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1010</real>
|
||||||
|
</dict>
|
||||||
|
<key>^version.plist$</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>rules2</key>
|
||||||
|
<dict>
|
||||||
|
<key>.*\.dSYM($|/)</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>11</real>
|
||||||
|
</dict>
|
||||||
|
<key>^(.*/)?\.DS_Store$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>2000</real>
|
||||||
|
</dict>
|
||||||
|
<key>^.*</key>
|
||||||
|
<true/>
|
||||||
|
<key>^.*\.lproj/</key>
|
||||||
|
<dict>
|
||||||
|
<key>optional</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1000</real>
|
||||||
|
</dict>
|
||||||
|
<key>^.*\.lproj/locversion.plist$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1100</real>
|
||||||
|
</dict>
|
||||||
|
<key>^Base\.lproj/</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1010</real>
|
||||||
|
</dict>
|
||||||
|
<key>^Info\.plist$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>20</real>
|
||||||
|
</dict>
|
||||||
|
<key>^PkgInfo$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>20</real>
|
||||||
|
</dict>
|
||||||
|
<key>^embedded\.provisionprofile$</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>20</real>
|
||||||
|
</dict>
|
||||||
|
<key>^version\.plist$</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>20</real>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
Binary file not shown.
@@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"name": "NIMUniPlugin",
|
||||||
|
"id": "NIMUniPlugin",
|
||||||
|
"version": "1.1.3",
|
||||||
|
"git": "3ff8678",
|
||||||
|
"buildAt": "7/21/2025, 10:17:00 AM",
|
||||||
|
"description": "uni消息推送插件",
|
||||||
|
"_dp_type": "nativeplugin",
|
||||||
|
"_dp_nativeplugin": {
|
||||||
|
"android": {
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"type": "module",
|
||||||
|
"name": "NIMUniPlugin-PluginModule",
|
||||||
|
"class": "com.netease.nimlib.uniapp.push.PushModule"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hooksClass": "com.netease.nimlib.uniapp.push.PushModule",
|
||||||
|
"integrateType": "aar",
|
||||||
|
"dependencies": [
|
||||||
|
"com.huawei.hms:push:6.9.0.300",
|
||||||
|
"com.meizu.flyme.internet:push-internal:4.2.3",
|
||||||
|
"com.google.android.gms:play-services-base:18.2.0",
|
||||||
|
"com.google.firebase:firebase-messaging:23.1.2",
|
||||||
|
"com.google.firebase:firebase-core:21.1.1",
|
||||||
|
"com.google.code.gson:gson:2.6.2",
|
||||||
|
"commons-codec:commons-codec:1.6",
|
||||||
|
"com.netease.nimlib:basesdk:9.16.1",
|
||||||
|
"com.netease.nimlib:push:9.16.1"
|
||||||
|
],
|
||||||
|
"compileOptions": {
|
||||||
|
"sourceCompatibility": "1.8",
|
||||||
|
"targetCompatibility": "1.8"
|
||||||
|
},
|
||||||
|
"abis": [
|
||||||
|
"armeabi-v7a",
|
||||||
|
"arm64-v8a",
|
||||||
|
"x86"
|
||||||
|
],
|
||||||
|
"minSdkVersion": "21",
|
||||||
|
"useAndroidX": true,
|
||||||
|
"parameters": {
|
||||||
|
"PUSH_VIVO_APPID": {
|
||||||
|
"des": "厂商VIVO-app_id",
|
||||||
|
"key": "com.vivo.push.app_id"
|
||||||
|
},
|
||||||
|
"PUSH_VIVO_APPKEY": {
|
||||||
|
"des": "厂商VIVO-app_key",
|
||||||
|
"key": "com.vivo.push.api_key"
|
||||||
|
},
|
||||||
|
"PUSH_HONOR_APPID": {
|
||||||
|
"des": "厂商HONOR-app_id",
|
||||||
|
"key": "com.hihonor.push.app_id"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ios": {
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"type": "module",
|
||||||
|
"name": "NIMUniPlugin-PluginModule",
|
||||||
|
"class": "NIMPluginModule"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hooksClass": "NIMPluginProxy",
|
||||||
|
"integrateType": "framework",
|
||||||
|
"deploymentTarget": "9.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-5
@@ -8,15 +8,20 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"description": "",
|
"description": "",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@xkit-yx/im-store-v2": "^0.8.3",
|
||||||
|
"@xkit-yx/utils": "^0.7.2",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"@xkit-yx/im-store-v2": "^0.8.3",
|
|
||||||
"@xkit-yx/utils": "^0.7.2",
|
|
||||||
"mobx": "^6.6.1",
|
|
||||||
"nim-web-sdk-ng": "^10.9.30",
|
|
||||||
"dayjs": "^1.11.18",
|
"dayjs": "^1.11.18",
|
||||||
|
"html2canvas": "^1.4.1",
|
||||||
|
"image-tools": "^1.4.0",
|
||||||
"js-base64": "^3.7.8",
|
"js-base64": "^3.7.8",
|
||||||
"js-md5": "^0.8.3",
|
"js-md5": "^0.8.3",
|
||||||
|
"mobx": "^6.6.1",
|
||||||
|
"nim-web-sdk-ng": "^10.9.50",
|
||||||
"pinyin": "^4.0.0",
|
"pinyin": "^4.0.0",
|
||||||
"uview-plus": "^3.4.73"
|
"uni-packing-wgt": "^1.2.3",
|
||||||
|
"uniapp-video-player": "^1.3.0",
|
||||||
|
"uview-plus": "^3.4.73",
|
||||||
|
"vconsole": "^3.15.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1695
-1171
File diff suppressed because it is too large
Load Diff
+197
@@ -0,0 +1,197 @@
|
|||||||
|
<template>
|
||||||
|
<view class="ad-container" v-if="adData.path">
|
||||||
|
<!-- 广告图片 -->
|
||||||
|
<image
|
||||||
|
class="ad-image"
|
||||||
|
:src="adData.path"
|
||||||
|
mode="aspectFill"
|
||||||
|
@click="handleAdClick"
|
||||||
|
></image>
|
||||||
|
|
||||||
|
<!-- 右上角倒计时跳过按钮 -->
|
||||||
|
<view class="skip-button" @click="skipAd">
|
||||||
|
<text class="skip-text">跳过 {{countdown}}s</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部点击跳转按钮 -->
|
||||||
|
<view class="bottom-button" v-if="adData.url" @click="handleAdClick">
|
||||||
|
<text class="button-text">点击查看详情</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 加载状态 -->
|
||||||
|
<view class="loading-container" v-else>
|
||||||
|
<text class="loading-text">加载中...</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted, nextTick, computed, onUnmounted } from 'vue';
|
||||||
|
import { onShow, onLoad, onPageScroll } from "@dcloudio/uni-app";
|
||||||
|
import my_api from '@/api/my_api.js'
|
||||||
|
import docUrl from "@/utils/docUrl.js";
|
||||||
|
const app = getApp()
|
||||||
|
// 广告数据
|
||||||
|
const adData = ref({
|
||||||
|
path: '',
|
||||||
|
url: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 倒计时
|
||||||
|
const countdown = ref(5);
|
||||||
|
let timer = null;
|
||||||
|
|
||||||
|
// 页面加载
|
||||||
|
onLoad(() => {
|
||||||
|
console.log('开屏广告页面加载');
|
||||||
|
getStartpage();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取开屏广告数据
|
||||||
|
const getStartpage = () => {
|
||||||
|
my_api.startpage().then(res => {
|
||||||
|
console.log('开屏广告数据:', res);
|
||||||
|
if (res && res.data) {
|
||||||
|
adData.value = {
|
||||||
|
path: docUrl + res.data.path || '',
|
||||||
|
url: res.data.url || ''
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果有广告图片,开始倒计时
|
||||||
|
if (res.data.path) {
|
||||||
|
|
||||||
|
startCountdown();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// 没有广告,直接跳转到首页
|
||||||
|
navigateToHome();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 接口返回异常,直接跳转到首页
|
||||||
|
navigateToHome();
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('获取开屏广告失败:', err);
|
||||||
|
// 接口调用失败,直接跳转到首页
|
||||||
|
navigateToHome();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始倒计时
|
||||||
|
const startCountdown = () => {
|
||||||
|
timer = setInterval(() => {
|
||||||
|
countdown.value--;
|
||||||
|
if (countdown.value <= 0) {
|
||||||
|
clearInterval(timer);
|
||||||
|
if(app.globalData.plAd){
|
||||||
|
navigateToHome();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳过广告
|
||||||
|
const skipAd = () => {
|
||||||
|
clearInterval(timer);
|
||||||
|
navigateToHome();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击广告
|
||||||
|
const handleAdClick = () => {
|
||||||
|
if (adData.value.url) {
|
||||||
|
// 有跳转链接,跳转到指定页面
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages/webview/webview?url=' + adData.value.url
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 没有跳转链接,直接跳转到首页
|
||||||
|
navigateToHome();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转到首页
|
||||||
|
const navigateToHome = () => {
|
||||||
|
uni.redirectTo({
|
||||||
|
url: '/pages/index/index'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页面卸载时清理定时器
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (timer) {
|
||||||
|
clearInterval(timer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.ad-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #000;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ad-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.skip-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 60rpx;
|
||||||
|
right: 30rpx;
|
||||||
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
|
border-radius: 40rpx;
|
||||||
|
padding: 16rpx 24rpx;
|
||||||
|
z-index: 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-text {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-button {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 100rpx;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
border-radius: 50rpx;
|
||||||
|
padding: 24rpx 60rpx;
|
||||||
|
box-shadow: 0 8rpx 32rpx rgba(102, 126, 234, 0.3);
|
||||||
|
z-index: 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-text {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-text {
|
||||||
|
color: #666;
|
||||||
|
font-size: 32rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<uni-nav-bar title="继续教育" fixed color="#8B2316" height="140rpx" :border="false" backgroundColor="#eeeeee"></uni-nav-bar>
|
<navBar :title="'继续教育'"></navBar>
|
||||||
<view class="page">
|
<view class="page">
|
||||||
<!-- 课程列表 -->
|
<!-- 课程列表 -->
|
||||||
<view class="course-list">
|
<view class="course-list">
|
||||||
@@ -103,21 +103,22 @@
|
|||||||
import xueyuanImg from "@/static/ganbingxueyuan.png"
|
import xueyuanImg from "@/static/ganbingxueyuan.png"
|
||||||
import newerImg from "@/static/xinshoujiaocheng.png"
|
import newerImg from "@/static/xinshoujiaocheng.png"
|
||||||
import navTo from '@/utils/navTo.js';
|
import navTo from '@/utils/navTo.js';
|
||||||
|
import navBar from "@/components/navBar/navBar.vue"
|
||||||
// 方法
|
// 方法
|
||||||
// 方法
|
// 方法
|
||||||
const goToCourse = (courseType) => {
|
const goToCourse = (courseType) => {
|
||||||
console.log('进入课程:', courseType);
|
|
||||||
|
|
||||||
// 根据课程类型进行不同的处理
|
// 根据课程类型进行不同的处理
|
||||||
switch(courseType) {
|
switch(courseType) {
|
||||||
case 'course':
|
case 'course':
|
||||||
navTo({
|
uni.sendNativeEvent('goCourse',{
|
||||||
url: '/pages_course/course/course'
|
msg: 'course'
|
||||||
})
|
})
|
||||||
break;
|
break;
|
||||||
case 'video':
|
case 'video':
|
||||||
navTo({
|
navTo({
|
||||||
url: '/pages_app/video/video'
|
url: '/pages_app/video/video?from=education'
|
||||||
})
|
})
|
||||||
break;
|
break;
|
||||||
case 'ppt':
|
case 'ppt':
|
||||||
@@ -166,9 +167,8 @@ $padding-small: 10px;
|
|||||||
|
|
||||||
.page {
|
.page {
|
||||||
background-color: $gray-bg;
|
background-color: $gray-bg;
|
||||||
min-height: calc(100vh - 140rpx);
|
min-height: calc(100vh - var(--status-bar-height) - 44px);
|
||||||
|
margin-top:calc(var(--status-bar-height) + 44px);
|
||||||
padding-bottom: 120rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 课程列表
|
// 课程列表
|
||||||
|
|||||||
+1029
-548
File diff suppressed because it is too large
Load Diff
+1468
-1130
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,52 @@
|
|||||||
|
<template>
|
||||||
|
<navBar :showLeft="false" :title="'加载中...'"></navBar>
|
||||||
|
<view class="loading-page"></view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { onMounted,ref} from 'vue';
|
||||||
|
import { onLoad,onUnload,onHide,onShow } from '@dcloudio/uni-app';
|
||||||
|
import navBar from '@/components/navBar/navBar.vue';
|
||||||
|
const timer=ref(null);
|
||||||
|
const count=ref(0);
|
||||||
|
const countDown=()=>{
|
||||||
|
if(timer.value){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
timer.value=setInterval(()=>{
|
||||||
|
count.value++;
|
||||||
|
if(count.value>=8){
|
||||||
|
clearInterval(timer.value);
|
||||||
|
plus.runtime.quit();
|
||||||
|
}
|
||||||
|
},1000);
|
||||||
|
}
|
||||||
|
onShow(() => {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '加载中...',
|
||||||
|
mask: true
|
||||||
|
});
|
||||||
|
countDown()
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnload(() => {
|
||||||
|
uni.hideLoading();
|
||||||
|
if(timer.value){
|
||||||
|
clearInterval(timer.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onHide(() => {
|
||||||
|
uni.hideLoading();
|
||||||
|
if(timer.value){
|
||||||
|
clearInterval(timer.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.loading-page{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<uni-nav-bar title="肝胆会议" fixed color="#8B2316" height="140rpx" :border="false" backgroundColor="#eeeeee"></uni-nav-bar>
|
<navBar :title="'肝胆会议'"></navBar>
|
||||||
<view class="page">
|
<view class="page">
|
||||||
<!-- 筛选标签栏 -->
|
<!-- 筛选标签栏 -->
|
||||||
<view class="filter-bar">
|
<view class="filter-bar">
|
||||||
@@ -146,6 +146,7 @@
|
|||||||
import timeImg from "@/static/play_long.png"
|
import timeImg from "@/static/play_long.png"
|
||||||
import api from '@/api/api';
|
import api from '@/api/api';
|
||||||
import docUrl from '@/utils/docUrl';
|
import docUrl from '@/utils/docUrl';
|
||||||
|
import navBar from "@/components/navBar/navBar.vue"
|
||||||
// 弹窗状态
|
// 弹窗状态
|
||||||
const isTimePopupShow = ref(false);
|
const isTimePopupShow = ref(false);
|
||||||
const isLocationPopupShow = ref(false);
|
const isLocationPopupShow = ref(false);
|
||||||
|
|||||||
+426
-31
@@ -1,20 +1,23 @@
|
|||||||
<template>
|
<template>
|
||||||
<uni-nav-bar title="我的" fixed color="#8B2316" height="140rpx" :border="false"
|
<navBar :title="'我的'" :showLeft="false"></navBar>
|
||||||
backgroundColor="#eeeeee"></uni-nav-bar>
|
|
||||||
<view class="page">
|
<view class="page">
|
||||||
|
|
||||||
|
|
||||||
<!-- 用户信息卡片 -->
|
<!-- 用户信息卡片 -->
|
||||||
<view class="user-card"
|
<view class="user-card"
|
||||||
:style="{'background-image': `url(${myInfoBackGround || '/static/big_background_my.png'})`, 'background-size':'cover','background-repeat':'no-repeat'}">
|
:style="{'background-image': `url(${myInfoBackGround || '/static/big_background_my.png'})`, 'background-size':'cover','background-repeat':'no-repeat'}">
|
||||||
<view class="user-info" @click="goToPage('myInfo')">
|
<view class="user-info">
|
||||||
<image class="avatar" :src="avatar" mode="aspectFill"></image>
|
<image class="avatar" :src="avatar" mode="aspectFill" @click="goToPage('myInfo')"></image>
|
||||||
<view class="user-info-content">
|
<view class="user-info-content">
|
||||||
<text class="username">{{username}}</text>
|
<text class="username">{{username}}</text>
|
||||||
<scroll-view class="honor_box" scroll-x="true" show-scrollbar="false">
|
<scroll-view class="honor_box" scroll-x="true" show-scrollbar="false">
|
||||||
<view class="honor_wrap">
|
<view class="honor_wrap">
|
||||||
<view class="honor_item" v-for="item in honor_list" :key="item.id">
|
<view class="honor_item" v-if="ranking > 0">
|
||||||
<image class="honor_image" src="/static/wdsc.png" mode="aspectFill"></image>
|
<image class="honor_image" :src="suifangImg" mode="aspectFill"></image>
|
||||||
|
<text class="honor_text">随访达人|排名{{ranking}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="honor_item" v-for="item in honor_list" :key="item.id" @click="getHonorDetail(item.id)">
|
||||||
|
<image class="honor_image" :src="rongyu" mode="aspectFill"></image>
|
||||||
<text class="honor_text">{{ item.nick_name }}</text>
|
<text class="honor_text">{{ item.nick_name }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -101,9 +104,9 @@
|
|||||||
<!-- 账户明细 -->
|
<!-- 账户明细 -->
|
||||||
<view class="section">
|
<view class="section">
|
||||||
<view class="section-title">账户明细</view>
|
<view class="section-title">账户明细</view>
|
||||||
<up-scroll-list indicatorActiveColor="#8B2316" indicatorWidth="40rpx" indicatorBarWidth="20rpx"
|
<up-scroll-list :indicator="isAccount" indicatorActiveColor="#8B2316" indicatorWidth="40rpx" indicatorBarWidth="20rpx"
|
||||||
class="account-grid">
|
class="account-grid">
|
||||||
<view class="account-item" @click="goToPage('myAccount')">
|
<view class="account-item" @click="goToPage('myAccount')" v-if="isAccount">
|
||||||
<up-image :src="wdzzImg" width="48rpx" height="48rpx"></up-image>
|
<up-image :src="wdzzImg" width="48rpx" height="48rpx"></up-image>
|
||||||
<text>我的账户</text>
|
<text>我的账户</text>
|
||||||
</view>
|
</view>
|
||||||
@@ -115,11 +118,11 @@
|
|||||||
<up-image :src="wdflImg" width="48rpx" height="48rpx"></up-image>
|
<up-image :src="wdflImg" width="48rpx" height="48rpx"></up-image>
|
||||||
<text>我的福利</text>
|
<text>我的福利</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="account-item" @click="goToPage('myFlower')">
|
<view class="account-item" @click="goToPage('myFlower')" v-if="isAccount">
|
||||||
<up-image :src="wdxhImg" width="48rpx" height="48rpx"></up-image>
|
<up-image :src="wdxhImg" width="48rpx" height="48rpx"></up-image>
|
||||||
<text>我的鲜花</text>
|
<text>我的鲜花</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="account-item" @click="goToPage('pptDetail')">
|
<view class="account-item" @click="goToPage('pptDetail')" v-if="isAccount">
|
||||||
<up-image :src="kjmxImg" width="48rpx" height="48rpx"></up-image>
|
<up-image :src="kjmxImg" width="48rpx" height="48rpx"></up-image>
|
||||||
<text>课件明细</text>
|
<text>课件明细</text>
|
||||||
</view>
|
</view>
|
||||||
@@ -144,13 +147,13 @@
|
|||||||
<up-image :src="ghsjhImg" width="48rpx" height="48rpx"></up-image>
|
<up-image :src="ghsjhImg" width="48rpx" height="48rpx"></up-image>
|
||||||
<text>更换手机号</text>
|
<text>更换手机号</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="operation-item" @click="goToPage('notifications')">
|
<view class="operation-item" @click="switchPushPermissions">
|
||||||
<up-image :src="tzykImg" width="48rpx" height="48rpx"></up-image>
|
<up-image :src="tzykImg" width="48rpx" height="48rpx"></up-image>
|
||||||
<text>通知已开</text>
|
<text>通知已{{notice_on?'开':'关'}}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="operation-item" @click="showVersion">
|
<view class="operation-item" @click="showVersion">
|
||||||
<up-image :src="versionImg" width="48rpx" height="48rpx"></up-image>
|
<up-image :src="hasNewVersion?versionImgOn:versionImg" width="48rpx" height="48rpx"></up-image>
|
||||||
<text>V{{version}}</text>
|
<text>{{hasNewVersion?'有新版本':'V'+version}}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -175,7 +178,7 @@
|
|||||||
|
|
||||||
<!-- 常用银行卡 -->
|
<!-- 常用银行卡 -->
|
||||||
<view class="sectioncell bank-section">
|
<view class="sectioncell bank-section">
|
||||||
<view class="bank-item" @click="goToPage('bankCard')">
|
<view class="bank-item" @click="goToPage('bankCard')" v-if="isAccount">
|
||||||
<view class="bank-icon">
|
<view class="bank-icon">
|
||||||
<up-image :src="cyyhk" width="48rpx" height="48rpx"></up-image>
|
<up-image :src="cyyhk" width="48rpx" height="48rpx"></up-image>
|
||||||
</view>
|
</view>
|
||||||
@@ -194,10 +197,12 @@
|
|||||||
<view class="settings-icon">
|
<view class="settings-icon">
|
||||||
<up-image :src="settingImg" width="48rpx" height="48rpx"></up-image>
|
<up-image :src="settingImg" width="48rpx" height="48rpx"></up-image>
|
||||||
</view>
|
</view>
|
||||||
<view class="settings-content">
|
<view class="settings-content flex-row" >
|
||||||
<text class="settings-title">设置与帮助</text>
|
<text class="settings-title">设置与帮助</text>
|
||||||
|
<text v-if="hasNewVersion && isIos" class="new-version">有新版本</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="settings-arrow">
|
<view class="settings-arrow">
|
||||||
|
|
||||||
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -215,16 +220,68 @@
|
|||||||
<!-- 底部导航栏 -->
|
<!-- 底部导航栏 -->
|
||||||
<CustomTabbar></CustomTabbar>
|
<CustomTabbar></CustomTabbar>
|
||||||
</view>
|
</view>
|
||||||
|
<unidialog :visible="hasSign" content="今日已签到,每天只能签到一次。<br>请明日继续哦~" @close="hasSign=false" :showCancel="true" cancelText="关闭"></unidialog>
|
||||||
|
<up-overlay :show="showSign" >
|
||||||
|
<view class="signwrap">
|
||||||
|
<view class="signbox">
|
||||||
|
<view class="close" @click="showSign=false"></view>
|
||||||
|
<view class="signbg">
|
||||||
|
<up-image :src="signImg" width="604rpx" height="964rpx" ></up-image>
|
||||||
|
</view>
|
||||||
|
<view class="signcontent">
|
||||||
|
<view class="day">今天是我们相识的第{{signInfo.gdxzday}}天</view>
|
||||||
|
<view class="signtotal">本周共签到{{signInfo.totalDay}}次</view>
|
||||||
|
<view class="signcontinue">已经连续签到{{signInfo.continuous_day}}天</view>
|
||||||
|
<view class="tip">连续签到获取更多积分</view>
|
||||||
|
<view class="news" @click.stop="goNews">
|
||||||
|
{{signInfo.news.summary}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</up-overlay>
|
||||||
|
<up-overlay :show="showHonor" >
|
||||||
|
<view class="honorwrap">
|
||||||
|
<view class="honorbox">
|
||||||
|
<image :src="docUrl+honnor_detail.img" class="honor_image"></image>
|
||||||
|
<uni-icons type="close" class="close_honor" size="24" color="#fff" @click="showHonor=false"></uni-icons>
|
||||||
|
<view class="content">
|
||||||
|
<view class="content_title">
|
||||||
|
{{honnor_detail.title}}
|
||||||
|
</view>
|
||||||
|
<view class="row">
|
||||||
|
<view class="row_item" v-for="item in honnor_detail.honorlist" :key="item.id">
|
||||||
|
{{ item.nick_name }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="content_content">
|
||||||
|
{{honnor_detail.note}}
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</up-overlay>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import unidialog from '@/components/dialog/dialog.vue'
|
||||||
|
import signImg from "@/static/sign_in_bng_big.png"
|
||||||
import CustomTabbar from '@/components/tabBar/tabBar.vue';
|
import CustomTabbar from '@/components/tabBar/tabBar.vue';
|
||||||
|
import navBar from "@/components/navBar/navBar.vue"
|
||||||
import {
|
import {
|
||||||
ref
|
ref,reactive
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
import {
|
import {
|
||||||
onShow
|
onShow
|
||||||
} from "@dcloudio/uni-app";
|
} from "@dcloudio/uni-app";
|
||||||
|
const showHonor=ref(false);
|
||||||
|
import docUrl from "@/utils/docUrl.js"
|
||||||
|
import honnorExpert from "@/static/zixunexpert.png"
|
||||||
|
import honnorYingxiong from "@/static/yingxiongbanglog.png"
|
||||||
|
import rongyu from "@/static/yxb.png"
|
||||||
import version from '@/utils/version.js'
|
import version from '@/utils/version.js'
|
||||||
import hzshImg from "@/static/hzsh.png"
|
import hzshImg from "@/static/hzsh.png"
|
||||||
import hzfzImg from "@/static/hzfz.png"
|
import hzfzImg from "@/static/hzfz.png"
|
||||||
@@ -246,8 +303,9 @@
|
|||||||
import ghsjhImg from "@/static/ghsjh.png"
|
import ghsjhImg from "@/static/ghsjh.png"
|
||||||
import tzykImg from "@/static/xxtx.png"
|
import tzykImg from "@/static/xxtx.png"
|
||||||
import versionImg from "@/static/fxxbb.png"
|
import versionImg from "@/static/fxxbb.png"
|
||||||
|
import versionImgOn from "@/static/fxbb.png"
|
||||||
|
import jifenImg from "@/static/point_buy.png"
|
||||||
|
import suifangImg from "@/static/suifang.png"
|
||||||
import fulicard from "@/static/fulicard.png"
|
import fulicard from "@/static/fulicard.png"
|
||||||
import fpgl from "@/static/fpgl.png"
|
import fpgl from "@/static/fpgl.png"
|
||||||
import cyyhk from "@/static/cyhhk.png"
|
import cyyhk from "@/static/cyhhk.png"
|
||||||
@@ -256,9 +314,16 @@
|
|||||||
import my_api from '@/api/my_api.js'
|
import my_api from '@/api/my_api.js'
|
||||||
import navTo from "@/utils/navTo"
|
import navTo from "@/utils/navTo"
|
||||||
import linkUrl from "@/utils/docUrl"
|
import linkUrl from "@/utils/docUrl"
|
||||||
|
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const isLargeFont = ref(false);
|
const isLargeFont = ref(false);
|
||||||
|
const hasSign = ref(false)
|
||||||
|
const showSign = ref(false)
|
||||||
|
const signInfo=reactive({
|
||||||
|
news:{
|
||||||
|
summary:''
|
||||||
|
}
|
||||||
|
})
|
||||||
// 新增:我的信息数据
|
// 新增:我的信息数据
|
||||||
const avatar = ref('')
|
const avatar = ref('')
|
||||||
const username = ref('')
|
const username = ref('')
|
||||||
@@ -269,6 +334,43 @@
|
|||||||
const totalPoints = ref(0)
|
const totalPoints = ref(0)
|
||||||
const sign_in = ref(0)
|
const sign_in = ref(0)
|
||||||
const honor_list = ref([])
|
const honor_list = ref([])
|
||||||
|
const ranking = ref(0)
|
||||||
|
|
||||||
|
const notice_on = ref(false)
|
||||||
|
const hasNewVersion = ref(false)
|
||||||
|
const checkVersion=()=>{
|
||||||
|
api.checkVersion().then(res=>{
|
||||||
|
if(res.code==80002){
|
||||||
|
hasNewVersion.value=true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const isAccount = ref(false);
|
||||||
|
const getIsAccount=()=>{
|
||||||
|
api.getIsAccount().then(res=>{
|
||||||
|
if(res.code==1){
|
||||||
|
isAccount.value=res.is_account==0?false:true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const goNews=()=>{
|
||||||
|
let url=docUrl+signInfo.news.path;
|
||||||
|
// #ifdef H5
|
||||||
|
window.open(url, '_blank');
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
plus.runtime.openURL(url);
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef MP
|
||||||
|
const encoded = encodeURIComponent(url);
|
||||||
|
navTo({
|
||||||
|
url: `/pages_app/webview/webview?url=${encoded}`
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
// 从storage获取用户信息
|
// 从storage获取用户信息
|
||||||
const getUserInfoFromStorage = () => {
|
const getUserInfoFromStorage = () => {
|
||||||
try {
|
try {
|
||||||
@@ -299,6 +401,7 @@
|
|||||||
title: '签到成功,获得'+res.bonuspoints+'积分',
|
title: '签到成功,获得'+res.bonuspoints+'积分',
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
});
|
});
|
||||||
|
Object.assign(signInfo,res);
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: res?.msg || '签到失败',
|
title: res?.msg || '签到失败',
|
||||||
@@ -326,6 +429,7 @@
|
|||||||
totalPoints.value = data.total_points || 0
|
totalPoints.value = data.total_points || 0
|
||||||
sign_in.value = data.sign_in || 0
|
sign_in.value = data.sign_in || 0
|
||||||
honor_list.value = data.honor_list || []
|
honor_list.value = data.honor_list || []
|
||||||
|
ranking.value = data.ranking || 0
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('获取我的信息失败', e)
|
console.error('获取我的信息失败', e)
|
||||||
@@ -419,7 +523,7 @@
|
|||||||
url="/pages_app/changeMobile/changeMobile"
|
url="/pages_app/changeMobile/changeMobile"
|
||||||
break;
|
break;
|
||||||
case 'benefitExchange':
|
case 'benefitExchange':
|
||||||
url="/pages_app/myWelfareCard/myWelfareCard"
|
url="/pages_app/myWelfareCard/myWelfareCard?from=my"
|
||||||
break;
|
break;
|
||||||
case 'bankCard':
|
case 'bankCard':
|
||||||
url="/pages_app/idcardAuth/bankCardList"
|
url="/pages_app/idcardAuth/bankCardList"
|
||||||
@@ -428,8 +532,9 @@
|
|||||||
url="/pages_app/setting/setting"
|
url="/pages_app/setting/setting"
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
const push_clientid = uni.getStorageSync("push_clientid")
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '功能开发中',
|
title: 'push_clientid: '+push_clientid,
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -438,6 +543,131 @@
|
|||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 判断通知权限是否开启
|
||||||
|
const isNoticeOn = () => {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
if (plus.os.name == "Android") {
|
||||||
|
var main = plus.android.runtimeMainActivity();
|
||||||
|
var NotificationManagerCompat = plus.android.importClass("android.support.v4.app.NotificationManagerCompat");
|
||||||
|
if (NotificationManagerCompat == null) {
|
||||||
|
NotificationManagerCompat = plus.android.importClass("androidx.core.app.NotificationManagerCompat");
|
||||||
|
}
|
||||||
|
var areNotificationsEnabled = NotificationManagerCompat.from(main).areNotificationsEnabled();
|
||||||
|
notice_on.value = areNotificationsEnabled
|
||||||
|
return areNotificationsEnabled;
|
||||||
|
} else if (plus.os.name == "iOS") {
|
||||||
|
var isIosOn = undefined;
|
||||||
|
var types = 0;
|
||||||
|
var app = plus.ios.invoke("UIApplication", "sharedApplication");
|
||||||
|
var settings = plus.ios.invoke(app, "currentUserNotificationSettings");
|
||||||
|
if (settings) {
|
||||||
|
types = settings.plusGetAttribute("types");
|
||||||
|
plus.ios.deleteObject(settings);
|
||||||
|
} else {
|
||||||
|
types = plus.ios.invoke(app, "enabledRemoteNotificationTypes");
|
||||||
|
}
|
||||||
|
plus.ios.deleteObject(app);
|
||||||
|
isIosOn = 0 != types;
|
||||||
|
notice_on.value = isIosOn
|
||||||
|
return isIosOn;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// 前往系统设置页面开启或关闭通知权限
|
||||||
|
const switchPushPermissions = () => {
|
||||||
|
const push_clientid = uni.getStorageSync("push_clientid")
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
let title = isNoticeOn() ? "通知权限关闭提醒" : "通知权限开启提醒";
|
||||||
|
let content = isNoticeOn()
|
||||||
|
? "通知权限已开启,是否前往设置关闭?"+push_clientid
|
||||||
|
: "您还没有开启通知权限,无法接受到消息通知,是否前往设置?"+push_clientid;
|
||||||
|
// 打开安卓系统设置页面
|
||||||
|
let openAndroidSetting = () => {
|
||||||
|
var main = plus.android.runtimeMainActivity();
|
||||||
|
var pkName = main.getPackageName();
|
||||||
|
var uid = main.getApplicationInfo().plusGetAttribute("uid");
|
||||||
|
var Intent = plus.android.importClass("android.content.Intent");
|
||||||
|
var Build = plus.android.importClass("android.os.Build");
|
||||||
|
//android 8.0引导
|
||||||
|
if (Build.VERSION.SDK_INT >= 26) {
|
||||||
|
var intent = new Intent("android.settings.APP_NOTIFICATION_SETTINGS");
|
||||||
|
intent.putExtra("android.provider.extra.APP_PACKAGE", pkName);
|
||||||
|
} else if (Build.VERSION.SDK_INT >= 21) {
|
||||||
|
//android 5.0-7.0
|
||||||
|
var intent = new Intent("android.settings.APP_NOTIFICATION_SETTINGS");
|
||||||
|
intent.putExtra("app_package", pkName);
|
||||||
|
intent.putExtra("app_uid", uid);
|
||||||
|
} else {
|
||||||
|
//(<21)其他--跳转到该应用管理的详情页
|
||||||
|
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||||
|
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
|
||||||
|
intent.setData(uri);
|
||||||
|
}
|
||||||
|
// 跳转到该应用的系统通知设置页
|
||||||
|
main.startActivity(intent);
|
||||||
|
};
|
||||||
|
// 打开苹果系统设置页面
|
||||||
|
let openIOSSetting = () => {
|
||||||
|
var app = plus.ios.invoke("UIApplication", "sharedApplication");
|
||||||
|
var setting = plus.ios.invoke("NSURL", "URLWithString:", "app-settings:");
|
||||||
|
plus.ios.invoke(app, "openURL:", setting);
|
||||||
|
plus.ios.deleteObject(setting);
|
||||||
|
plus.ios.deleteObject(app);
|
||||||
|
// ios18跳转不过去的解决方案
|
||||||
|
// 方案一:使用uni.openAppAuthorizeSetting(),文档地址:https://uniapp.dcloud.net.cn/api/system/openappauthorizesetting.html
|
||||||
|
// 方案二:待验证,AI生成;来源评论区:iOS 18以后,openURL:完全被弃用,需要用openURL:options:completionHandler:替代。
|
||||||
|
// var app = plus.ios.invoke("UIApplication", "sharedApplication");
|
||||||
|
// var url;
|
||||||
|
// // 获取安全 URL(iOS 8+)
|
||||||
|
// if (plus.ios.invoke("UIApplication", "respondsToSelector:", "openSettingsURLString")) {
|
||||||
|
// var urlString = plus.ios.invoke("UIApplication", "openSettingsURLString");
|
||||||
|
// url = plus.ios.invoke("NSURL", "URLWithString:", urlString);
|
||||||
|
// } else {
|
||||||
|
// url = plus.ios.invoke("NSURL", "URLWithString:", "app-settings:");
|
||||||
|
// }
|
||||||
|
// // 判断新 API 可用性(iOS 10+)
|
||||||
|
// var supportsNewAPI = plus.ios.invoke(app, "respondsToSelector:", "openURL:options:completionHandler:");
|
||||||
|
// if (supportsNewAPI) {
|
||||||
|
// var options = plus.ios.newObject("NSDictionary");
|
||||||
|
// var completion = plus.ios.newBlock(function(success) {
|
||||||
|
// console.log("跳转结果:" + success);
|
||||||
|
// if (!success) {
|
||||||
|
// plus.nativeUI.toast("无法打开设置,请手动前往");
|
||||||
|
// }
|
||||||
|
// }, "v@:B");
|
||||||
|
// plus.ios.invoke(app, "openURL:options:completionHandler:", url, options, completion);
|
||||||
|
// plus.ios.deleteObject(completion);
|
||||||
|
// } else {
|
||||||
|
// if (plus.ios.invoke(app, "canOpenURL:", url)) {
|
||||||
|
// plus.ios.invoke(app, "openURL:", url);
|
||||||
|
// } else {
|
||||||
|
// throw new Error("当前系统不支持跳转设置");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// plus.ios.deleteObject(url);
|
||||||
|
// plus.ios.deleteObject(app);
|
||||||
|
};
|
||||||
|
// 弹窗提醒开通或关闭权限,点击确认后,跳转到系统设置页面进行设置
|
||||||
|
uni.showModal({
|
||||||
|
title: title,
|
||||||
|
content: content,
|
||||||
|
showCancel: true,
|
||||||
|
confirmColor: "#ff903f",
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
if (plus.os.name == "Android") {
|
||||||
|
openAndroidSetting();
|
||||||
|
} else if (plus.os.name == "iOS") {
|
||||||
|
openIOSSetting();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const showYearSummary = () => {
|
const showYearSummary = () => {
|
||||||
console.log('显示年度总结');
|
console.log('显示年度总结');
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
@@ -453,7 +683,16 @@
|
|||||||
showCancel: false
|
showCancel: false
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const honnor_detail=ref({});
|
||||||
|
const getHonorDetail=async(id)=>{
|
||||||
|
const res = await api.gethonorDetail({
|
||||||
|
id:id
|
||||||
|
})
|
||||||
|
if (res.code == 1 ) {
|
||||||
|
honnor_detail.value = res.data;
|
||||||
|
showHonor.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
const onStatsClick = (key) => {
|
const onStatsClick = (key) => {
|
||||||
let url = '';
|
let url = '';
|
||||||
switch (key) {
|
switch (key) {
|
||||||
@@ -485,12 +724,23 @@
|
|||||||
isBoundWechat.value = res.data
|
isBoundWechat.value = res.data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const isBoundWechat = ref(false)
|
const isBoundWechat = ref(false);
|
||||||
|
const isIos = ref(false);
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
console.log('我的页面显示');
|
console.log('我的页面显示');
|
||||||
getUserInfoFromStorage() // 先从storage获取用户信息
|
getUserInfoFromStorage() // 先从storage获取用户信息
|
||||||
fetchMyInfo() // 然后从API获取最新数据
|
fetchMyInfo() // 然后从API获取最新数据
|
||||||
getIsBoundWechat()
|
getIsBoundWechat()
|
||||||
|
isNoticeOn();
|
||||||
|
checkVersion();
|
||||||
|
getIsAccount();
|
||||||
|
let systemInfo = uni.getSystemInfoSync();
|
||||||
|
console.log(systemInfo)
|
||||||
|
if(systemInfo.osName == 'ios'){
|
||||||
|
isIos.value = true;
|
||||||
|
}else{
|
||||||
|
isIos.value = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -514,12 +764,151 @@
|
|||||||
|
|
||||||
.page {
|
.page {
|
||||||
background-color: $gray-bg;
|
background-color: $gray-bg;
|
||||||
height: calc(100vh - 140rpx);
|
margin-top:calc(var(--status-bar-height) + 44px);
|
||||||
|
height: calc(100vh - var(--status-bar-height) - 44px);
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
padding-bottom: 100rpx;
|
|
||||||
}
|
}
|
||||||
|
.flex-row{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.new-version{
|
||||||
|
background:#8B2316;
|
||||||
|
color:#fff;
|
||||||
|
font-size: 24rpx;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
padding: 8rpx 20rpx;
|
||||||
|
border-radius: 30rpx;
|
||||||
|
}
|
||||||
|
.honorwrap{
|
||||||
|
width:100%;
|
||||||
|
height:100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
.honorbox{
|
||||||
|
|
||||||
|
width:80%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
min-height:200rpx;
|
||||||
|
background:linear-gradient(to bottom, #54049b, #da4ee2);
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
.row{
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr); /* 创建两列,每列等宽 */
|
||||||
|
gap: 20px;
|
||||||
|
.row_item{
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #da4ee2;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
text-align: center;
|
||||||
|
padding: 10rpx 20rpx;
|
||||||
|
background:#fff;
|
||||||
|
white-space: nowrap;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
border:1rpx solid #da4ee2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.close_honor{
|
||||||
|
position: absolute;
|
||||||
|
top:20rpx;
|
||||||
|
right:20rpx;
|
||||||
|
}
|
||||||
|
.honor_image{
|
||||||
|
width:269rpx;
|
||||||
|
height:213rpx;
|
||||||
|
position: absolute;
|
||||||
|
top:-76rpx;
|
||||||
|
left:50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
.content{
|
||||||
|
margin-top:73rpx;
|
||||||
|
background:#fff;
|
||||||
|
border-radius: 5rpx;
|
||||||
|
padding: 20rpx;
|
||||||
|
.content_title{
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 35rpx 0 20rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #da4ee2;
|
||||||
|
}
|
||||||
|
.content_content{
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.signwrap{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height:100%;
|
||||||
|
.signbox{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
z-index:0;
|
||||||
|
.close{
|
||||||
|
position:absolute;
|
||||||
|
right:0;
|
||||||
|
height:60rpx;
|
||||||
|
width:60rpx;
|
||||||
|
opacity: 0;
|
||||||
|
background:#fff;
|
||||||
|
z-index:2;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.signwrap .signcontent{
|
||||||
|
width:100%;
|
||||||
|
top:0;
|
||||||
|
position: absolute;
|
||||||
|
z-index:1;
|
||||||
|
}
|
||||||
|
.signwrap .signcontent .day{
|
||||||
|
margin-top: 384rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.signwrap .signtotal{
|
||||||
|
margin-top: 30rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
.signwrap .signcontinue{
|
||||||
|
font-size: 30rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signwrap .signcontent .tip{
|
||||||
|
margin-top: 40rpx;
|
||||||
|
color:red;
|
||||||
|
font-size: 28rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.signwrap .signcontent .news{
|
||||||
|
margin: 196rpx 60rpx 0;
|
||||||
|
height: 116rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
.signwrap .signbg{
|
||||||
|
width:604rpx;
|
||||||
|
height:964rpx;
|
||||||
|
}
|
||||||
// 用户信息卡片
|
// 用户信息卡片
|
||||||
.user-card {
|
.user-card {
|
||||||
|
|
||||||
@@ -541,7 +930,6 @@
|
|||||||
width: 120rpx;
|
width: 120rpx;
|
||||||
height: 120rpx;
|
height: 120rpx;
|
||||||
border-radius: 10rpx;
|
border-radius: 10rpx;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-info-content {
|
.user-info-content {
|
||||||
@@ -549,6 +937,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 10rpx;
|
gap: 10rpx;
|
||||||
|
margin-left: 10rpx;
|
||||||
|
|
||||||
.username {
|
.username {
|
||||||
color: $white;
|
color: $white;
|
||||||
@@ -589,6 +978,11 @@
|
|||||||
.honor_text {
|
.honor_text {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: $white;
|
color: $white;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.bar_rank{
|
||||||
|
padding:0 6rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -619,7 +1013,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 54rpx;
|
top: 54rpx;
|
||||||
width: 160rpx;
|
width: 150rpx;
|
||||||
height: 56rpx;
|
height: 56rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -641,10 +1035,11 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
top: 54rpx;
|
top: 54rpx;
|
||||||
width: 160rpx;
|
width: 160rpx;
|
||||||
height: 56rpx;
|
height: 54rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border: 1rpx solid #fc564a;
|
border: 1rpx solid #fc564a;
|
||||||
|
border-right: none;
|
||||||
border-radius: 30rpx 0 0 30rpx;
|
border-radius: 30rpx 0 0 30rpx;
|
||||||
background: #fff url("@/static/qd_bg.9.png")no-repeat 0 0;
|
background: #fff url("@/static/qd_bg.9.png")no-repeat 0 0;
|
||||||
background-size: 57rpx 56rpx;
|
background-size: 57rpx 56rpx;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<uni-nav-bar title="患教学堂" fixed color="#8B2316" height="140rpx" :border="false" backgroundColor="#eeeeee"></uni-nav-bar>
|
<navBar :title="'患教学堂'" :showLeft="false"></navBar>
|
||||||
<view class="page">
|
<view class="page">
|
||||||
<!-- 顶部标题栏 -->
|
<!-- 顶部标题栏 -->
|
||||||
|
|
||||||
@@ -10,12 +10,13 @@
|
|||||||
<view class="tab-item" :class="{ active: activeTab === 0 }" @click="switchTab(0)">
|
<view class="tab-item" :class="{ active: activeTab === 0 }" @click="switchTab(0)">
|
||||||
患教文库
|
患教文库
|
||||||
</view>
|
</view>
|
||||||
|
<view class="bar"></view>
|
||||||
<view class="tab-item" :class="{ active: activeTab === 1 }" @click="switchTab(1)">
|
<view class="tab-item" :class="{ active: activeTab === 1 }" @click="switchTab(1)">
|
||||||
患教视频
|
患教视频
|
||||||
</view>
|
</view>
|
||||||
<view class="tab-item" :class="{ active: activeTab === 2 }" @click="switchTab(2)">
|
<!-- <view class="tab-item" :class="{ active: activeTab === 2 }" @click="switchTab(2)">
|
||||||
常见问题
|
常见问题
|
||||||
</view>
|
</view> -->
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 筛选栏 -->
|
<!-- 筛选栏 -->
|
||||||
@@ -51,7 +52,7 @@
|
|||||||
:class="{ active: tag.selected }"
|
:class="{ active: tag.selected }"
|
||||||
@click="toggleTag(index)"
|
@click="toggleTag(index)"
|
||||||
>
|
>
|
||||||
{{ tag.DES }}
|
{{ tag.NAME }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -74,20 +75,20 @@
|
|||||||
:lower-threshold="100"
|
:lower-threshold="100"
|
||||||
>
|
>
|
||||||
<view class="article-item" v-for="(article, index) in articleList" :key="article.uuid || index" @click="goToDetail(article)">
|
<view class="article-item" v-for="(article, index) in articleList" :key="article.uuid || index" @click="goToDetail(article)">
|
||||||
<image class="article-image" :src="article.image" mode="aspectFill"></image>
|
<image class="article-image" :src="article.image"></image>
|
||||||
<view class="article-content">
|
<view class="article-content">
|
||||||
<view class="article-title">{{ article.title }}</view>
|
<view class="article-title">{{ article.title }}</view>
|
||||||
<view class="article-meta">
|
<view class="article-meta">
|
||||||
<view class="date-tag" v-if="article.isToday">今日</view>
|
<view class="date-tag" v-if="article.isToday">今日</view>
|
||||||
<view class="date" v-else>{{ article.date }}</view>
|
<view class="date" v-else>{{ article.date }}</view>
|
||||||
<view class="stats">
|
<view class="stats">
|
||||||
<view class="stat-item">
|
<view class="stat-item readnum">
|
||||||
<uni-icons type="eye" size="12" color="#999"></uni-icons>
|
<uni-icons type="eye" size="12" color="#999"></uni-icons>
|
||||||
<text>{{ article.views }}</text>
|
<text>{{ formatNumber(article.views) }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="stat-item">
|
<view class="stat-item">
|
||||||
<uni-icons type="hand-up" size="13" color="#999"></uni-icons>
|
<uni-icons type="hand-up" size="13" color="#999"></uni-icons>
|
||||||
<text>{{ article.likes }}</text>
|
<text>{{ formatNumber(article.likes) }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -107,8 +108,9 @@
|
|||||||
|
|
||||||
<!-- 空状态 -->
|
<!-- 空状态 -->
|
||||||
<view class="empty-state" v-if="articleList.length === 0 && !loading">
|
<view class="empty-state" v-if="articleList.length === 0 && !loading">
|
||||||
<uni-icons type="article" size="80" color="#cccccc"></uni-icons>
|
<empty :emptyDesc="'暂无患教信息'"></empty>
|
||||||
<text class="empty-text">暂无文章</text>
|
<!-- <uni-icons type="article" size="80" color="#cccccc"></uni-icons>
|
||||||
|
<text class="empty-text">暂无文章</text> -->
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
@@ -120,7 +122,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { onShow } from "@dcloudio/uni-app";
|
import {onShow,onLoad,onBackPress } from "@dcloudio/uni-app";
|
||||||
import CustomTabbar from '@/components/tabBar/tabBar.vue';
|
import CustomTabbar from '@/components/tabBar/tabBar.vue';
|
||||||
import upImg from "@/static/cb_up.png"
|
import upImg from "@/static/cb_up.png"
|
||||||
import downImg from "@/static/cb_up.png"
|
import downImg from "@/static/cb_up.png"
|
||||||
@@ -129,9 +131,24 @@
|
|||||||
import api from "@/api/api.js"
|
import api from "@/api/api.js"
|
||||||
import docUrl from '@/utils/docUrl.js';
|
import docUrl from '@/utils/docUrl.js';
|
||||||
import navTo from '@/utils/navTo.js';
|
import navTo from '@/utils/navTo.js';
|
||||||
|
import navBar from "@/components/navBar/navBar.vue"
|
||||||
|
import formatNumber from '@/utils/formatNumber.js';
|
||||||
const type=ref(1)
|
const type=ref(1)
|
||||||
|
onBackPress(() => {
|
||||||
|
plus.runtime.quit();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
onLoad(() => {
|
||||||
|
uni.sendNativeEvent("portraitReport",{
|
||||||
|
msg:{
|
||||||
|
event_nickname: "list_page",
|
||||||
|
page_type: "患教文库",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
(ret) => {
|
||||||
|
console.log(ret);
|
||||||
|
});
|
||||||
|
})
|
||||||
// 分页相关状态
|
// 分页相关状态
|
||||||
const currentPage = ref(1);
|
const currentPage = ref(1);
|
||||||
const pageSize = ref(10);
|
const pageSize = ref(10);
|
||||||
@@ -147,7 +164,8 @@
|
|||||||
// 重置分页状态
|
// 重置分页状态
|
||||||
currentPage.value = 1;
|
currentPage.value = 1;
|
||||||
hasMore.value = true;
|
hasMore.value = true;
|
||||||
polularScienceArticleListByKeywordsNew(true);
|
articleList.value = [];
|
||||||
|
polularScienceArticleListByKeywordsNew(false);
|
||||||
};
|
};
|
||||||
const loadGuideTags = async () => {
|
const loadGuideTags = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -195,9 +213,9 @@
|
|||||||
// 判断是否还有更多数据
|
// 判断是否还有更多数据
|
||||||
hasMore.value = newData.length >= pageSize.value;
|
hasMore.value = newData.length >= pageSize.value;
|
||||||
|
|
||||||
if (!isRefresh) {
|
// if (!isRefresh) {
|
||||||
currentPage.value++;
|
// currentPage.value++;
|
||||||
}
|
// }
|
||||||
|
|
||||||
console.log('文章数据加载成功:', articleList.value);
|
console.log('文章数据加载成功:', articleList.value);
|
||||||
}
|
}
|
||||||
@@ -240,9 +258,18 @@
|
|||||||
|
|
||||||
// 格式化日期
|
// 格式化日期
|
||||||
const formatDate = (date) => {
|
const formatDate = (date) => {
|
||||||
|
const today = new Date();
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const currentYear = today.getFullYear();
|
||||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
const day = String(date.getDate()).padStart(2, '0');
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
return `${month}-${day}`;
|
|
||||||
|
// 如果年份是今年,只显示月日,否则显示年月日
|
||||||
|
if (year === currentYear) {
|
||||||
|
return `${month}-${day}`;
|
||||||
|
} else {
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// 筛选标签数据
|
// 筛选标签数据
|
||||||
const filterTags = ref([]);
|
const filterTags = ref([]);
|
||||||
@@ -255,12 +282,12 @@
|
|||||||
|
|
||||||
if(index==1){
|
if(index==1){
|
||||||
navTo({
|
navTo({
|
||||||
url: '/pages_app/patientVideo/patientVideo'
|
url: '/pages_app/patientVideo/patientVideo?from=patientClass'
|
||||||
})
|
})
|
||||||
}else if(index==2){
|
}else if(index==2){
|
||||||
let url=encodeURIComponent('https://wx.igandan.com/wxPatient/index.htm#/problem?link=share&fromtype=doctor')
|
let url=encodeURIComponent('https://wx.igandan.com/wxPatient/index.htm#/problem?link=share&fromtype=doctor')
|
||||||
navTo({
|
navTo({
|
||||||
url: '/pages_app/webview/webview?url='+url
|
url: '/pages_app/webview/webview?url='+url+'&title='+'常见问题'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -270,15 +297,15 @@
|
|||||||
// 跳转到详情页
|
// 跳转到详情页
|
||||||
if (article.path) {
|
if (article.path) {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages_app/webview/webview?url=${encodeURIComponent(docUrl+article.path)}&title=${encodeURIComponent(article.title)}`
|
url: `/pages_app/webview/webviewClass?url=${encodeURIComponent(docUrl+article.path+'?fromtype=doctor')}&title=患教详情&uuid=${article.uuid}&sharetitle=${article.title}&summary=${article.summary}&type=huanjiao&imgPath=${encodeURIComponent(article.image)}&tags=${article.tags}`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 跳转到搜索页面
|
// 跳转到搜索页面
|
||||||
const goToSearch = () => {
|
const goToSearch = () => {
|
||||||
uni.navigateTo({
|
uni.sendNativeEvent('goHomeSearch',{
|
||||||
url: '/pages_app/search/search'
|
msg: 'patientClass'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -296,6 +323,7 @@
|
|||||||
// 上拉加载更多
|
// 上拉加载更多
|
||||||
const onLoadMore = async () => {
|
const onLoadMore = async () => {
|
||||||
if (!hasMore.value || loading.value) return;
|
if (!hasMore.value || loading.value) return;
|
||||||
|
currentPage.value++
|
||||||
await polularScienceArticleListByKeywordsNew(false);
|
await polularScienceArticleListByKeywordsNew(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -319,7 +347,19 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const toggleTag = (index) => {
|
const toggleTag = (index) => {
|
||||||
filterTags.value[index].selected = !filterTags.value[index].selected;
|
const tag = filterTags.value[index];
|
||||||
|
// 若当前为未选中状态,且已选满3个,则禁止再选
|
||||||
|
if (!tag.selected) {
|
||||||
|
const selectedCount = filterTags.value.filter(t => t.selected).length;
|
||||||
|
if (selectedCount >= 3) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '最多选择3个标签',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tag.selected = !tag.selected;
|
||||||
};
|
};
|
||||||
|
|
||||||
const resetFilter = () => {
|
const resetFilter = () => {
|
||||||
@@ -333,25 +373,26 @@
|
|||||||
// 检查是否有选中的标签
|
// 检查是否有选中的标签
|
||||||
const hasSelected = filterTags.value.some(tag => tag.selected);
|
const hasSelected = filterTags.value.some(tag => tag.selected);
|
||||||
isFilterActive.value = hasSelected;
|
isFilterActive.value = hasSelected;
|
||||||
|
let words='';
|
||||||
// 执行筛选逻辑
|
// 执行筛选逻辑
|
||||||
if (hasSelected) {
|
if (hasSelected) {
|
||||||
const selectedTags = filterTags.value.filter(tag => tag.selected).map(tag => tag.DES);
|
const selectedTags = filterTags.value.filter(tag => tag.selected).map(tag => tag.NAME);
|
||||||
console.log('选中的标签:', selectedTags);
|
console.log('选中的标签:', selectedTags);
|
||||||
keywords.value = selectedTags.join(',');
|
words = selectedTags.join(',');
|
||||||
} else {
|
} else {
|
||||||
keywords.value = '';
|
words = '';
|
||||||
}
|
}
|
||||||
|
keywords.value = words;
|
||||||
// 重置分页状态
|
// 重置分页状态
|
||||||
currentPage.value = 1;
|
currentPage.value = 1;
|
||||||
hasMore.value = true;
|
hasMore.value = true;
|
||||||
|
articleList.value = [];
|
||||||
showFilter.value = false;
|
showFilter.value = false;
|
||||||
polularScienceArticleListByKeywordsNew(true);
|
polularScienceArticleListByKeywordsNew(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
|
|
||||||
polularScienceArticleListByKeywordsNew(true);
|
polularScienceArticleListByKeywordsNew(true);
|
||||||
loadGuideTags();
|
loadGuideTags();
|
||||||
});
|
});
|
||||||
@@ -369,14 +410,14 @@ $gray-dark: #666;
|
|||||||
$text-color: #333;
|
$text-color: #333;
|
||||||
|
|
||||||
// 尺寸变量
|
// 尺寸变量
|
||||||
$border-radius: 8px;
|
$border-radius: 16rpx;
|
||||||
$border-radius-small: 6px;
|
$border-radius-small: 12rpx;
|
||||||
$padding: 15px;
|
$padding: 30rpx;
|
||||||
$padding-small: 10px;
|
$padding-small: 20rpx;
|
||||||
|
|
||||||
.page {
|
.page {
|
||||||
background-color: $gray-bg;
|
background-color: $gray-bg;
|
||||||
height: calc(100vh - 140rpx);
|
height: calc(100vh - 180rpx);
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -385,19 +426,25 @@ $padding-small: 10px;
|
|||||||
.top{
|
.top{
|
||||||
width:100%;
|
width:100%;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top:140rpx;
|
top:calc(var(--status-bar-height) + 44px);
|
||||||
}
|
}
|
||||||
// 选项卡
|
// 选项卡
|
||||||
.tabs {
|
.tabs {
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
display: flex;
|
display: flex;
|
||||||
border-bottom: 1px solid $gray-light;
|
align-items: center;
|
||||||
|
border-bottom: 2rpx solid $gray-light;
|
||||||
|
.bar{
|
||||||
|
width: 2rpx;
|
||||||
|
height: 98rpx;
|
||||||
|
background-color: $gray-light;
|
||||||
|
|
||||||
|
}
|
||||||
.tab-item {
|
.tab-item {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: $padding 0;
|
padding: $padding 0;
|
||||||
font-size: 16px;
|
font-size: 32rpx;
|
||||||
color: $gray-dark;
|
color: $gray-dark;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
@@ -411,8 +458,8 @@ $padding-small: 10px;
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
width: 30px;
|
width: 60rpx;
|
||||||
height: 2px;
|
height: 4rpx;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -425,25 +472,25 @@ $padding-small: 10px;
|
|||||||
padding: $padding-small $padding;
|
padding: $padding-small $padding;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-bottom: 1px solid $gray-light;
|
border-bottom: 2rpx solid $gray-light;
|
||||||
|
|
||||||
.search-box {
|
.search-box {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 5px;
|
gap: 10rpx;
|
||||||
|
|
||||||
.search-text {
|
.search-text {
|
||||||
font-size: 14px;
|
font-size: 28rpx;
|
||||||
color: $gray-medium;
|
color: $gray-medium;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
width: 1px;
|
width: 2rpx;
|
||||||
height: 16px;
|
height: 32rpx;
|
||||||
background-color: $gray-medium;
|
background-color: $gray-light;
|
||||||
margin: 0 $padding;
|
margin: 0 $padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,8 +499,8 @@ $padding-small: 10px;
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 3px;
|
gap: 6rpx;
|
||||||
font-size: 14px;
|
font-size: 28rpx;
|
||||||
color: #999;
|
color: #999;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
@@ -466,23 +513,24 @@ $padding-small: 10px;
|
|||||||
// 文章列表
|
// 文章列表
|
||||||
.article-list {
|
.article-list {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
height:calc(100vh - 450rpx);
|
// height:calc(100vh - var(--status-bar-height) - 44px - 207rpx);
|
||||||
top: 342rpx;
|
top: calc(var(--status-bar-height) + 44px + 188rpx);
|
||||||
|
|
||||||
padding-bottom: 130rpx;
|
bottom: 128rpx;
|
||||||
.article-item {
|
.article-item {
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
margin-bottom: $padding-small;
|
margin-bottom: $padding-small;
|
||||||
border-radius: $border-radius;
|
border-radius: $border-radius;
|
||||||
padding: $padding;
|
padding: $padding;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 12px;
|
|
||||||
|
|
||||||
.article-image {
|
.article-image {
|
||||||
width: 80px;
|
width: 260rpx;
|
||||||
height: 80px;
|
height: 160rpx;
|
||||||
border-radius: $border-radius-small;
|
border-radius: $border-radius-small;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
margin-right: 24rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.article-content {
|
.article-content {
|
||||||
@@ -492,7 +540,7 @@ $padding-small: 10px;
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
.article-title {
|
.article-title {
|
||||||
font-size: 16px;
|
font-size: 32rpx;
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
margin-bottom: $padding-small;
|
margin-bottom: $padding-small;
|
||||||
@@ -506,32 +554,40 @@ $padding-small: 10px;
|
|||||||
|
|
||||||
.article-meta {
|
.article-meta {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
.date-tag {
|
.date-tag {
|
||||||
background-color: $primary-color;
|
background-color: $primary-color;
|
||||||
color: $white;
|
color: $white;
|
||||||
font-size: 12px;
|
font-size: 24rpx;
|
||||||
padding: 2px 6px;
|
padding: 4rpx 12rpx;
|
||||||
border-radius: 3px;
|
border-radius: 6rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.date {
|
.date {
|
||||||
font-size: 12px;
|
width: 125rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
color: $gray-medium;
|
color: $gray-medium;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats {
|
.stats {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: $padding;
|
gap: $padding;
|
||||||
|
margin-left: 50rpx;
|
||||||
|
.readnum{
|
||||||
|
width:100rpx;
|
||||||
|
}
|
||||||
.stat-item {
|
.stat-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 3px;
|
gap: 10rpx;
|
||||||
font-size: 12px;
|
|
||||||
|
font-size: 24rpx;
|
||||||
color: $gray-medium;
|
color: $gray-medium;
|
||||||
|
text{
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -591,8 +647,8 @@ $padding-small: 10px;
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 2px;
|
gap: 4rpx;
|
||||||
font-size: 12px;
|
font-size: 24rpx;
|
||||||
color: $gray-medium;
|
color: $gray-medium;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
@@ -600,7 +656,7 @@ $padding-small: 10px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
text {
|
text {
|
||||||
font-size: 10px;
|
font-size: 20rpx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -619,7 +675,7 @@ $padding-small: 10px;
|
|||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
|
|
||||||
.filter-content {
|
.filter-content {
|
||||||
margin-top:329rpx;
|
margin-top:calc(var(--status-bar-height) + 44px + 188rpx);;
|
||||||
|
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
// border-radius: 20rpx 20rpx 0 0;
|
// border-radius: 20rpx 20rpx 0 0;
|
||||||
@@ -630,17 +686,21 @@ $padding-small: 10px;
|
|||||||
.filter-tags {
|
.filter-tags {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 20rpx;
|
|
||||||
margin-bottom: 60rpx;
|
margin-bottom: 60rpx;
|
||||||
max-height: 65vh;
|
max-height: 65vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
.tag-item {
|
.tag-item {
|
||||||
background-color: #f8f8f8;
|
background-color: #f8f8f8;
|
||||||
color: $gray-dark;
|
color: $gray-dark;
|
||||||
padding: 8rpx 24rpx;
|
padding: 8rpx 0rpx;
|
||||||
|
width:152rpx;
|
||||||
|
margin:8rpx;
|
||||||
|
text-align:center;
|
||||||
border-radius: 30rpx;
|
border-radius: 30rpx;
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
border: 2rpx solid #efefef;
|
border: 2rpx solid #efefef;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted } from 'vue';
|
||||||
|
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||||
|
|
||||||
|
// 页面加载
|
||||||
|
onLoad(() => {
|
||||||
|
console.log('登录页面加载完成');
|
||||||
|
// #ifdef APP
|
||||||
|
|
||||||
|
console.log('一键登录');
|
||||||
|
uni.login({
|
||||||
|
provider: 'univerify',
|
||||||
|
univerifyStyle: {
|
||||||
|
"fullScreen": true, // 是否全屏显示,默认值: false
|
||||||
|
"backgroundColor": "#ffffff", // 授权页面背景颜色,默认值:#ffffff
|
||||||
|
"backgroundImage": "", // 全屏显示的背景图片,默认值:"" (仅支持本地图片,只有全屏显示时支持)
|
||||||
|
"icon": {
|
||||||
|
"path": "static/xxx.png", // 自定义显示在授权框中的logo,仅支持本地图片 默认显示App logo
|
||||||
|
"width": "60px", //图标宽度 默认值:60px
|
||||||
|
"height": "60px" //图标高度 默认值:60px
|
||||||
|
},
|
||||||
|
"closeIcon": {
|
||||||
|
"path": "static/xxx.png", // 自定义显示在授权框中的logo,仅支持本地图片
|
||||||
|
"width": "60px", //图标宽度 默认值:60px (HBuilderX 4.0+ 仅iOS支持)
|
||||||
|
"height": "60px" //图标高度 默认值:60px (HBuilderX 4.0+ 仅iOS支持)
|
||||||
|
},
|
||||||
|
"phoneNum": {
|
||||||
|
"color": "#202020" // 手机号文字颜色 默认值:#202020
|
||||||
|
},
|
||||||
|
"slogan": {
|
||||||
|
"color": "#BBBBBB" // slogan 字体颜色 默认值:#BBBBBB
|
||||||
|
},
|
||||||
|
"authButton": {
|
||||||
|
"normalColor": "#3479f5", // 授权按钮正常状态背景颜色 默认值:#3479f5
|
||||||
|
"highlightColor": "#2861c5", // 授权按钮按下状态背景颜色 默认值:#2861c5(仅ios支持)
|
||||||
|
"disabledColor": "#73aaf5", // 授权按钮不可点击时背景颜色 默认值:#73aaf5(仅ios支持)
|
||||||
|
"textColor": "#ffffff", // 授权按钮文字颜色 默认值:#ffffff
|
||||||
|
"title": "本机号码一键登录", // 授权按钮文案 默认值:“本机号码一键登录”
|
||||||
|
"borderRadius": "24px" // 授权按钮圆角 默认值:"24px" (按钮高度的一半)
|
||||||
|
},
|
||||||
|
"otherLoginButton": {
|
||||||
|
"visible": true, // 是否显示其他登录按钮,默认值:true
|
||||||
|
"normalColor": "", // 其他登录按钮正常状态背景颜色 默认值:透明
|
||||||
|
"highlightColor": "", // 其他登录按钮按下状态背景颜色 默认值:透明
|
||||||
|
"textColor": "#656565", // 其他登录按钮文字颜色 默认值:#656565
|
||||||
|
"title": "其他登录方式", // 其他登录方式按钮文字 默认值:“其他登录方式”
|
||||||
|
"borderColor": "", //边框颜色 默认值:透明(仅iOS支持)
|
||||||
|
"borderRadius": "0px" // 其他登录按钮圆角 默认值:"24px" (按钮高度的一半)
|
||||||
|
},
|
||||||
|
"privacyTerms": {
|
||||||
|
"defaultCheckBoxState": true, // 条款勾选框初始状态 默认值: true
|
||||||
|
"isCenterHint": false, //未勾选服务条款时点击登录按钮的提示是否居中显示 默认值: false (3.7.13+ 版本支持)
|
||||||
|
"uncheckedImage": "", // 可选 条款勾选框未选中状态图片(仅支持本地图片 建议尺寸 24x24px)(3.2.0+ 版本支持)
|
||||||
|
"checkedImage": "", // 可选 条款勾选框选中状态图片(仅支持本地图片 建议尺寸24x24px)(3.2.0+ 版本支持)
|
||||||
|
"checkBoxSize": 12, // 可选 条款勾选框大小
|
||||||
|
"textColor": "#BBBBBB", // 文字颜色 默认值:#BBBBBB
|
||||||
|
"termsColor": "#5496E3", // 协议文字颜色 默认值: #5496E3
|
||||||
|
"prefix": "我已阅读并同意", // 条款前的文案 默认值:“我已阅读并同意”
|
||||||
|
"suffix": "并使用本机号码登录", // 条款后的文案 默认值:“并使用本机号码登录”
|
||||||
|
"privacyItems": [ // 自定义协议条款,最大支持2个,需要同时设置url和title. 否则不生效
|
||||||
|
{
|
||||||
|
"url": "https://", // 点击跳转的协议详情页面
|
||||||
|
"title": "用户服务协议" // 协议名称
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
success(res) { // 登录成功
|
||||||
|
console.log(res.authResult); // {openid:'登录授权唯一标识',access_token:'接口返回的 token'}
|
||||||
|
},
|
||||||
|
fail(res) { // 登录失败
|
||||||
|
console.log(res.errCode)
|
||||||
|
console.log(res.errMsg)
|
||||||
|
uni.redirectTo({
|
||||||
|
url: '/pages_app/login/login?univerify=0'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
});
|
||||||
|
|
||||||
|
// 页面显示
|
||||||
|
onShow(() => {
|
||||||
|
console.log('登录页面显示');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,299 @@
|
|||||||
|
<template>
|
||||||
|
<view class="wrap">
|
||||||
|
<view :class="isFull ? 'player-full' : 'player'">
|
||||||
|
<plv-player
|
||||||
|
ref="vodPlayer"
|
||||||
|
class="vod-player"
|
||||||
|
seekType=1
|
||||||
|
autoPlay=true
|
||||||
|
disableScreenCAP=false
|
||||||
|
rememberLastPosition=false
|
||||||
|
@onPlayStatus="onPlayStatus"
|
||||||
|
@onPlayError="onPlayError"
|
||||||
|
@positionChange="positionChange"
|
||||||
|
@onEnableSubtitle="onEnableSubtitle"
|
||||||
|
@onSRTTextConfig="onSRTTextConfig"
|
||||||
|
@onSRTTitle="onSRTTitle">
|
||||||
|
</plv-player>
|
||||||
|
<skin ref="skinRef"
|
||||||
|
class="skin-control"
|
||||||
|
:defaultVolume="defaultVolume"
|
||||||
|
@onPlayBtnClick="onPlayBtnClick"
|
||||||
|
@onToSeek="onToSeek"
|
||||||
|
@onFullBtnClick="onFullBtnClick"
|
||||||
|
@onHdBtnClick="onHdBtnClick"
|
||||||
|
@onRateBtnClick="onRateBtnClick"
|
||||||
|
@onVolumeChanged="onVolumeChanged"
|
||||||
|
@onScalingBtnClick="onScalingBtnClick"
|
||||||
|
@onScreenShot="onScreenShot"
|
||||||
|
@onChangeSRTBtnClick="onChangeSRTBtnClick"
|
||||||
|
@onChangeSRTSingleMode="onChangeSRTSingleMode"
|
||||||
|
@onOpenSRT="onOpenSRT">
|
||||||
|
</skin>
|
||||||
|
</view>
|
||||||
|
<view v-if="!isFull" style="padding: 20rpx;">
|
||||||
|
<input class="uni-input" style="min-height: 35px; height: 35px; border: 1px solid #cccccc;font-size: 14px;" :value="videoVid"
|
||||||
|
@input="onVidInput" placeholder="请输入视频vid" />
|
||||||
|
<button type="primary" @click="setVid()">播放</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { onShow } from '@dcloudio/uni-app';
|
||||||
|
//import Head from '../../components/page-head.nvue';
|
||||||
|
//import skin from '@/components/plv-player-skin/skin.nvue';
|
||||||
|
//import DragTips from '@/components/plv-player-skin/drag-tips.nvue';
|
||||||
|
const dom = weex.requireModule('dom');
|
||||||
|
var configModule = uni.requireNativePlugin("PLV-VodUniPlugin-ConfigModule")
|
||||||
|
const vod=ref(null);
|
||||||
|
|
||||||
|
const title='播放器Demo';
|
||||||
|
// 播放器组件
|
||||||
|
const vodPlayer=ref(null);
|
||||||
|
const skinRef=ref(null);
|
||||||
|
const isFull=ref(false);
|
||||||
|
const defaultVolume=ref(0.5);
|
||||||
|
const videoVid=ref('4ae3fe3ab5a2009a8d6605d81b2e3c9b_4');
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
configModule.setConfig({
|
||||||
|
'config': "dDzXiPJ8psA/7LvtlPgpNfdOjzKVVEYvca1QBOp2MqCVKC93YiligqqfzOzETkDmolLNBUF4vAykBuUnn+U4V9NoK9vaofwESluIMO9WSB0eWhrw+fBkn+h+OZAmwmYgHQ6fCtsggZKN6cW/FhjWAQ==", //加密串配置
|
||||||
|
},
|
||||||
|
(ret) => {
|
||||||
|
if (ret.isSuccess == true) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '设置加密串成功',
|
||||||
|
icon: "none"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
const onVidInput=(event)=> {
|
||||||
|
videoVid.value = event.detail.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const setVid=()=> {
|
||||||
|
if(!videoVid.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "请输入视频Vid",
|
||||||
|
icon: "none"
|
||||||
|
})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vodPlayer.value.setVid({
|
||||||
|
vid:videoVid.value,
|
||||||
|
level:0
|
||||||
|
}, (ret) => {
|
||||||
|
console.log(12)
|
||||||
|
console.log(ret)
|
||||||
|
text.value = JSON.stringify(ret);
|
||||||
|
if (ret.errMsg != null) {
|
||||||
|
uni.showToast({
|
||||||
|
title: ret.errMsg,
|
||||||
|
icon: "none"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPlayError=(e)=>{
|
||||||
|
console.log(e);
|
||||||
|
if (e.detail.errEvent != null) {
|
||||||
|
uni.showToast({
|
||||||
|
title:'playErrorEvent - '+e.detail.errEvent,
|
||||||
|
icon: "none"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const positionChange=(e)=>{
|
||||||
|
skinRef.value.timeUpdate(e.detail.currentPosition);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEnableSubtitle=(e)=>{
|
||||||
|
console.log("===1" + e.detail);
|
||||||
|
skinRef.value.setEnableSubtitle(e.detail.isEnableSubtitle, e.detail.isEnableDoubleSubtitle);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSRTTextConfig=(e)=>{
|
||||||
|
console.log("===1 fontColor: " + e.detail.fontColor);
|
||||||
|
skinRef.value.setSRTTextConfig(e.detail);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSRTTitle=(e)=>{
|
||||||
|
console.log("===1 onSRTTitle" + e.detail);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPlayStatus=(e)=>{
|
||||||
|
//const { skin, vodPlayer } = this;
|
||||||
|
const state = e.detail.playbackState;
|
||||||
|
const preparedToPlay = e.detail.preparedToPlay;
|
||||||
|
if (state != null) {
|
||||||
|
skinRef.value.changePlayStatus(state === 'start');
|
||||||
|
} else if (preparedToPlay != null) {
|
||||||
|
updateDuration();
|
||||||
|
updateLevels();
|
||||||
|
updateScaling();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateDuration=()=> {
|
||||||
|
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
vodPlayer.value.getDuration(null, ret => {
|
||||||
|
skinRef.value.updateDuration(ret.duration);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateLevels=()=> {
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
|
||||||
|
vodPlayer.value.getLevelNum(null, ret => {
|
||||||
|
skinRef.value.updateLevels(ret.levelNum);
|
||||||
|
});
|
||||||
|
|
||||||
|
vodPlayer.value.getCurrentLevel(null, ret => {
|
||||||
|
skinRef.value.updateCurrentLevel(ret.currentLevel);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateScaling=()=> {
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
|
||||||
|
vodPlayer.value.getScalingMode({}, ret => {
|
||||||
|
skinRef.value.updateScaling(ret.scalingMode);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPlayBtnClick=(isPlaying)=> {
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
isPlaying ? vodPlayer.value.start() : vodPlayer.value.pause();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onHdBtnClick=(level)=> {
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
vodPlayer.value.changeLevel({level});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onRateBtnClick=(speed)=> {
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
vodPlayer.value.setSpeed({speed});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onScalingBtnClick=(scalingMode)=> {
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
vodPlayer.value.setScalingMode({scalingMode});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeSRTBtnClick=(srt)=> {
|
||||||
|
console.log("===1 " + srt);
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
vodPlayer.value.changeSRT(srt);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onChangeSRTSingleMode=(isSingle)=> {
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
vodPlayer.value.changeSRTSingleMode(isSingle);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOpenSRT=(isOpen)=> {
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
vodPlayer.value.setOpenSRT({
|
||||||
|
openSrt: isOpen
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onFullBtnClick=(isFull)=> {
|
||||||
|
// plus.screen.unlockOrientation();
|
||||||
|
plus.navigator.setFullscreen(isFull);
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
isFull ? vodPlayer.value.changeToLandscape() : vodPlayer.value.changeToPortrait();
|
||||||
|
isFull.value = isFull;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onToSeek=(time)=> {
|
||||||
|
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
vodPlayer.value.seekTo({seconds: time});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onVolumeChanged=(value)=> {
|
||||||
|
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
vodPlayer.value.getVolume(null, ret => {
|
||||||
|
const changedValue = ret.volume + value;
|
||||||
|
|
||||||
|
const realValue =limit(changedValue, 0, 1);
|
||||||
|
|
||||||
|
vodPlayer.value.setVolume({volume: realValue});
|
||||||
|
|
||||||
|
skinRef.value.updateVolumeValue(realValue);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onScreenShot=()=> {
|
||||||
|
if (vodPlayer.value) return;
|
||||||
|
|
||||||
|
vodPlayer.value.snapshot(null, result =>{
|
||||||
|
if(result.errMsg != null){
|
||||||
|
console.log(result.errMsg)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 控制最小值,最大值
|
||||||
|
* @param num
|
||||||
|
* @param min
|
||||||
|
* @param max
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
const limit=(num, min, max)=> {
|
||||||
|
if (num < min) return min;
|
||||||
|
if (num > max) return max;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.wrap {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
height: 140rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player {
|
||||||
|
height: 400rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player-full {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vod-player {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-control {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,337 @@
|
|||||||
|
<template>
|
||||||
|
<view class="wrap">
|
||||||
|
<view :class="isFull ? 'player-full' : 'player'">
|
||||||
|
<plv-player
|
||||||
|
ref="vod"
|
||||||
|
class="vod-player"
|
||||||
|
seekType=1
|
||||||
|
autoPlay=true
|
||||||
|
disableScreenCAP=false
|
||||||
|
rememberLastPosition=false
|
||||||
|
@onPlayStatus="onPlayStatus"
|
||||||
|
@onPlayError="onPlayError"
|
||||||
|
@positionChange="positionChange"
|
||||||
|
@onEnableSubtitle="onEnableSubtitle"
|
||||||
|
@onSRTTextConfig="onSRTTextConfig"
|
||||||
|
@onSRTTitle="onSRTTitle">
|
||||||
|
</plv-player>
|
||||||
|
<Skin ref="skin"
|
||||||
|
class="skin-control"
|
||||||
|
:defaultVolume="defaultVolume"
|
||||||
|
@onPlayBtnClick="onPlayBtnClick"
|
||||||
|
@onToSeek="onToSeek"
|
||||||
|
@onFullBtnClick="onFullBtnClick"
|
||||||
|
@onHdBtnClick="onHdBtnClick"
|
||||||
|
@onRateBtnClick="onRateBtnClick"
|
||||||
|
@onVolumeChanged="onVolumeChanged"
|
||||||
|
@onScalingBtnClick="onScalingBtnClick"
|
||||||
|
@onScreenShot="onScreenShot"
|
||||||
|
@onChangeSRTBtnClick="onChangeSRTBtnClick"
|
||||||
|
@onChangeSRTSingleMode="onChangeSRTSingleMode"
|
||||||
|
@onOpenSRT="onOpenSRT">
|
||||||
|
</Skin>
|
||||||
|
</view>
|
||||||
|
<view v-if="!isFull" style="padding: 20rpx;">
|
||||||
|
<input class="uni-input" style="min-height: 35px; height: 35px; border: 1px solid #cccccc;font-size: 14px;" :value="videoVid"
|
||||||
|
@input="onVidInput" placeholder="请输入视频vid" />
|
||||||
|
<button type="primary" @click="setVid()">播放</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
//import Head from '../../components/page-head.nvue';
|
||||||
|
import Skin from '@/components/plv-player-skin2/skin.nvue';
|
||||||
|
//import DragTips from '@/components/plv-player-skin/drag-tips.nvue';
|
||||||
|
const dom = weex.requireModule('dom');
|
||||||
|
var configModule = uni.requireNativePlugin("PLV-VodUniPlugin-ConfigModule")
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
Skin,
|
||||||
|
//Head
|
||||||
|
},
|
||||||
|
|
||||||
|
onReady() {
|
||||||
|
configModule.setConfig({
|
||||||
|
'config': "dDzXiPJ8psA/7LvtlPgpNfdOjzKVVEYvca1QBOp2MqCVKC93YiligqqfzOzETkDmolLNBUF4vAykBuUnn+U4V9NoK9vaofwESluIMO9WSB0eWhrw+fBkn+h+OZAmwmYgHQ6fCtsggZKN6cW/FhjWAQ==", //加密串配置
|
||||||
|
},
|
||||||
|
(ret) => {
|
||||||
|
if (ret.isSuccess == true) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '设置加密串成功',
|
||||||
|
icon: "none"
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let errMsg = ret.errMsg;
|
||||||
|
uni.showToast({
|
||||||
|
title: '设置加密串失败:' + errMsg,
|
||||||
|
icon: "none"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.vodPlayer = this.$refs.vod;
|
||||||
|
this.skin = this.$refs.skin;
|
||||||
|
// plus.screen.lockOrientation('portrait-primary');
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
title: '播放器Demo',
|
||||||
|
// 播放器组件
|
||||||
|
vodPlayer: null,
|
||||||
|
// 控制栏组件
|
||||||
|
skin: null,
|
||||||
|
//是否全屏
|
||||||
|
isFull: false,
|
||||||
|
// 默认音量
|
||||||
|
defaultVolume: 0.5,
|
||||||
|
videoVid: '4ae3fe3ab5a2009a8d6605d81b2e3c9b_4'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
//输入vid
|
||||||
|
onVidInput: function(event) {
|
||||||
|
this.videoVid = event.detail.value;
|
||||||
|
},
|
||||||
|
|
||||||
|
setVid() {
|
||||||
|
if(!this.videoVid) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "请输入视频Vid",
|
||||||
|
icon: "none"
|
||||||
|
})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
vodPlayer.setVid({
|
||||||
|
vid:this.videoVid,
|
||||||
|
level:0
|
||||||
|
}, (ret) => {
|
||||||
|
console.log(12)
|
||||||
|
console.log(ret)
|
||||||
|
this.text = JSON.stringify(ret);
|
||||||
|
if (ret.errMsg != null) {
|
||||||
|
uni.showToast({
|
||||||
|
title: ret.errMsg,
|
||||||
|
icon: "none"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onPlayError(e){
|
||||||
|
console.log(e);
|
||||||
|
if (e.detail.errEvent != null) {
|
||||||
|
uni.showToast({
|
||||||
|
title:'playErrorEvent - '+e.detail.errEvent,
|
||||||
|
icon: "none"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
positionChange(e){
|
||||||
|
this.skin.timeUpdate(e.detail.currentPosition);
|
||||||
|
},
|
||||||
|
|
||||||
|
onEnableSubtitle(e){
|
||||||
|
console.log("===1" + e.detail);
|
||||||
|
this.skin.setEnableSubtitle(e.detail.isEnableSubtitle, e.detail.isEnableDoubleSubtitle);
|
||||||
|
},
|
||||||
|
|
||||||
|
onSRTTextConfig(e) {
|
||||||
|
console.log("===1 fontColor: " + e.detail.fontColor);
|
||||||
|
this.skit.setSRTTextConfig(e.detail);
|
||||||
|
},
|
||||||
|
|
||||||
|
onSRTTitle(e) {
|
||||||
|
console.log("===1 onSRTTitle" + e.detail);
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
onPlayStatus(e){
|
||||||
|
const { skin, vodPlayer } = this;
|
||||||
|
const state = e.detail.playbackState;
|
||||||
|
const preparedToPlay = e.detail.preparedToPlay;
|
||||||
|
if (state != null) {
|
||||||
|
this.skin.changePlayStatus(state === 'start');
|
||||||
|
} else if (preparedToPlay != null) {
|
||||||
|
this.updateDuration();
|
||||||
|
this.updateLevels();
|
||||||
|
this.updateScaling();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
updateDuration() {
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
vodPlayer.getDuration(null, ret => {
|
||||||
|
this.skin.updateDuration(ret.duration);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateLevels() {
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
|
||||||
|
vodPlayer.getLevelNum(null, ret => {
|
||||||
|
this.skin.updateLevels(ret.levelNum);
|
||||||
|
});
|
||||||
|
|
||||||
|
vodPlayer.getCurrentLevel(null, ret => {
|
||||||
|
this.skin.updateCurrentLevel(ret.currentLevel);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateScaling() {
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
|
||||||
|
vodPlayer.getScalingMode({}, ret => {
|
||||||
|
this.skin.updateScaling(ret.scalingMode);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onPlayBtnClick(isPlaying) {
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
isPlaying ? vodPlayer.start() : vodPlayer.pause();
|
||||||
|
},
|
||||||
|
|
||||||
|
onHdBtnClick(level) {
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
vodPlayer.changeLevel({level});
|
||||||
|
},
|
||||||
|
|
||||||
|
onRateBtnClick(speed) {
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
vodPlayer.setSpeed({speed});
|
||||||
|
},
|
||||||
|
|
||||||
|
onScalingBtnClick(scalingMode) {
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
vodPlayer.setScalingMode({scalingMode});
|
||||||
|
},
|
||||||
|
|
||||||
|
onChangeSRTBtnClick(srt) {
|
||||||
|
console.log("===1 " + srt);
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
vodPlayer.changeSRT(srt);
|
||||||
|
},
|
||||||
|
|
||||||
|
onChangeSRTSingleMode(isSingle) {
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
vodPlayer.changeSRTSingleMode(isSingle);
|
||||||
|
},
|
||||||
|
|
||||||
|
onOpenSRT(isOpen) {
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
vodPlayer.setOpenSRT({
|
||||||
|
openSrt: isOpen
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onFullBtnClick(isFull) {
|
||||||
|
// plus.screen.unlockOrientation();
|
||||||
|
plus.navigator.setFullscreen(isFull);
|
||||||
|
|
||||||
|
//通过h5+实现横竖屏
|
||||||
|
// isFull ? plus.screen.lockOrientation('landscape-primary') : plus.screen.lockOrientation('portrait-primary');
|
||||||
|
|
||||||
|
//通过原生实现横竖屏切换
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
isFull ? vodPlayer.changeToLandscape() : vodPlayer.changeToPortrait();
|
||||||
|
|
||||||
|
this.isFull = isFull;
|
||||||
|
},
|
||||||
|
|
||||||
|
onToSeek(time) {
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
vodPlayer.seekTo({seconds: time});
|
||||||
|
},
|
||||||
|
|
||||||
|
onVolumeChanged(value) {
|
||||||
|
const { vodPlayer, skin } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
vodPlayer.getVolume(null, ret => {
|
||||||
|
const changedValue = ret.volume + value;
|
||||||
|
|
||||||
|
const realValue = this.limit(changedValue, 0, 1);
|
||||||
|
|
||||||
|
vodPlayer.setVolume({volume: realValue});
|
||||||
|
|
||||||
|
skin.updateVolumeValue(realValue);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onScreenShot() {
|
||||||
|
const { vodPlayer } = this;
|
||||||
|
if (!vodPlayer) return;
|
||||||
|
|
||||||
|
vodPlayer.snapshot(null, result =>{
|
||||||
|
if(result.errMsg != null){
|
||||||
|
console.log(result.errMsg)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 控制最小值,最大值
|
||||||
|
* @param num
|
||||||
|
* @param min
|
||||||
|
* @param max
|
||||||
|
* @returns {*}
|
||||||
|
*/
|
||||||
|
limit(num, min, max) {
|
||||||
|
if (num < min) return min;
|
||||||
|
if (num > max) return max;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.wrap {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
height: 140rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player {
|
||||||
|
height: 400rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player-full {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vod-player {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skin-control {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -1,17 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<web-view :src="url"></web-view>
|
<navBar :title="title" ></navBar>
|
||||||
|
<web-view :src="url" :webview-styles="webviewStyles"></web-view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import navBar from "@/components/navBar/navBar.vue"
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
url: ''
|
url: '',
|
||||||
|
title: '新闻详情',
|
||||||
|
webviewStyles: {
|
||||||
|
width: '100%',
|
||||||
|
height: 'calc(100vh - 160px)'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLoad(item) {
|
onLoad(item) {
|
||||||
// 传入需要跳转的链接 使用web-view标签进行跳转
|
// 传入需要跳转的链接 使用web-view标签进行跳转
|
||||||
this.url = decodeURIComponent(item.url)
|
this.url = decodeURIComponent(item.url)
|
||||||
|
this.title = item.title;
|
||||||
// console.log(this.url)
|
// console.log(this.url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,843 @@
|
|||||||
|
<template>
|
||||||
|
<view class="zhinan-list-page">
|
||||||
|
<!-- 头部导航栏 -->
|
||||||
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
|
left-icon="left"
|
||||||
|
title="文献期刊"
|
||||||
|
@clickLeft="goBack"
|
||||||
|
|
||||||
|
color="#8B2316"
|
||||||
|
|
||||||
|
:border="false"
|
||||||
|
backgroundColor="#eeeeee"
|
||||||
|
>
|
||||||
|
|
||||||
|
</uni-nav-bar>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 使用scroll-view实现列表 -->
|
||||||
|
<scroll-view
|
||||||
|
class="guidelines-scroll-view"
|
||||||
|
scroll-y="true"
|
||||||
|
|
||||||
|
>
|
||||||
|
<!-- 指南列表 -->
|
||||||
|
<view class="guidelines-list">
|
||||||
|
<view
|
||||||
|
class="guideline-item"
|
||||||
|
v-for="(item, index) in downLoadtaskList"
|
||||||
|
:key="item.id || index"
|
||||||
|
|
||||||
|
>
|
||||||
|
<!-- 指南信息 -->
|
||||||
|
<view class="item-content">
|
||||||
|
<view class="item-title">{{ item.title }}</view>
|
||||||
|
<view class="item-bottom">
|
||||||
|
<view class="item-date">{{ formatDate(item.releaseTime) }}</view>
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<view class="item-action">
|
||||||
|
<view
|
||||||
|
class="view-btn"
|
||||||
|
@click.stop="viewGuideline(item)"
|
||||||
|
>查看</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 无数据提示 -->
|
||||||
|
<view class="no-data" v-if="downLoadtaskList.length === 0 ">
|
||||||
|
<uni-icons type="info" size="60" color="#999"></uni-icons>
|
||||||
|
<text>暂无数据</text>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
<!-- 组内排序弹窗 -->
|
||||||
|
<view v-if="showInnerSort" class="popup-panel">
|
||||||
|
<view
|
||||||
|
class="popup-item"
|
||||||
|
:class="{ active: sort == 1 }"
|
||||||
|
@click.stop="chooseInnerSort(1)"
|
||||||
|
>
|
||||||
|
<text class="item-text">下载量</text>
|
||||||
|
<uni-icons
|
||||||
|
v-if="sort == 1"
|
||||||
|
type="checkmarkempty"
|
||||||
|
color="#8B2316"
|
||||||
|
size="22"
|
||||||
|
></uni-icons>
|
||||||
|
</view>
|
||||||
|
<view class="popup-divider"></view>
|
||||||
|
<view
|
||||||
|
class="popup-item"
|
||||||
|
:class="{ active: sort == 2 }"
|
||||||
|
@click.stop="chooseInnerSort(2)"
|
||||||
|
>
|
||||||
|
<text class="item-text">上传时间</text>
|
||||||
|
<uni-icons
|
||||||
|
v-if="sort == 2"
|
||||||
|
type="checkmarkempty"
|
||||||
|
color="#8B2316"
|
||||||
|
size="22"
|
||||||
|
></uni-icons>
|
||||||
|
</view>
|
||||||
|
<view class="popup-divider"></view>
|
||||||
|
<view
|
||||||
|
class="popup-item"
|
||||||
|
:class="{ active: sort == 3 }"
|
||||||
|
@click.stop="chooseInnerSort(3)"
|
||||||
|
>
|
||||||
|
<text class="item-text">标题</text>
|
||||||
|
<uni-icons
|
||||||
|
v-if="sort == 3"
|
||||||
|
type="checkmarkempty"
|
||||||
|
color="#8B2316"
|
||||||
|
size="22"
|
||||||
|
></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted,computed,nextTick} from "vue";
|
||||||
|
import api from "@/api/api.js";
|
||||||
|
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||||
|
import docUrl from "@/utils/docUrl.js";
|
||||||
|
import navTo from "@/utils/navTo.js";
|
||||||
|
import hotImg from "@/static/hot_booklist.png";
|
||||||
|
const guidelinesList = ref([]);
|
||||||
|
const isLoading = ref(false);
|
||||||
|
const hasMoreData = ref(true);
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const isRefreshing = ref(false);
|
||||||
|
const keywords = ref("");
|
||||||
|
import upImg from "@/static/triangle_green_theme.png";
|
||||||
|
import downImg from "@/static/triangle_normal.png";
|
||||||
|
const loadMoreStatus = ref("more"); // 'loading', 'more', 'noMore'
|
||||||
|
const typeUuid = ref("");
|
||||||
|
const title = ref("");
|
||||||
|
const sort = ref(2);
|
||||||
|
const showInnerSort = ref(false);
|
||||||
|
const innerSortTitle = ref("上传时间");
|
||||||
|
import downloadStore from "@/store/downloadStoreFile.js";
|
||||||
|
const downloadTasks=ref([]);
|
||||||
|
const downLoadtaskList=computed(()=>{
|
||||||
|
return downloadTasks.value.filter((item)=>item.status == "completed" && item.type == "article");
|
||||||
|
});
|
||||||
|
const chooseInnerSort = (index) => {
|
||||||
|
sort.value = index;
|
||||||
|
if (index == 1) {
|
||||||
|
innerSortTitle.value = "下载量";
|
||||||
|
} else if (index == 2) {
|
||||||
|
innerSortTitle.value = "上传时间";
|
||||||
|
} else if (index == 3) {
|
||||||
|
innerSortTitle.value = "标题";
|
||||||
|
}
|
||||||
|
showInnerSort.value = false;
|
||||||
|
loadGuidelinesList(true);
|
||||||
|
};
|
||||||
|
onLoad((options) => {
|
||||||
|
|
||||||
|
});
|
||||||
|
const goGot = () => {
|
||||||
|
navTo({
|
||||||
|
url: "/pages_app/hot/hot?from=hot&typeUuid=" + typeUuid.value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const toggleInnerSort = () => {
|
||||||
|
showInnerSort.value = !showInnerSort.value;
|
||||||
|
};
|
||||||
|
onShow(() => {
|
||||||
|
|
||||||
|
syncTasksFromStore();
|
||||||
|
// 监听store变化
|
||||||
|
downloadStore.addListener((tasks) => {
|
||||||
|
downloadTasks.value = tasks;
|
||||||
|
|
||||||
|
});
|
||||||
|
// 恢复正在下载的任务
|
||||||
|
resumeDownloadingTasks();
|
||||||
|
// 页面显示时,如果列表为空则加载数据
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// 跳转到搜索页
|
||||||
|
const goToSearch = () => {
|
||||||
|
const q = keywords.value ? encodeURIComponent(keywords.value) : "";
|
||||||
|
const t = title.value ? encodeURIComponent(title.value) : "";
|
||||||
|
const type = typeUuid.value
|
||||||
|
? `&typeUuid=${encodeURIComponent(typeUuid.value)}`
|
||||||
|
: "";
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages_app/search/search?keywords=${q}&title=${t}${type}`,
|
||||||
|
});
|
||||||
|
// const goSearch=()=>{
|
||||||
|
// uni.sendNativeEvent('goHomeSearch', {
|
||||||
|
// msg: 'goHomeSearch'
|
||||||
|
// },ret => {
|
||||||
|
// console.log(ret);
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
|
// scroll-view 下拉刷新
|
||||||
|
const onRefresh = async () => {
|
||||||
|
console.log("scroll-view 下拉刷新触发");
|
||||||
|
isRefreshing.value = true;
|
||||||
|
await refreshData();
|
||||||
|
isRefreshing.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// scroll-view 滚动到底部
|
||||||
|
const onScrollToLower = () => {
|
||||||
|
console.log("=== onScrollToLower 触发 ===");
|
||||||
|
console.log("当前状态:", {
|
||||||
|
loadMoreStatus: loadMoreStatus.value,
|
||||||
|
isRefreshing: isRefreshing.value,
|
||||||
|
currentPage: currentPage.value,
|
||||||
|
listLength: guidelinesList.value.length,
|
||||||
|
hasMoreData: hasMoreData.value,
|
||||||
|
isLoading: isLoading.value,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (
|
||||||
|
loadMoreStatus.value === "more" &&
|
||||||
|
!isRefreshing.value &&
|
||||||
|
!isLoading.value
|
||||||
|
) {
|
||||||
|
console.log("条件满足,开始加载更多数据");
|
||||||
|
loadMoreData();
|
||||||
|
} else {
|
||||||
|
console.log("条件不满足,跳过加载:", {
|
||||||
|
loadMoreStatus: loadMoreStatus.value,
|
||||||
|
isRefreshing: isRefreshing.value,
|
||||||
|
isLoading: isLoading.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 刷新数据
|
||||||
|
const refreshData = async () => {
|
||||||
|
try {
|
||||||
|
currentPage.value = 1;
|
||||||
|
hasMoreData.value = true;
|
||||||
|
loadMoreStatus.value = "more";
|
||||||
|
|
||||||
|
await loadGuidelinesList(true);
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: "刷新成功",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("刷新失败:", error);
|
||||||
|
uni.showToast({
|
||||||
|
title: "刷新失败",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载指南列表
|
||||||
|
const loadGuidelinesList = async (isRefresh = false) => {
|
||||||
|
console.log("=== loadGuidelinesList 开始 ===");
|
||||||
|
console.log("当前参数:", {
|
||||||
|
isRefresh,
|
||||||
|
page: currentPage.value,
|
||||||
|
keywords: keywords.value,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (isLoading.value) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
isLoading.value = true;
|
||||||
|
loadMoreStatus.value = "loading";
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
page: currentPage.value,
|
||||||
|
pageSize: pageSize.value,
|
||||||
|
type: 1, // 诊疗指南类型
|
||||||
|
sort: 2,
|
||||||
|
typeUuid: typeUuid.value,
|
||||||
|
keywords: keywords.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await api.searchLibraryU(params);
|
||||||
|
console.log("指南列表响应:", res);
|
||||||
|
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
const newData = res.data.list || res.data;
|
||||||
|
|
||||||
|
if (isRefresh) {
|
||||||
|
guidelinesList.value = newData;
|
||||||
|
console.log("刷新模式:替换列表数据");
|
||||||
|
} else {
|
||||||
|
guidelinesList.value = [...guidelinesList.value, ...newData];
|
||||||
|
console.log("加载更多:追加数据到列表");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否还有更多数据
|
||||||
|
if (newData.length < pageSize.value) {
|
||||||
|
loadMoreStatus.value = "noMore";
|
||||||
|
hasMoreData.value = false;
|
||||||
|
console.log("没有更多数据了");
|
||||||
|
} else {
|
||||||
|
loadMoreStatus.value = "more";
|
||||||
|
hasMoreData.value = true;
|
||||||
|
// 只有在加载更多模式下才递增页码
|
||||||
|
if (!isRefresh) {
|
||||||
|
currentPage.value++;
|
||||||
|
console.log(`还有更多数据,下一页: ${currentPage.value}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error("加载指南列表失败:", res.message);
|
||||||
|
loadMoreStatus.value = "noMore";
|
||||||
|
uni.showToast({
|
||||||
|
title: res.message || "加载失败",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("加载指南列表异常:", error);
|
||||||
|
loadMoreStatus.value = "noMore";
|
||||||
|
uni.showToast({
|
||||||
|
title: "网络异常,请重试",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false;
|
||||||
|
console.log("=== loadGuidelinesList 结束 ===");
|
||||||
|
console.log("最终状态:", {
|
||||||
|
loadMoreStatus: loadMoreStatus.value,
|
||||||
|
page: currentPage.value,
|
||||||
|
listLength: guidelinesList.value.length,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 加载更多数据
|
||||||
|
const loadMoreData = () => {
|
||||||
|
console.log("=== loadMoreData 被调用 ===");
|
||||||
|
console.log("检查条件:", {
|
||||||
|
hasMoreData: hasMoreData.value,
|
||||||
|
isLoading: isLoading.value,
|
||||||
|
currentPage: currentPage.value,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hasMoreData.value && !isLoading.value) {
|
||||||
|
console.log("条件满足,开始加载更多数据");
|
||||||
|
loadGuidelinesList(false);
|
||||||
|
} else {
|
||||||
|
console.log("条件不满足,跳过加载更多");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 下载指南
|
||||||
|
const downloadGuideline = (item) => {
|
||||||
|
console.log("下载指南:", item);
|
||||||
|
uni.showToast({
|
||||||
|
title: "开始下载...",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 这里可以调用下载API
|
||||||
|
// 示例:下载PDF文件
|
||||||
|
if (item.file_path) {
|
||||||
|
uni.downloadFile({
|
||||||
|
url: item.file_path,
|
||||||
|
success: (res) => {
|
||||||
|
if (res.statusCode === 200) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "下载成功",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error("下载失败:", err);
|
||||||
|
uni.showToast({
|
||||||
|
title: "下载失败1",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const downLoad = (item) => {
|
||||||
|
if(!item.path){
|
||||||
|
uni.showToast({
|
||||||
|
title: "暂无下载链接",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addDownloadTask({
|
||||||
|
url: docUrl + item.path,
|
||||||
|
title: item.title,
|
||||||
|
id: item.uuid,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 查看指南(支持常用文档直链:pdf/doc/docx/xls/xlsx/ppt/pptx/txt)
|
||||||
|
const viewGuideline = (cell) => {
|
||||||
|
console.log(downloadTasks.value);
|
||||||
|
downloadTasks.value.forEach(item => {
|
||||||
|
if(item.id == cell.id) {
|
||||||
|
console.log(2222222222);
|
||||||
|
console.log(item.localPath);
|
||||||
|
plus.runtime.openFile(item.localPath, function(e) {
|
||||||
|
console.log('打开成功');
|
||||||
|
}, function(e) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '打开失败:' + e.message,
|
||||||
|
icon: "none",
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
console.log('打开失败:' + e.message);
|
||||||
|
});
|
||||||
|
// uni.openDocument({
|
||||||
|
// filePath: item.localPath,
|
||||||
|
// fileType: 'pdf',
|
||||||
|
// success: () => console.log('打开成功'),
|
||||||
|
// fail: (err) => {
|
||||||
|
// uni.showModal({
|
||||||
|
// title: '提示',
|
||||||
|
// content: JSON.stringify(err),
|
||||||
|
// showCancel: false,
|
||||||
|
// confirmText: '确定',
|
||||||
|
// success: (res) => {
|
||||||
|
// if(res.confirm){
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// let url = "https://view.xdocin.com/view?src=" + encodeURIComponent(pdfUrl);
|
||||||
|
// uni.downloadFile({
|
||||||
|
// url: pdfUrl,
|
||||||
|
// success: (res) => {
|
||||||
|
// if (res.statusCode === 200) {
|
||||||
|
// uni.openDocument({
|
||||||
|
// filePath: res.tempFilePath, // 临时文件路径
|
||||||
|
// fileType: 'pdf',
|
||||||
|
// success: () => console.log('打开成功'),
|
||||||
|
// fail: (err) => console.error('打开失败', err)
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回上一页
|
||||||
|
const goBack = () => {
|
||||||
|
uni.navigateBack();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加下载任务
|
||||||
|
const addDownloadTask = (item) => {
|
||||||
|
// 使用store添加任务
|
||||||
|
const taskIndex = downloadStore.addTask({
|
||||||
|
...item,
|
||||||
|
type: 'zhinan',
|
||||||
|
});
|
||||||
|
// 同步任务列表
|
||||||
|
syncTasksFromStore();
|
||||||
|
// 开始下载
|
||||||
|
startDownload(taskIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 开始下载
|
||||||
|
const startDownload = (index) => {
|
||||||
|
const taskItem = downloadStore.getTask(index);
|
||||||
|
if (!taskItem) return;
|
||||||
|
if(taskItem.status == "loading"){
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
uni.showToast({
|
||||||
|
title: "正在下载中",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "loading"
|
||||||
|
});
|
||||||
|
|
||||||
|
const task = uni.downloadFile({
|
||||||
|
url: taskItem.url,
|
||||||
|
success: (res1) => {
|
||||||
|
console.log("res1:"+JSON.stringify(res1));
|
||||||
|
if (res1.statusCode === 200) {
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "completed",
|
||||||
|
filePath: res1.tempFilePath,
|
||||||
|
});
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: "下载成功",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
uni.saveFile({
|
||||||
|
tempFilePath: res1.tempFilePath,
|
||||||
|
success: function (res2) {
|
||||||
|
console.log("res2:"+JSON.stringify(res2));
|
||||||
|
uni.getSavedFileInfo({
|
||||||
|
filePath: res2.savedFilePath,
|
||||||
|
success: function (res) {
|
||||||
|
console.log("res:"+JSON.stringify(res));
|
||||||
|
console.log("size:"+res.size);
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "completed",
|
||||||
|
localPath: res2.savedFilePath,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "failed",
|
||||||
|
});
|
||||||
|
removeTask(index);
|
||||||
|
uni.showToast({
|
||||||
|
title: "下载失败2",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "failed",
|
||||||
|
});
|
||||||
|
removeTask(index);
|
||||||
|
uni.showToast({
|
||||||
|
title: "下载失败3: " + (err.errMsg || "未知错误"),
|
||||||
|
icon: "none",
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听下载进度
|
||||||
|
task.onProgressUpdate((update) => {
|
||||||
|
const currentTask = downloadStore.getTask(index);
|
||||||
|
if (currentTask && currentTask.status === "downloading") {
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
progress: update.progress
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 保存task对象到store(用于暂停/继续)
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
task: task,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const syncTasksFromStore = () => {
|
||||||
|
downloadTasks.value = downloadStore.getTasks();
|
||||||
|
};
|
||||||
|
const removeTask = (index) => {
|
||||||
|
downloadStore.removeTask(index);
|
||||||
|
syncTasksFromStore();
|
||||||
|
};
|
||||||
|
// 恢复正在下载的任务
|
||||||
|
const resumeDownloadingTasks = () => {
|
||||||
|
// 使用 nextTick 确保在页面渲染后再恢复下载任务
|
||||||
|
nextTick(() => {
|
||||||
|
downloadStore.resumeDownloadingTasks((index) => {
|
||||||
|
// 重新开始下载(uni.downloadFile不支持断点续传,所以从0开始)
|
||||||
|
console.log("恢复下载任务:", downloadStore.getTask(index)?.url);
|
||||||
|
startDownload(index);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 测试加载更多功能
|
||||||
|
const testLoadMore = () => {
|
||||||
|
console.log("=== 手动测试加载更多 ===");
|
||||||
|
console.log("当前状态:", {
|
||||||
|
loadMoreStatus: loadMoreStatus.value,
|
||||||
|
hasMoreData: hasMoreData.value,
|
||||||
|
isLoading: isLoading.value,
|
||||||
|
currentPage: currentPage.value,
|
||||||
|
listLength: guidelinesList.value.length,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (loadMoreStatus.value === "more" && !isLoading.value) {
|
||||||
|
loadMoreData();
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: `状态: ${loadMoreStatus.value}, 加载中: ${isLoading.value}`,
|
||||||
|
icon: "none",
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 格式化日期
|
||||||
|
const formatDate = (dateString) => {
|
||||||
|
if (!dateString) return "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
const date = new Date(dateString);
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
|
const day = String(date.getDate()).padStart(2, "0");
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
} catch (error) {
|
||||||
|
return dateString;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 颜色变量
|
||||||
|
$primary-color: #ff4757;
|
||||||
|
$text-primary: #333;
|
||||||
|
$text-secondary: #666;
|
||||||
|
$text-light: #999;
|
||||||
|
$border-color: #e0e0e0;
|
||||||
|
$bg-color: #f6f6f6;
|
||||||
|
$white: #ffffff;
|
||||||
|
.imgbox {
|
||||||
|
width: 32rpx;
|
||||||
|
margin-top: -10rpx;
|
||||||
|
}
|
||||||
|
.popup-panel {
|
||||||
|
position: fixed;
|
||||||
|
top:285rpx;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: #fff;
|
||||||
|
z-index: 100;
|
||||||
|
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 28rpx 30rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-divider {
|
||||||
|
height: 2rpx;
|
||||||
|
background: #eaeaea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-item.active .item-text {
|
||||||
|
color: #8b2316;
|
||||||
|
}
|
||||||
|
.current-sort {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
|
||||||
|
.sort-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sort-icon.up {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-left: 8rpx solid transparent;
|
||||||
|
border-right: 8rpx solid transparent;
|
||||||
|
border-bottom: 12rpx solid #999;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border-bottom-color: #ff0000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.zhinan-list-page {
|
||||||
|
background-color: $bg-color;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guidelines-scroll-view {
|
||||||
|
position: fixed;
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 99;
|
||||||
|
height: calc(100vh - var(--status-bar-height) - 44px);
|
||||||
|
background-color: $bg-color;
|
||||||
|
}
|
||||||
|
// 固定搜索容器
|
||||||
|
.search-container-fixed {
|
||||||
|
position: fixed;
|
||||||
|
top: calc(var(--status-bar-height) + 44px); // 导航栏高度
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 90;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 30rpx 30rpx;
|
||||||
|
background-color: $white;
|
||||||
|
gap: 20rpx;
|
||||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
// 筛选栏
|
||||||
|
.filter-bar {
|
||||||
|
background-color: $white;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 2px solid #eee;
|
||||||
|
|
||||||
|
.search-box {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
.search-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
width: 1px;
|
||||||
|
height: 16px;
|
||||||
|
background-color: #999;
|
||||||
|
margin: 0 60rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 3px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 指南列表
|
||||||
|
.guidelines-list {
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
|
||||||
|
.guideline-item {
|
||||||
|
background-color: $white;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 30rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
.item-content {
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 30rpx;
|
||||||
|
|
||||||
|
.item-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: $text-primary;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-bottom {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
|
||||||
|
.item-date {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: $text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-action {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.download-btn {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: rgba(255, 71, 87, 0.1);
|
||||||
|
// transition: all 0.3s ease;
|
||||||
|
|
||||||
|
// &:active {
|
||||||
|
// transform: scale(0.95);
|
||||||
|
// background-color: rgba(255, 71, 87, 0.2);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
.view-btn {
|
||||||
|
color: #8b2316;
|
||||||
|
font-size: 28rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
background-color: darken($primary-color, 10%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载更多状态
|
||||||
|
.load-more-status {
|
||||||
|
padding: 20rpx 0;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.loading,
|
||||||
|
.more,
|
||||||
|
.no-more {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
padding: 20rpx 0;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: $text-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无数据提示
|
||||||
|
.no-data {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 120rpx 0;
|
||||||
|
|
||||||
|
text {
|
||||||
|
margin-top: 30rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: $text-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<uni-nav-bar
|
<!-- <uni-nav-bar
|
||||||
left-icon="left"
|
left-icon="left"
|
||||||
title="购买积分"
|
title="购买积分"
|
||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
fixed
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
height="180rpx"
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
></uni-nav-bar>
|
></uni-nav-bar> -->
|
||||||
|
<navBar :title="'购买积分'" ></navBar>
|
||||||
<view class="buy-point-page">
|
<view class="buy-point-page">
|
||||||
|
|
||||||
|
|
||||||
@@ -46,20 +47,80 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<unidialog
|
||||||
|
:visible="freeVisible"
|
||||||
|
:content="freeContent"
|
||||||
|
@close="freeClose"
|
||||||
|
@confirm="freeConfirm"
|
||||||
|
></unidialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
|
import api from '@/api/api';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
import unidialog from '@/components/dialog/dialog.vue';
|
||||||
|
import navBar from '@/components/navBar/navBar.vue';
|
||||||
|
const freeVisible = ref(false);
|
||||||
|
const freeContent = ref('您确定是否购买?');
|
||||||
|
const product_id = ref('');
|
||||||
|
const type = ref('');
|
||||||
|
const freeClose = () => {
|
||||||
|
freeVisible.value = false;
|
||||||
|
};
|
||||||
|
const freeConfirm = () => {
|
||||||
|
freeVisible.value = false;
|
||||||
|
api.createBointsOrder({
|
||||||
|
point: selectedPackageData.value.points
|
||||||
|
}).then(res => {
|
||||||
|
if(res.code==200){
|
||||||
|
console.log('price:'+res.data.amount);
|
||||||
|
console.log('order_id:'+res.data.order_id);
|
||||||
|
console.log('trade_no:'+res.data.trade_no);
|
||||||
|
console.log('jifen:'+res.data.point);
|
||||||
|
uni.sendNativeEvent('payPonitPage', {
|
||||||
|
msg: {
|
||||||
|
"price":res.data.amount,
|
||||||
|
"order_id":res.data.order_id,
|
||||||
|
"trade_no":res.data.trade_no,
|
||||||
|
'jifen':res.data.point,
|
||||||
|
'product_id':product_id.value,
|
||||||
|
'type':type.value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
onLoad((options) => {
|
||||||
|
if(options.product_id){
|
||||||
|
product_id.value = options.product_id;
|
||||||
|
}
|
||||||
|
if(options.type){
|
||||||
|
type.value = options.type;
|
||||||
|
}
|
||||||
|
getPointUnitPrice();
|
||||||
|
});
|
||||||
|
const pointUnitPrice = ref(1);
|
||||||
// 积分套餐数据 - 根据图片显示5个选项
|
// 积分套餐数据 - 根据图片显示5个选项
|
||||||
const packages = ref([
|
const packages = ref([
|
||||||
{ id: 1, points: 500, price: '45.00' },
|
{ id: 1, points: 500, price: 500*pointUnitPrice.value/100 },
|
||||||
{ id: 2, points: 1000, price: '88.00' },
|
{ id: 2, points: 1000, price: 1000*pointUnitPrice.value/100 },
|
||||||
{ id: 3, points: 2500, price: '198.00' },
|
{ id: 3, points: 2500, price: 2500*pointUnitPrice.value/100 },
|
||||||
{ id: 4, points: 5000, price: '398.00' },
|
{ id: 4, points: 5000, price: 5000*pointUnitPrice.value/100 },
|
||||||
{ id: 5, points: 10000, price: '758.00' }
|
{ id: 5, points: 10000, price: 10000*pointUnitPrice.value/100 }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const getPointUnitPrice = () => {
|
||||||
|
api.getPointUnitPrice().then(res => {
|
||||||
|
if(res.code==200){
|
||||||
|
pointUnitPrice.value=Number(res.data);
|
||||||
|
console.log(pointUnitPrice.value);
|
||||||
|
packages.value.forEach(pkg => {
|
||||||
|
pkg.price = pkg.points * pointUnitPrice.value / 100;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
// 选择状态
|
// 选择状态
|
||||||
const selectedPackage = ref(0); // 默认未选择
|
const selectedPackage = ref(0); // 默认未选择
|
||||||
|
|
||||||
@@ -96,18 +157,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const packageData = selectedPackageData.value;
|
const packageData = selectedPackageData.value;
|
||||||
uni.showModal({
|
freeVisible.value=true;
|
||||||
title: '确认购买',
|
|
||||||
content: `确认购买${packageData.points}积分,支付金额¥${packageData.price}?`,
|
|
||||||
success: (res) => {
|
|
||||||
if (res.confirm) {
|
|
||||||
uni.showToast({
|
|
||||||
title: '购买成功',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -138,7 +188,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.buy-point-page {
|
.buy-point-page {
|
||||||
height: calc(100vh - 140rpx);
|
height: 100vh;
|
||||||
background-color: $bg-color;
|
background-color: $bg-color;
|
||||||
overflow: hidden; // 隐藏滚动条
|
overflow: hidden; // 隐藏滚动条
|
||||||
|
|
||||||
@@ -224,6 +274,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.main-content {
|
.main-content {
|
||||||
|
margin-top: calc(var(--status-bar-height) + 44px);
|
||||||
padding: 40rpx 0rpx;
|
padding: 40rpx 0rpx;
|
||||||
|
|
||||||
.page-title {
|
.page-title {
|
||||||
|
|||||||
@@ -0,0 +1,323 @@
|
|||||||
|
<template>
|
||||||
|
<view class="address-page">
|
||||||
|
<navBar :title="'收货地址'" />
|
||||||
|
<!-- <uni-nav-bar left-icon="left" title="收货地址" fixed color="#8B2316" height="180rpx" :border="false" backgroundColor="#ffffff" @clickLeft="goBack" /> -->
|
||||||
|
|
||||||
|
<scroll-view scroll-y class="content">
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="label">收件人</view>
|
||||||
|
<input class="input" v-model="receiver" placeholder="请输入收货人名字" />
|
||||||
|
</view>
|
||||||
|
<view class="divider-line"></view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="label">手机号</view>
|
||||||
|
<input class="input" v-model="mobile" type="number" placeholder="收货人的电话,方便联系" />
|
||||||
|
</view>
|
||||||
|
<view class="divider-line"></view>
|
||||||
|
|
||||||
|
<!-- <view class="form-item">
|
||||||
|
<view class="label">邮箱</view>
|
||||||
|
<input class="input" v-model="email" type="text" placeholder="用于接收电子卡等信息(可选)" />
|
||||||
|
</view> -->
|
||||||
|
|
||||||
|
|
||||||
|
<view class="form-item select-item" @click="openAreaPicker">
|
||||||
|
<view class="label">地址</view>
|
||||||
|
<view class="input placeholder" v-if="!regionText">请选择地址</view>
|
||||||
|
<view class="input" v-else>{{ regionText }}</view>
|
||||||
|
<text class="arrow">›</text>
|
||||||
|
</view>
|
||||||
|
<view class="divider-line"></view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="label">详细地址</view>
|
||||||
|
<input class="input" v-model="detail" placeholder="请输入街道、门牌等详细地址信息" />
|
||||||
|
</view>
|
||||||
|
<view class="divider-line"></view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<view class="footer-bar" @click="submit">
|
||||||
|
<view class="confirm-btn" >确定兑换</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 省市区选择器 -->
|
||||||
|
<view v-if="showAreaPicker" class="picker-mask" @click="closeAreaPicker"></view>
|
||||||
|
<view v-if="showAreaPicker" class="picker-panel">
|
||||||
|
<view class="picker-header">
|
||||||
|
<text class="picker-btn" @click="closeAreaPicker">取消</text>
|
||||||
|
<text class="picker-title">选择地区</text>
|
||||||
|
<text class="picker-btn ok" @click="confirmArea">确定</text>
|
||||||
|
</view>
|
||||||
|
<picker-view v-if="provinces.length && cities.length && areas.length" class="picker-view" :indicator-style="indicatorStyle" :value="pickerIndex" @change="onAreaChange">
|
||||||
|
<picker-view-column>
|
||||||
|
<view v-for="(p,pi) in provinces" :key="pi" class="picker-item">{{ p.name }}</view>
|
||||||
|
</picker-view-column>
|
||||||
|
<picker-view-column>
|
||||||
|
<view v-for="(c,ci) in cities" :key="ci" class="picker-item">{{ c.name }}</view>
|
||||||
|
</picker-view-column>
|
||||||
|
<picker-view-column>
|
||||||
|
<view v-for="(a,ai) in areas" :key="ai" class="picker-item">{{ a.name }}</view>
|
||||||
|
</picker-view-column>
|
||||||
|
</picker-view>
|
||||||
|
<view v-else class="picker-empty">地区数据加载中...</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<unidialog
|
||||||
|
:title="'确认兑换信息'"
|
||||||
|
:visible="freeVisible"
|
||||||
|
:content="freeContent"
|
||||||
|
:titleColor="'#000'"
|
||||||
|
@close="freeClose"
|
||||||
|
@confirm="freeConfirm"
|
||||||
|
>
|
||||||
|
<template #content>
|
||||||
|
<view>
|
||||||
|
<view class="row">
|
||||||
|
<view class="left">收件人:</view>
|
||||||
|
<view class="right">{{ receiver }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="row">
|
||||||
|
<view class="left">手机号:</view>
|
||||||
|
<view class="right">{{ mobile }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="row">
|
||||||
|
<view class="left">地址:</view>
|
||||||
|
<view class="right">{{ regionText+detail }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="row">
|
||||||
|
<view class="left">兑换积分:</view>
|
||||||
|
<view class="right"><text class="price">0积分</text>(包邮)</view>
|
||||||
|
</view>
|
||||||
|
<view class="row">请确认此次兑换,物品不退不换</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</unidialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
|
import areaList from '@/utils/areaList.js'
|
||||||
|
import api from '@/api/api.js'
|
||||||
|
import unidialog from '@/components/dialog/dialog.vue';
|
||||||
|
const freeVisible = ref(false)
|
||||||
|
const freeContent = ref('')
|
||||||
|
const goods_order_id = ref('')
|
||||||
|
const goodsName = ref('');
|
||||||
|
import navTo from '@/utils/navTo';
|
||||||
|
const freeClose = () => {
|
||||||
|
freeVisible.value = false
|
||||||
|
}
|
||||||
|
const freeConfirm = () => {
|
||||||
|
freeVisible.value = false;
|
||||||
|
api.useWelfareNum({
|
||||||
|
other_uuid: goods_order_id.value,
|
||||||
|
type: 5
|
||||||
|
}).then(res => {
|
||||||
|
if(res.code == 1 || res.code == 200){
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: '兑换成功',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
navTo({
|
||||||
|
url: '/pages_goods/myRedemption/myRedemption?from=upan'
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
// uni.sendNativeEvent('goTabbarPage', {
|
||||||
|
// msg: 'mine'
|
||||||
|
// },ret => {
|
||||||
|
// console.log(ret);
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const receiver = ref('')
|
||||||
|
const mobile = ref('')
|
||||||
|
const regionText = ref('')
|
||||||
|
const detail = ref('')
|
||||||
|
const email = ref('')
|
||||||
|
const editingId = ref(null)
|
||||||
|
const goodsUuid = ref('')
|
||||||
|
const goodsNum = ref(0)
|
||||||
|
const goBack = () => uni.navigateBack()
|
||||||
|
|
||||||
|
// 省市区数据(适配树形数组:[{code,label,value,children:[...] }...])
|
||||||
|
const provinces = ref([])
|
||||||
|
const cities = ref([])
|
||||||
|
const areas = ref([])
|
||||||
|
const pickerIndex = ref([0,0,0])
|
||||||
|
const showAreaPicker = ref(false)
|
||||||
|
const indicatorStyle = `height: 80rpx;`
|
||||||
|
|
||||||
|
const normalizeNode = (node) => ({
|
||||||
|
code: node?.code || '',
|
||||||
|
name: node?.label || node?.value || node?.name || '',
|
||||||
|
children: Array.isArray(node?.children) ? node.children : []
|
||||||
|
})
|
||||||
|
|
||||||
|
const getAreaTree = () => {
|
||||||
|
const raw = areaList && (areaList.default || areaList)
|
||||||
|
return Array.isArray(raw) ? raw.map(normalizeNode) : []
|
||||||
|
}
|
||||||
|
|
||||||
|
const buildData = () => {
|
||||||
|
const tree = getAreaTree()
|
||||||
|
provinces.value = tree.length ? tree : [{ code: '', name: '', children: [] }]
|
||||||
|
const pIdx = Math.min(pickerIndex.value[0], Math.max(provinces.value.length - 1, 0))
|
||||||
|
const pNode = provinces.value[pIdx]
|
||||||
|
cities.value = (pNode?.children || []).map(normalizeNode)
|
||||||
|
if (!cities.value.length) cities.value = [{ code: '', name: '', children: [] }]
|
||||||
|
const cIdx = Math.min(pickerIndex.value[1], Math.max(cities.value.length - 1, 0))
|
||||||
|
const cNode = cities.value[cIdx]
|
||||||
|
areas.value = (cNode?.children || []).map(normalizeNode)
|
||||||
|
if (!areas.value.length) areas.value = [{ code: '', name: '' }]
|
||||||
|
}
|
||||||
|
|
||||||
|
const openAreaPicker = () => {
|
||||||
|
showAreaPicker.value = true
|
||||||
|
pickerIndex.value = [0,0,0]
|
||||||
|
buildData()
|
||||||
|
}
|
||||||
|
const closeAreaPicker = () => { showAreaPicker.value = false }
|
||||||
|
|
||||||
|
const onAreaChange = (e) => {
|
||||||
|
const val = (e && e.detail && e.detail.value) ? e.detail.value : [0,0,0]
|
||||||
|
const [pi, ci, ai] = val
|
||||||
|
if (pi !== pickerIndex.value[0]) {
|
||||||
|
pickerIndex.value = [pi, 0, 0]
|
||||||
|
buildData()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (ci !== pickerIndex.value[1]) {
|
||||||
|
pickerIndex.value = [pi, ci, 0]
|
||||||
|
buildData()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pickerIndex.value = [pi, ci, ai]
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmArea = () => {
|
||||||
|
const p = provinces.value[pickerIndex.value[0]]
|
||||||
|
const c = cities.value[pickerIndex.value[1]]
|
||||||
|
const a = areas.value[pickerIndex.value[2]]
|
||||||
|
regionText.value = [p?.name, c?.name, a?.name].filter(Boolean).join(' ')
|
||||||
|
closeAreaPicker()
|
||||||
|
}
|
||||||
|
|
||||||
|
onLoad((opts) => {
|
||||||
|
console.log(22);
|
||||||
|
console.log(opts);
|
||||||
|
goodsUuid.value = opts.goodsUuid
|
||||||
|
goodsNum.value = opts.goodsNum;
|
||||||
|
goodsName.value = opts.goodsName;
|
||||||
|
getAddress()
|
||||||
|
})
|
||||||
|
|
||||||
|
const saveAddress = () => {
|
||||||
|
uni.setStorageSync('goods_address', {
|
||||||
|
receiver: receiver.value,
|
||||||
|
mobile: mobile.value,
|
||||||
|
regionText: regionText.value,
|
||||||
|
detail: detail.value,
|
||||||
|
email: email.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const getAddress = () => {
|
||||||
|
const address = uni.getStorageSync('goods_address')
|
||||||
|
if(address){
|
||||||
|
receiver.value = address.receiver
|
||||||
|
mobile.value = address.mobile
|
||||||
|
regionText.value = address.regionText
|
||||||
|
detail.value = address.detail
|
||||||
|
email.value = address.email
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = () => {
|
||||||
|
|
||||||
|
if (!receiver.value) return uni.showToast({ title: '请输入收件人', icon: 'none' })
|
||||||
|
if (!/^1\d{10}$/.test(mobile.value)) return uni.showToast({ title: '请输入正确手机号', icon: 'none' })
|
||||||
|
if (!regionText.value) return uni.showToast({ title: '请选择地址', icon: 'none' })
|
||||||
|
if (!detail.value) return uni.showToast({ title: '请输入详细地址', icon: 'none' })
|
||||||
|
uni.sendNativeEvent("portraitReport",{
|
||||||
|
msg:{
|
||||||
|
event_nickname: "boint_jifengood",
|
||||||
|
page_type: "积分商城",
|
||||||
|
resource_name:goodsName.value,
|
||||||
|
event_val:0,
|
||||||
|
event_unit:'积分',
|
||||||
|
number:goodsNum.value,
|
||||||
|
belong:'U盘',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
(ret) => {
|
||||||
|
console.log(ret);
|
||||||
|
});
|
||||||
|
saveAddress();
|
||||||
|
api.createGoodsOrder({
|
||||||
|
goodsUuid: goodsUuid.value,
|
||||||
|
goodsNum: goodsNum.value,
|
||||||
|
user_name: receiver.value,
|
||||||
|
mobile: mobile.value,
|
||||||
|
email:'',
|
||||||
|
address: regionText.value+detail.value
|
||||||
|
}).then(res => {
|
||||||
|
if(res.code == 1 || res.code == 200){
|
||||||
|
freeVisible.value = true
|
||||||
|
goods_order_id.value = res.data.goods_order_id
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.address-page { min-height: 100vh; background: #fff; }
|
||||||
|
.content { position: absolute; top: calc(var(--status-bar-height) + 44px); bottom: 120rpx; left: 0; right: 0; background: #fff; }
|
||||||
|
.form-item { display: flex; align-items: center; padding: 24rpx; }
|
||||||
|
.label { width: 160rpx; color: #333; font-size: 30rpx; }
|
||||||
|
.input { flex: 1; color: #333; font-size: 30rpx; }
|
||||||
|
.placeholder { color: #808080;}
|
||||||
|
.divider-line { height: 2rpx; background: #eee; margin: 0 24rpx; }
|
||||||
|
.select-item { position: relative; }
|
||||||
|
.arrow { position: absolute; right: 24rpx; color: #999; font-size: 48rpx; }
|
||||||
|
.footer-bar { position: fixed; left: 0; right: 0; bottom: 0; height: 120rpx; background: #27c5b8; display: flex; align-items: center; justify-content: center; }
|
||||||
|
.confirm-btn { color: #fff; font-size: 34rpx; font-weight: 700; }
|
||||||
|
|
||||||
|
/* 地区选择器 */
|
||||||
|
.picker-mask { position: fixed; left: 0; right: 0; top: 0; bottom: 0; background: rgba(0,0,0,0.4); }
|
||||||
|
.picker-panel { position: fixed; left: 0; right: 0; bottom: 0; background: #fff; }
|
||||||
|
.picker-header { display: flex; align-items: center; justify-content: space-between; padding: 20rpx 24rpx; border-bottom: 1rpx solid #eee; }
|
||||||
|
.picker-title { font-size: 30rpx; color: #333; }
|
||||||
|
.picker-btn { color: #666; font-size: 28rpx; }
|
||||||
|
.picker-btn.ok { color: #38c1b1; }
|
||||||
|
.picker-view { height: 480rpx; }
|
||||||
|
.picker-item { height: 80rpx; line-height: 80rpx; text-align: center; color: #333; }
|
||||||
|
.picker-empty { padding: 40rpx; text-align: center; color: #999; }
|
||||||
|
.row{
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
font-size: 28rpx;
|
||||||
|
padding: 12rpx 0;
|
||||||
|
|
||||||
|
max-width: 800rpx;
|
||||||
|
|
||||||
|
.left{
|
||||||
|
text-align: left;
|
||||||
|
max-width: 142rpx;
|
||||||
|
white-space: nowrap;
|
||||||
|
width:auto!important;
|
||||||
|
}
|
||||||
|
.price{
|
||||||
|
color: #FF4D4F;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.left{
|
||||||
|
width: 160rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -0,0 +1,297 @@
|
|||||||
|
<template>
|
||||||
|
<navBar :title="'U盘在线兑换'" />
|
||||||
|
|
||||||
|
<view class="buy-upan-page">
|
||||||
|
<!-- 主要内容区域 -->
|
||||||
|
<view class="main-content">
|
||||||
|
<!-- 商品信息卡片 -->
|
||||||
|
<view class="product-card">
|
||||||
|
<!-- 商品描述 -->
|
||||||
|
<view class="product-title">{{ goodsInfo.name }}</view>
|
||||||
|
|
||||||
|
<!-- 兑换信息 -->
|
||||||
|
<view class="exchange-info">
|
||||||
|
<text class="info-left">免费兑换剩余{{ remainingCount }}个</text>
|
||||||
|
<text class="info-right">已兑换{{ exchangedCount }}件</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 兑换数量选择器 -->
|
||||||
|
<view class="quantity-section">
|
||||||
|
<text class="quantity-label">兑换数量</text>
|
||||||
|
<view class="quantity-selector">
|
||||||
|
<view
|
||||||
|
class="quantity-btn minus-btn"
|
||||||
|
:class="{ disabled: quantity <= 1 }"
|
||||||
|
@click="decreaseQuantity"
|
||||||
|
>
|
||||||
|
<text class="btn-text">—</text>
|
||||||
|
</view>
|
||||||
|
<view class="quantity-display">
|
||||||
|
<text class="quantity-value">{{ quantity }}</text>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="quantity-btn plus-btn"
|
||||||
|
:class="{ disabled: quantity >= remainingCount }"
|
||||||
|
@click="increaseQuantity"
|
||||||
|
>
|
||||||
|
<text class="btn-text">+</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部兑换按钮 -->
|
||||||
|
<view class="bottom-actions">
|
||||||
|
<view class="exchange-btn" @click="handleExchange">
|
||||||
|
<text class="btn-text">我要兑换</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
import { onShow } from '@dcloudio/uni-app';
|
||||||
|
import navBar from '@/components/navBar/navBar.vue';
|
||||||
|
import api from '@/api/api';
|
||||||
|
import goods_api from '@/api/goods_api';
|
||||||
|
import navTo from '@/utils/navTo';
|
||||||
|
const goodsUuid = ref('');
|
||||||
|
|
||||||
|
|
||||||
|
// 商品信息
|
||||||
|
const remainingCount = ref(0); // 剩余数量
|
||||||
|
const exchangedCount = ref(1129); // 已兑换数量
|
||||||
|
const quantity = ref(1); // 当前选择的数量
|
||||||
|
const goodsInfo = ref({});
|
||||||
|
|
||||||
|
// 增加数量
|
||||||
|
const increaseQuantity = () => {
|
||||||
|
if (quantity.value < remainingCount.value) {
|
||||||
|
quantity.value += 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const getUpanCount = async () => {
|
||||||
|
const res = await goods_api.getUpanWelfareCount()
|
||||||
|
if (res.code == 200) {
|
||||||
|
remainingCount.value=res.data;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// 减少数量
|
||||||
|
const decreaseQuantity = () => {
|
||||||
|
if (quantity.value > 1) {
|
||||||
|
quantity.value -= 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理兑换
|
||||||
|
const handleExchange = () => {
|
||||||
|
if (quantity.value <= 0) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请选择兑换数量',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (quantity.value > remainingCount.value) {
|
||||||
|
// uni.showToast({
|
||||||
|
// title: '兑换数量不能超过剩余数量',
|
||||||
|
// icon: 'none'
|
||||||
|
// });
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TODO: 调用兑换接口
|
||||||
|
navTo({
|
||||||
|
url:'/pages_app/buyUpan/address?goodsUuid='+goodsUuid.value+'&goodsNum='+quantity.value+'&goodsName='+goodsInfo.value.name
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取U盘福利剩余数量
|
||||||
|
const getUpanWelfareCount = () => {
|
||||||
|
api.getUGoods().then(res => {
|
||||||
|
console.log(res);
|
||||||
|
if (res.code == 1 || res.code == 200) {
|
||||||
|
// 根据实际接口返回的数据结构更新
|
||||||
|
console.log(33);
|
||||||
|
console.log(res.data);
|
||||||
|
goodsInfo.value = res.data;
|
||||||
|
if (res.data) {
|
||||||
|
//remainingCount.value = res.data.remainingCount;
|
||||||
|
exchangedCount.value = res.data.times;
|
||||||
|
goodsUuid.value = res.data.uuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('获取U盘福利数量失败:', err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onShow((options) => {
|
||||||
|
//remainingCount.value = options.restNum;
|
||||||
|
// 可选:获取实时剩余数量
|
||||||
|
//getUGoods();
|
||||||
|
getUpanWelfareCount();
|
||||||
|
getUpanCount();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
// 变量定义
|
||||||
|
$bg-color: #ffffff;
|
||||||
|
$text-primary: #333333;
|
||||||
|
$text-secondary: #666666;
|
||||||
|
$text-light: #999999;
|
||||||
|
$border-color: #e5e5e5;
|
||||||
|
$white: #ffffff;
|
||||||
|
$teal-color: #00cbc0;
|
||||||
|
$light-teal: #e6f7f6;
|
||||||
|
$page-bg: #f5f6f7;
|
||||||
|
|
||||||
|
// 混合器
|
||||||
|
@mixin flex-center {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin flex-between {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buy-upan-page {
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: $page-bg;
|
||||||
|
margin-top: calc(var(--status-bar-height) + 44px);
|
||||||
|
// 为底部按钮留出空间
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 商品信息卡片
|
||||||
|
.product-card {
|
||||||
|
background-color: $white;
|
||||||
|
|
||||||
|
padding: 40rpx 30rpx;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
|
||||||
|
.product-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: $text-primary;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.exchange-info {
|
||||||
|
@include flex-between;
|
||||||
|
font-size: 28rpx;
|
||||||
|
|
||||||
|
.info-left {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-right {
|
||||||
|
color: $text-secondary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数量选择器区域
|
||||||
|
.quantity-section {
|
||||||
|
background-color: $white;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 40rpx 30rpx;
|
||||||
|
|
||||||
|
.quantity-label {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: $text-primary;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quantity-selector {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 20rpx;
|
||||||
|
|
||||||
|
.quantity-btn {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
border: 2rpx solid $teal-color;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
@include flex-center;
|
||||||
|
background-color: $white;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
.btn-text {
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: $teal-color;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
border-color: $border-color;
|
||||||
|
cursor: not-allowed;
|
||||||
|
|
||||||
|
.btn-text {
|
||||||
|
color: $text-light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.disabled):active {
|
||||||
|
background-color: $light-teal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.quantity-display {
|
||||||
|
min-width: 120rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
background-color: $teal-color;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
@include flex-center;
|
||||||
|
margin: 0 10rpx;
|
||||||
|
|
||||||
|
.quantity-value {
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: $white;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 底部操作按钮
|
||||||
|
.bottom-actions {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
.exchange-btn {
|
||||||
|
background-color: $teal-color;
|
||||||
|
height: 88rpx;
|
||||||
|
@include flex-center;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-text {
|
||||||
|
color: $white;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,458 @@
|
|||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<!-- 头部导航 -->
|
||||||
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
|
left-icon="left"
|
||||||
|
title="病情记录"
|
||||||
|
@clickLeft="goBack"
|
||||||
|
|
||||||
|
color="#8B2316"
|
||||||
|
|
||||||
|
:border="false"
|
||||||
|
backgroundColor="#eee"
|
||||||
|
>
|
||||||
|
<template #right>
|
||||||
|
<view class="nav-right">
|
||||||
|
<uni-icons type="plus" size="24" color="#8B2316" @click="goAddRecord" style="margin-left: 30rpx;"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</uni-nav-bar>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 主要内容区域 -->
|
||||||
|
<scroll-view
|
||||||
|
class="main-content"
|
||||||
|
scroll-y
|
||||||
|
refresher-enabled
|
||||||
|
:refresher-triggered="refreshing"
|
||||||
|
@refresherrefresh="onRefresh"
|
||||||
|
@scrolltolower="onLoadMore"
|
||||||
|
:lower-threshold="100"
|
||||||
|
>
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<empty v-if="recordList.length === 0 && !loading" :emptyDesc="'您暂未添加病情记录'"></empty>
|
||||||
|
<!-- <view class="empty-state" v-if="recordList.length === 0 && !loading">
|
||||||
|
<text class="empty-text">暂无病情记录</text>
|
||||||
|
<button class="add-first-btn" @click="addRecord">添加第一条记录</button>
|
||||||
|
</view> -->
|
||||||
|
|
||||||
|
<!-- 时间线容器 -->
|
||||||
|
<view class="timeline-container" v-else>
|
||||||
|
<!-- 时间线 -->
|
||||||
|
<view class="timeline-line"></view>
|
||||||
|
|
||||||
|
<!-- 记录条目 -->
|
||||||
|
<view
|
||||||
|
class="record-item"
|
||||||
|
v-for="(record, index) in recordList"
|
||||||
|
:key="record.uuid"
|
||||||
|
@click="goToDetail(record)"
|
||||||
|
>
|
||||||
|
<!-- 时间线节点 -->
|
||||||
|
<view class="timeline-node">
|
||||||
|
<view class="node-circle"></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 记录内容 -->
|
||||||
|
<view class="record-content">
|
||||||
|
<!-- 日期气泡 -->
|
||||||
|
<view class="date-bubble">
|
||||||
|
<text class="date-text">{{ record.create_date }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 记录描述 -->
|
||||||
|
<view class="record-description" v-if="record.des">
|
||||||
|
<text class="description-text">{{ record.des }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 记录图片 -->
|
||||||
|
<view class="record-images" v-if="record.photo && record.photo.length > 0">
|
||||||
|
<view class="image-grid">
|
||||||
|
<view
|
||||||
|
class="image-item"
|
||||||
|
v-for="(imagePath, imgIndex) in record.photo"
|
||||||
|
:key="imgIndex"
|
||||||
|
@click.stop="previewImages(record.photo, imgIndex)"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
:src="docUrl + imagePath"
|
||||||
|
class="content-image"
|
||||||
|
mode="aspectFill"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 加载更多状态 -->
|
||||||
|
<view class="load-more" v-if="recordList.length > 0">
|
||||||
|
<view class="loading-text" v-if="loadingMore">
|
||||||
|
<uni-load-more status="loading" content-text="{ contentText: { contentdown: '上拉显示更多', contentrefresh: '正在加载...', contentnomore: '没有更多数据了' } }"></uni-load-more>
|
||||||
|
</view>
|
||||||
|
<!-- <view class="no-more-text" v-else-if="currentPage >= totalPage">
|
||||||
|
<text>没有更多数据了</text>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// Vue3 Composition API
|
||||||
|
import { ref, reactive, onMounted, computed } from 'vue'
|
||||||
|
import { onShow, onLoad } from '@dcloudio/uni-app'
|
||||||
|
import navBar from '@/components/navBar/navBar.vue'
|
||||||
|
import api from '@/api/api.js'
|
||||||
|
import docUrl from '@/utils/docUrl.js'
|
||||||
|
import empty from '@/components/empty/empty.vue'
|
||||||
|
|
||||||
|
const patientUuid = ref('')
|
||||||
|
const getRecordList = (isRefresh = false) => {
|
||||||
|
let usrInfo = uni.getStorageSync('userInfo')
|
||||||
|
|
||||||
|
// 如果是刷新,重置页码
|
||||||
|
if (isRefresh) {
|
||||||
|
currentPage.value = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置加载状态
|
||||||
|
if (isRefresh) {
|
||||||
|
refreshing.value = true
|
||||||
|
} else if (currentPage.value === 1) {
|
||||||
|
loading.value = true
|
||||||
|
} else {
|
||||||
|
loadingMore.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
api.conditionRecordList({
|
||||||
|
patient_uuid: patientUuid.value,
|
||||||
|
expert_uuid: usrInfo.uuid,
|
||||||
|
page: currentPage.value
|
||||||
|
}).then(res => {
|
||||||
|
console.log(res)
|
||||||
|
if(res.code == 200){
|
||||||
|
const newList = res.data.list || []
|
||||||
|
|
||||||
|
if (isRefresh || currentPage.value === 1) {
|
||||||
|
// 刷新或首次加载,替换数据
|
||||||
|
recordList.value = newList
|
||||||
|
} else {
|
||||||
|
// 加载更多,追加数据
|
||||||
|
recordList.value = [...recordList.value, ...newList]
|
||||||
|
}
|
||||||
|
|
||||||
|
totalPage.value = res.data.totalPage || 1
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('获取病情记录失败:', err)
|
||||||
|
uni.showToast({
|
||||||
|
title: '获取数据失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}).finally(() => {
|
||||||
|
// 重置加载状态
|
||||||
|
loading.value = false
|
||||||
|
refreshing.value = false
|
||||||
|
loadingMore.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const goToDetail = (record) => {
|
||||||
|
uni.setStorageSync('caseRecord', record)
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages_app/caseRecord/caseRecord?uuid=' + record.uuid + '&patientUuid=' + patientUuid.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const goAddRecord = () => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages_app/caseRecord/caseRecord?patientUuid=' + patientUuid.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onLoad((options) => {
|
||||||
|
patientUuid.value = options.uuid
|
||||||
|
})
|
||||||
|
onShow(() => {
|
||||||
|
getRecordList()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 响应式数据
|
||||||
|
const recordList = ref([])
|
||||||
|
const totalPage = ref(1)
|
||||||
|
const currentPage = ref(1)
|
||||||
|
const loading = ref(false)
|
||||||
|
const refreshing = ref(false)
|
||||||
|
const loadingMore = ref(false)
|
||||||
|
|
||||||
|
// 方法
|
||||||
|
const goBack = () => {
|
||||||
|
uni.navigateBack({
|
||||||
|
delta: 1,
|
||||||
|
fail() {
|
||||||
|
uni.redirectTo({
|
||||||
|
url: '/pages/index/index'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const addRecord = () => {
|
||||||
|
// 跳转到添加记录页面
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages_app/caseRecord/caseRecord?patientUuid=' + patientUuid.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const managePatients = () => {
|
||||||
|
// 管理患者功能
|
||||||
|
addRecord()
|
||||||
|
}
|
||||||
|
|
||||||
|
const previewImages = (imageList, currentIndex) => {
|
||||||
|
const urls = imageList.map(img => docUrl + img)
|
||||||
|
uni.previewImage({
|
||||||
|
current: currentIndex,
|
||||||
|
urls: urls
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下拉刷新
|
||||||
|
const onRefresh = () => {
|
||||||
|
console.log('下拉刷新')
|
||||||
|
getRecordList(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上拉加载更多
|
||||||
|
const onLoadMore = () => {
|
||||||
|
console.log('上拉加载更多')
|
||||||
|
|
||||||
|
// 如果正在加载或没有更多数据,则不执行
|
||||||
|
if (loadingMore.value || loading.value || refreshing.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果已经是最后一页,不执行
|
||||||
|
if (currentPage.value >= totalPage.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 页码加1
|
||||||
|
currentPage.value++
|
||||||
|
|
||||||
|
// 加载更多数据
|
||||||
|
getRecordList(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生命周期
|
||||||
|
onMounted(() => {
|
||||||
|
console.log('病情记录页面已加载')
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.container {
|
||||||
|
background-color: #ffffff;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 头部导航样式 */
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-btn {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon {
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: #8B2316;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #8B2316;
|
||||||
|
font-weight: bold;
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-btn {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-icon {
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: #8B2316;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 主要内容区域 */
|
||||||
|
.main-content {
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
bottom:0;
|
||||||
|
padding: 40rpx 30rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-line {
|
||||||
|
position: absolute;
|
||||||
|
left: 30rpx;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 4rpx;
|
||||||
|
background-color: #8B2316;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-item {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 60rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeline-node {
|
||||||
|
position: relative;
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.node-circle {
|
||||||
|
width: 20rpx;
|
||||||
|
height: 20rpx;
|
||||||
|
background-color: #8B2316;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 4rpx solid #ffffff;
|
||||||
|
box-shadow: 0 0 0 2rpx #8B2316;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-content {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-bubble {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border: 2rpx solid #8B2316;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-description {
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description-text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-images {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 15rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-item {
|
||||||
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 空状态样式 */
|
||||||
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 100rpx 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #999999;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-first-btn {
|
||||||
|
background-color: #8B2316;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 25rpx;
|
||||||
|
padding: 20rpx 40rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 加载更多样式 */
|
||||||
|
.load-more {
|
||||||
|
padding: 40rpx 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-text {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-more-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式调整 */
|
||||||
|
@media (max-width: 750rpx) {
|
||||||
|
.content-image {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 400rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,466 @@
|
|||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<!-- 头部导航 -->
|
||||||
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
|
left-icon="left"
|
||||||
|
title="病情记录"
|
||||||
|
@clickLeft="goBack"
|
||||||
|
color="#8B2316"
|
||||||
|
:border="false"
|
||||||
|
backgroundColor="#eee"
|
||||||
|
>
|
||||||
|
<template #right>
|
||||||
|
<view class="nav-right">
|
||||||
|
<text class="modify-btn" @click="saveRecord" v-if="recordUuid"
|
||||||
|
>修改</text
|
||||||
|
>
|
||||||
|
<text class="save-btn" @click="saveRecord" v-else>提交</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</uni-nav-bar>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 主要内容区域 -->
|
||||||
|
<view class="main-content">
|
||||||
|
<!-- 日期选择区域 -->
|
||||||
|
<view class="form-item row">
|
||||||
|
<view class="form-label">日期</view>
|
||||||
|
<view class="form-value" @click="openDateTime">
|
||||||
|
<text class="date-text">{{ dateTime }}</text>
|
||||||
|
<uni-icons type="right" size="16" color="#999"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="divider"></view>
|
||||||
|
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="form-label">描述</view>
|
||||||
|
<view class="form-value">
|
||||||
|
<textarea
|
||||||
|
class="description-input"
|
||||||
|
v-model="des"
|
||||||
|
placeholder="请输入患者病情"
|
||||||
|
:adjust-position="false"
|
||||||
|
></textarea>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="divider"></view>
|
||||||
|
|
||||||
|
<!-- 图片上传区域 -->
|
||||||
|
<view class="form-item">
|
||||||
|
<view class="form-label">图片</view>
|
||||||
|
<view class="image-upload-area">
|
||||||
|
<!-- 已上传的图片 -->
|
||||||
|
<view
|
||||||
|
class="image-item"
|
||||||
|
v-for="(image, index) in tempImageList"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
:src="image"
|
||||||
|
class="uploaded-image"
|
||||||
|
mode="aspectFill"
|
||||||
|
@click="previewImage(index)"
|
||||||
|
/>
|
||||||
|
<view class="delete-btn" @click="deleteImage(index)">
|
||||||
|
<uni-icons type="closeempty" size="15" color="#fff"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 添加图片按钮 -->
|
||||||
|
<view
|
||||||
|
class="add-image-btn"
|
||||||
|
v-if="imageList.length < 9"
|
||||||
|
@click="chooseImage"
|
||||||
|
>
|
||||||
|
<uni-icons type="plus" size="24" color="#999"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部删除按钮 -->
|
||||||
|
<view class="bottom-actions" v-if="recordUuid">
|
||||||
|
<button class="delete-btn" @click="deleteRecord">删除该条记录</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<up-datetime-picker
|
||||||
|
:show="showDate"
|
||||||
|
v-model="selectedDate"
|
||||||
|
@cancel="showDate = false"
|
||||||
|
@confirm="confirmDate"
|
||||||
|
mode="date"
|
||||||
|
></up-datetime-picker>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// Vue3 Composition API
|
||||||
|
import { ref, reactive, onMounted, computed } from "vue";
|
||||||
|
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||||
|
import api from "@/api/api.js";
|
||||||
|
import docUrl from "@/utils/docUrl.js";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { pathToBase64} from "image-tools";
|
||||||
|
|
||||||
|
// 响应式数据
|
||||||
|
const des = ref("");
|
||||||
|
const showDate = ref(false);
|
||||||
|
const recordUuid = ref("");
|
||||||
|
const patientUuid = ref("");
|
||||||
|
const dateTime = ref(dayjs().format("YYYY年MM月DD日"));
|
||||||
|
const selectedDate = ref(dayjs());
|
||||||
|
const description = ref("");
|
||||||
|
const imageList = ref([]);
|
||||||
|
const tempImageList = ref([]);
|
||||||
|
const originalData = ref({});
|
||||||
|
|
||||||
|
// 方法
|
||||||
|
const goBack = () => {
|
||||||
|
uni.navigateBack({
|
||||||
|
delta: 1,
|
||||||
|
fail() {
|
||||||
|
uni.redirectTo({
|
||||||
|
url: "/pages/index/index",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const confirmDate = ({ value, mode }) => {
|
||||||
|
console.log(value);
|
||||||
|
dateTime.value = dayjs(value).format("YYYY年MM月DD日");
|
||||||
|
selectedDate.value = dayjs(value).format("YYYY-MM-DD");
|
||||||
|
showDate.value = false;
|
||||||
|
};
|
||||||
|
const openDateTime = () => {
|
||||||
|
console.log("openDateTime");
|
||||||
|
showDate.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const chooseImage = () => {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: 8 - imageList.value.length,
|
||||||
|
sizeType: ["original", "compressed"],
|
||||||
|
sourceType: ["album", "camera"],
|
||||||
|
success: (res) => {
|
||||||
|
// 这里应该上传图片到服务器
|
||||||
|
// imageList.value = [...imageList.value, ...res.tempFilePaths]
|
||||||
|
tempImageList.value = [...tempImageList.value, ...res.tempFilePaths];
|
||||||
|
for (let i = 0; i < res.tempFilePaths.length; i++) {
|
||||||
|
pathToBase64(res.tempFilePaths[i])
|
||||||
|
.then((base64) => {
|
||||||
|
imageList.value.push(base64.split(',')[1]);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteImage = (index) => {
|
||||||
|
// 显示模态框
|
||||||
|
uni.showModal({
|
||||||
|
title: "确认删除",
|
||||||
|
content: "确定要删除这张图片吗?",
|
||||||
|
// 设置模态框点击确定按钮后的回调函数
|
||||||
|
success: (res) => {
|
||||||
|
// 如果用户点击了确认按钮
|
||||||
|
if (res.confirm) {
|
||||||
|
// 从imageList数组中删除指定索引的图片
|
||||||
|
imageList.value.splice(index, 1);
|
||||||
|
tempImageList.value.splice(index, 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const previewImage = (index) => {
|
||||||
|
uni.previewImage({
|
||||||
|
current: index,
|
||||||
|
urls: imageList.value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const addRecord = async () => {
|
||||||
|
if (!des.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "请输入患者病情",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let usrInfo = uni.getStorageSync("userInfo");
|
||||||
|
const res = await api.addConditionRecord({
|
||||||
|
patient_uuid: patientUuid.value,
|
||||||
|
expert_uuid: usrInfo.uuid,
|
||||||
|
des: des.value,
|
||||||
|
create_date: dayjs(selectedDate.value).format("YYYY-MM-DD"),
|
||||||
|
img1: imageList.value[0] || "",
|
||||||
|
img2: imageList.value[1] || "",
|
||||||
|
img3: imageList.value[2] || "",
|
||||||
|
img4: imageList.value[3] || "",
|
||||||
|
img5: imageList.value[4] || "",
|
||||||
|
img6: imageList.value[5] || "",
|
||||||
|
img7: imageList.value[6] || "",
|
||||||
|
img8: imageList.value[7] || "",
|
||||||
|
});
|
||||||
|
if (res.code == 200) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "添加成功",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
goBack();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const updateRecord = async () => {
|
||||||
|
if (!des.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "请输入患者病情",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let usrInfo = uni.getStorageSync("userInfo");
|
||||||
|
const res = await api.updateConditionRecord({
|
||||||
|
uuid: recordUuid.value,
|
||||||
|
patient_uuid: patientUuid.value,
|
||||||
|
expert_uuid: usrInfo.uuid,
|
||||||
|
des: des.value,
|
||||||
|
create_date: dayjs(selectedDate.value).format("YYYY-MM-DD"),
|
||||||
|
img1: imageList.value[0] || "",
|
||||||
|
img2: imageList.value[1] || "",
|
||||||
|
img3: imageList.value[2] || "",
|
||||||
|
img4: imageList.value[3] || "",
|
||||||
|
img5: imageList.value[4] || "",
|
||||||
|
img6: imageList.value[5] || "",
|
||||||
|
img7: imageList.value[6] || "",
|
||||||
|
img8: imageList.value[7] || "",
|
||||||
|
});
|
||||||
|
if (res.code == 200) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "修改成功",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
uni.setStorageSync("caseRecord", null);
|
||||||
|
goBack();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const deleteConditionRecord = async () => {
|
||||||
|
const res = await api.deleteConditionRecord({
|
||||||
|
uuid: recordUuid.value,
|
||||||
|
});
|
||||||
|
if (res.code == 200) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "删除成功",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
goBack();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteRecord = () => {
|
||||||
|
uni.showModal({
|
||||||
|
title: "确认删除",
|
||||||
|
content: "确定要删除这条记录吗?",
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
deleteConditionRecord();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 生命周期
|
||||||
|
onLoad((options) => {
|
||||||
|
console.log(options);
|
||||||
|
recordUuid.value = options.uuid || "";
|
||||||
|
patientUuid.value = options.patientUuid || "";
|
||||||
|
if (recordUuid.value) {
|
||||||
|
imageList.value = [];
|
||||||
|
let record = uni.getStorageSync("caseRecord");
|
||||||
|
des.value = record.des;
|
||||||
|
tempImageList.value = record.photo.map((item) => docUrl + item);
|
||||||
|
// imageList.value = record.photo.map(item=>docUrl+item);
|
||||||
|
dateTime.value = dayjs(record.create_date).format("YYYY年MM月DD日");
|
||||||
|
selectedDate.value = dayjs(record.create_date);
|
||||||
|
for (let i = 0; i < record.photo.length; i++) {
|
||||||
|
console.log("url", docUrl + record.photo[i]);
|
||||||
|
uni.request({
|
||||||
|
url: docUrl + record.photo[i],
|
||||||
|
method: "GET",
|
||||||
|
responseType: "arraybuffer",
|
||||||
|
success: (res) => {
|
||||||
|
const base64 = `${uni.arrayBufferToBase64(res.data)}`;
|
||||||
|
console.log(base64);
|
||||||
|
imageList.value.push(base64);
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
reject(err);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const saveRecord = () => {
|
||||||
|
if (recordUuid.value) {
|
||||||
|
updateRecord();
|
||||||
|
} else {
|
||||||
|
addRecord();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
background-color: #ffffff;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 头部导航样式 */
|
||||||
|
.nav-right {
|
||||||
|
padding-right: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modify-btn,
|
||||||
|
.save-btn {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #8b2316;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 主要内容区域 */
|
||||||
|
.main-content {
|
||||||
|
position: fixed;
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
bottom:150rpx;
|
||||||
|
z-index:1;
|
||||||
|
overflow-y: scroll;
|
||||||
|
padding:0 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
padding: 30rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-value {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description-input {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 200rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 1.6;
|
||||||
|
background-color: 2rpx solid #f5f5f5;
|
||||||
|
border: none;
|
||||||
|
padding: 20rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description-input:disabled {
|
||||||
|
color: #999999;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 图片上传区域 */
|
||||||
|
.image-upload-area {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-item {
|
||||||
|
position: relative;
|
||||||
|
width: 160rpx;
|
||||||
|
height: 160rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploaded-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-item .delete-btn {
|
||||||
|
position: absolute;
|
||||||
|
top: 10rpx;
|
||||||
|
right: 10rpx;
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-image-btn {
|
||||||
|
width: 160rpx;
|
||||||
|
height: 160rpx;
|
||||||
|
border: 2rpx dashed #cccccc;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
height: 1rpx;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
margin: 0 -30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部操作区域 */
|
||||||
|
.bottom-actions {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
padding: 30rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-top: 1rpx solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-actions .delete-btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 88rpx;
|
||||||
|
background-color: #8b2316;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
fixed
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
height="180rpx"
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
></uni-nav-bar>
|
></uni-nav-bar>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
fixed
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
height="180rpx"
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
></uni-nav-bar>
|
></uni-nav-bar>
|
||||||
|
|||||||
@@ -0,0 +1,354 @@
|
|||||||
|
<template>
|
||||||
|
<view class="container">
|
||||||
|
<!-- 头部导航 -->
|
||||||
|
<navBar :title="headerTitle" />
|
||||||
|
|
||||||
|
<!-- 主要内容区域 -->
|
||||||
|
<view class="main-content">
|
||||||
|
<!-- 疾病诊断部分 -->
|
||||||
|
<view class="header">
|
||||||
|
<view class="section">
|
||||||
|
<view class="section-content">
|
||||||
|
<text class="diagnosis-text">疾病诊断: {{ pageData.diseaseName }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 化验报告部分 -->
|
||||||
|
<view class="section">
|
||||||
|
<view class="section-header">
|
||||||
|
<text class="section-title">化验报告</text>
|
||||||
|
</view>
|
||||||
|
<view class="section-content">
|
||||||
|
<text class="no-report-text" v-if="!pageData.hasLabReport">无检查化验报告</text>
|
||||||
|
<view v-else class="lab-report-container">
|
||||||
|
<view class="image-grid">
|
||||||
|
<view
|
||||||
|
class="image-item"
|
||||||
|
v-for="(image, index) in caseImages"
|
||||||
|
:key="image.uuid"
|
||||||
|
@click="previewImage(index)"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
:src="docUrl+image.path"
|
||||||
|
class="report-image"
|
||||||
|
mode="aspectFill"
|
||||||
|
/>
|
||||||
|
<!-- <view class="image-date">{{ formatDate(image.createDate) }}</view> -->
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 疾病描述部分 -->
|
||||||
|
<view class="section">
|
||||||
|
<view class="section-header">
|
||||||
|
<text class="section-title">疾病描述</text>
|
||||||
|
</view>
|
||||||
|
<view class="section-content">
|
||||||
|
<text class="description-text">{{ pageData.des || '暂无描述' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部线条 -->
|
||||||
|
<view class="bottom-line"></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
// Vue3 Composition API
|
||||||
|
import { ref, reactive, onMounted, computed } from 'vue'
|
||||||
|
import { onShow,onLoad } from '@dcloudio/uni-app'
|
||||||
|
import navBar from '@/components/navBar/navBar.vue'
|
||||||
|
import api from '@/api/api.js'
|
||||||
|
import docUrl from '@/utils/docUrl.js'
|
||||||
|
const uuid = ref('')
|
||||||
|
onLoad((options) => {
|
||||||
|
uuid.value = options.uuid
|
||||||
|
})
|
||||||
|
onShow(() => {
|
||||||
|
getDetail()
|
||||||
|
})
|
||||||
|
// 响应式数据
|
||||||
|
const pageData = ref({
|
||||||
|
date: '',
|
||||||
|
diseaseName: '',
|
||||||
|
diagnosis: '',
|
||||||
|
hasLabReport: false,
|
||||||
|
labReport: '',
|
||||||
|
description: '',
|
||||||
|
photo: '',
|
||||||
|
age: 0,
|
||||||
|
title: '',
|
||||||
|
patientUuid: '',
|
||||||
|
diseaseUuid: '',
|
||||||
|
state: 0,
|
||||||
|
createDate: '',
|
||||||
|
modifyDate: null
|
||||||
|
})
|
||||||
|
|
||||||
|
// 案例图片数据
|
||||||
|
const caseImages = ref([])
|
||||||
|
|
||||||
|
const getDetail = () => {
|
||||||
|
api.caseDetail({
|
||||||
|
caseUuid: uuid.value
|
||||||
|
}).then(res => {
|
||||||
|
console.log(res)
|
||||||
|
if(res.code == 200){
|
||||||
|
// 更新案例数据
|
||||||
|
pageData.value = res.data.case
|
||||||
|
// 更新案例图片
|
||||||
|
caseImages.value = res.data.caseImg || []
|
||||||
|
// 设置是否有化验报告(根据图片数量判断)
|
||||||
|
pageData.value.hasLabReport = caseImages.value.length > 0
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('获取案例详情失败:', err)
|
||||||
|
uni.showToast({
|
||||||
|
title: '获取数据失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算属性
|
||||||
|
const headerTitle = computed(() => {
|
||||||
|
return pageData.value.title || `${pageData.value.createDate}${pageData.value.diseaseName}`
|
||||||
|
})
|
||||||
|
|
||||||
|
// 格式化日期
|
||||||
|
const formatDate = (dateStr) => {
|
||||||
|
if (!dateStr) return ''
|
||||||
|
const date = new Date(dateStr)
|
||||||
|
return date.toLocaleDateString('zh-CN', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit'
|
||||||
|
}).replace(/\//g, '-')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方法
|
||||||
|
const goBack = () => {
|
||||||
|
uni.navigateBack()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预览图片
|
||||||
|
const previewImage = (index) => {
|
||||||
|
const urls = caseImages.value.map(img => docUrl+img.path)
|
||||||
|
uni.previewImage({
|
||||||
|
current: index,
|
||||||
|
urls: urls
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生命周期
|
||||||
|
onMounted(() => {
|
||||||
|
// 页面加载时的逻辑
|
||||||
|
console.log('检查记录页面已加载')
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.container {
|
||||||
|
background-color: #ffffff;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 状态栏样式 */
|
||||||
|
.status-bar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10rpx 30rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-left {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-center {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.network-icons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bluetooth-icon, .wifi-icon {
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.speed {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.signal {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-right {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 头部导航样式 */
|
||||||
|
|
||||||
|
|
||||||
|
.back-btn {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon {
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: #ff4444;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #ff4444;
|
||||||
|
font-weight: bold;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 主要内容区域 */
|
||||||
|
.main-content {
|
||||||
|
position: fixed;
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
left: 0;
|
||||||
|
right:0;
|
||||||
|
bottom: 0rpx;
|
||||||
|
overflow-y: scroll;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.section {
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.red-bar {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 8rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
background-color: #ff4444;
|
||||||
|
border-radius: 4rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333333;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-content {
|
||||||
|
padding-left: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.diagnosis-text {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.header{
|
||||||
|
background: #8B2316;
|
||||||
|
color: #fff;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
.section{
|
||||||
|
padding:20rpx;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
}
|
||||||
|
.section-content{
|
||||||
|
padding-left:0rpx;
|
||||||
|
}
|
||||||
|
.diagnosis-text{
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.no-report-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lab-report-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lab-report-container {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-item {
|
||||||
|
position: relative;
|
||||||
|
width: 200rpx;
|
||||||
|
height: 200rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.report-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-date {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
|
||||||
|
color: white;
|
||||||
|
font-size: 20rpx;
|
||||||
|
padding: 20rpx 10rpx 10rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部线条 */
|
||||||
|
.bottom-line {
|
||||||
|
height: 2rpx;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
margin: 40rpx 30rpx 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
+146
-54
@@ -4,6 +4,7 @@
|
|||||||
<navBar title="公益咨询" />
|
<navBar title="公益咨询" />
|
||||||
<view class="tabs">
|
<view class="tabs">
|
||||||
<view :class="['tab', activeTab==='new' ? 'active' : '']" @tap="switchTab('new')">新的咨询</view>
|
<view :class="['tab', activeTab==='new' ? 'active' : '']" @tap="switchTab('new')">新的咨询</view>
|
||||||
|
<view class="bar"></view>
|
||||||
<view :class="['tab', activeTab==='mine' ? 'active' : '']" @tap="switchTab('mine')">我已回答</view>
|
<view :class="['tab', activeTab==='mine' ? 'active' : '']" @tap="switchTab('mine')">我已回答</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="tabs-spacer"></view>
|
<view class="tabs-spacer"></view>
|
||||||
@@ -18,16 +19,20 @@
|
|||||||
@scrolltolower="onReachBottom"
|
@scrolltolower="onReachBottom"
|
||||||
lower-threshold="80"
|
lower-threshold="80"
|
||||||
>
|
>
|
||||||
<view v-for="(item, idx) in displayList" :key="idx" class="consult-card" @click="goDetail(item.id)">
|
<view v-for="(item, idx) in displayList" :key="idx" class="consult-card" @click="goDetail(item.id,item.patientUuid)">
|
||||||
<view class="card-head">
|
<view class="card-head">
|
||||||
<text class="user-name">{{ item.maskName }}</text>
|
<view class="namebox">
|
||||||
|
<text class="user-name">{{ item.maskName }}</text>
|
||||||
|
<text class="user-avatar" v-if="bottomActive!=='quick'">({{item.sex==1?'女':'男' }}<text decode> </text>{{ calcAge(item.birthDate) }}岁)</text>
|
||||||
|
</view>
|
||||||
<text class="date">{{ item.date }}</text>
|
<text class="date">{{ item.date }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="card-body">
|
<view class="card-body">
|
||||||
<text class="content">{{ item.content }}</text>
|
<text class="content twoline">{{ item.disease_describe }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="card-foot" v-if="bottomActive==='multi'">
|
<view class="card-foot" v-if="bottomActive==='multi'">
|
||||||
<text class="reply-count">{{ item.answer_num }}位医生已回答</text>
|
<text class="reply-count" v-if="item.answer_num>0">{{ item.answer_num }}位医生已回答</text>
|
||||||
|
<text class="reply-count-none" v-else>暂未有医生回答</text>
|
||||||
<view v-if="item.tag" class="tag">{{ item.tag }}</view>
|
<view v-if="item.tag" class="tag">{{ item.tag }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="card-foot" v-else>
|
<view class="card-foot" v-else>
|
||||||
@@ -52,7 +57,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed } from 'vue'
|
import { ref, computed } from 'vue'
|
||||||
import { onShow } from '@dcloudio/uni-app'
|
import { onShow,onBackPress,onLoad } from '@dcloudio/uni-app'
|
||||||
import navBar from '@/components/navBar/navBar.vue'
|
import navBar from '@/components/navBar/navBar.vue'
|
||||||
import empty from '@/components/empty/empty.vue'
|
import empty from '@/components/empty/empty.vue'
|
||||||
import api from '@/api/api.js'
|
import api from '@/api/api.js'
|
||||||
@@ -65,14 +70,30 @@ const pageSize=ref(10)
|
|||||||
const hasMore = ref(true)
|
const hasMore = ref(true)
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const isRefreshing = ref(false)
|
const isRefreshing = ref(false)
|
||||||
const goDetail=async(uuid)=>{
|
onBackPress(()=>{
|
||||||
|
plus.runtime.quit();
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
const goDetail=async(uuid,patientUuid)=>{
|
||||||
if(bottomActive.value==='quick'){
|
if(bottomActive.value==='quick'){
|
||||||
let userId=uni.getStorageSync('userInfo').uuid.toLowerCase();
|
if(activeTab.value==='new'){
|
||||||
let conversationId=userId+'|1|'+uuid.toLowerCase();
|
navTo({
|
||||||
await uni.$UIKitStore.uiStore.selectConversation(conversationId)
|
url:'/pages_app/freeDetail/freeDetail?uuid='+uuid
|
||||||
navTo({
|
})
|
||||||
url:'/pages_chat/chat/index?from=consult'
|
}else{
|
||||||
|
let userId=uni.getStorageSync('userInfo').uuid.toLowerCase();
|
||||||
|
uni.sendNativeEvent('goConsultPage', {
|
||||||
|
msg: 'chat'
|
||||||
|
},ret => {
|
||||||
|
console.log(ret);
|
||||||
})
|
})
|
||||||
|
//let conversationId=userId+'|1|'+patientUuid.toLowerCase();
|
||||||
|
//await uni.$UIKitStore.uiStore.selectConversation(conversationId)
|
||||||
|
// navTo({
|
||||||
|
// url:'/pages_chat/chat/index?from=consult&&patientUuid='+patientUuid+'&&uuid='+uuid
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
let status=0;
|
let status=0;
|
||||||
if(activeTab.value==='new'){
|
if(activeTab.value==='new'){
|
||||||
@@ -90,6 +111,22 @@ function maskName(name){
|
|||||||
const first = name.slice(0,1)
|
const first = name.slice(0,1)
|
||||||
return `${first}**`
|
return `${first}**`
|
||||||
}
|
}
|
||||||
|
// 根据出生日期计算年龄(birth 可以是 'YYYY-MM-DD' 或可被 Date 解析的字符串 / 时间戳)
|
||||||
|
function calcAge(birth) {
|
||||||
|
if (!birth) return ''
|
||||||
|
const birthDate = new Date(birth)
|
||||||
|
if (isNaN(birthDate.getTime())) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
const today = new Date()
|
||||||
|
let age = today.getFullYear() - birthDate.getFullYear()
|
||||||
|
const m = today.getMonth() - birthDate.getMonth()
|
||||||
|
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
|
||||||
|
age--
|
||||||
|
}
|
||||||
|
// 年龄小于 0 视为无效
|
||||||
|
return age >= 0 ? age : ''
|
||||||
|
}
|
||||||
const newConsultList=async(isRefresh=false)=>{
|
const newConsultList=async(isRefresh=false)=>{
|
||||||
if(isLoading.value) return
|
if(isLoading.value) return
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
@@ -106,12 +143,15 @@ const newConsultList=async(isRefresh=false)=>{
|
|||||||
if(res && res.code===200 && res.data && res.data.consult_list){
|
if(res && res.code===200 && res.data && res.data.consult_list){
|
||||||
const list = Array.isArray(res.data.consult_list.list) ? res.data.consult_list.list : []
|
const list = Array.isArray(res.data.consult_list.list) ? res.data.consult_list.list : []
|
||||||
const mapped = list.map(item=>({
|
const mapped = list.map(item=>({
|
||||||
maskName: maskName(item.realName || ''),
|
maskName: item.realName,
|
||||||
date: (item.createDate || '').slice(0,10),
|
date: (item.createDate || '').slice(0,16),
|
||||||
content: item.content || '',
|
content: item.content || '',
|
||||||
replyCount: 0,
|
replyCount: 0,
|
||||||
|
sex: item.sex || 0,
|
||||||
|
birthDate: item.birthDate || item.birthday,
|
||||||
tag: item.diseaseName || '',
|
tag: item.diseaseName || '',
|
||||||
id:item.patientUuid || ''
|
id:item.uuid || '',
|
||||||
|
patientUuid:item.patientUuid || ''
|
||||||
}))
|
}))
|
||||||
if(isRefresh){
|
if(isRefresh){
|
||||||
listNew.value = mapped
|
listNew.value = mapped
|
||||||
@@ -142,12 +182,15 @@ const consultListHis=async(isRefresh=false)=>{
|
|||||||
if(res.code==200){
|
if(res.code==200){
|
||||||
const list = Array.isArray(res.data.list) ? res.data.list : []
|
const list = Array.isArray(res.data.list) ? res.data.list : []
|
||||||
const mapped = list.map(item=>({
|
const mapped = list.map(item=>({
|
||||||
maskName: maskName(item.realName || ''),
|
maskName: item.realName,
|
||||||
date: (item.createDate || '').slice(0,10),
|
date: (item.createDate || '').slice(0,16),
|
||||||
content: item.content || '',
|
content: item.content || '',
|
||||||
replyCount: 0,
|
replyCount: 0,
|
||||||
|
sex: item.sex || 0,
|
||||||
|
birthDate: item.birthDate || item.birthday,
|
||||||
tag: item.diseaseName || '',
|
tag: item.diseaseName || '',
|
||||||
id:item.patientUuid || ''
|
id:item.uuid || '',
|
||||||
|
patientUuid:item.patientUuid || ''
|
||||||
}))
|
}))
|
||||||
if(isRefresh){
|
if(isRefresh){
|
||||||
listMine.value = mapped
|
listMine.value = mapped
|
||||||
@@ -182,7 +225,9 @@ const listNewInterrogation=async(isRefresh=false)=>{
|
|||||||
maskName: maskName(item.name || ''),
|
maskName: maskName(item.name || ''),
|
||||||
date: (item.create_date || '').slice(0,10),
|
date: (item.create_date || '').slice(0,10),
|
||||||
content: item.your_question || '',
|
content: item.your_question || '',
|
||||||
disease_describe:item.your_question || '',
|
disease_describe:item.disease_describe || '',
|
||||||
|
sex: item.sex || 0,
|
||||||
|
birthDate: item.birthday || '',
|
||||||
answer_num: item.answer_num || 0,
|
answer_num: item.answer_num || 0,
|
||||||
tag: item.disease_name || '',
|
tag: item.disease_name || '',
|
||||||
id:item.step1_uuid || ''
|
id:item.step1_uuid || ''
|
||||||
@@ -220,6 +265,8 @@ const listMyAnsweredInterrogation=async(isRefresh=false)=>{
|
|||||||
date: (item.create_date || '').slice(0,10),
|
date: (item.create_date || '').slice(0,10),
|
||||||
content: item.your_question || '',
|
content: item.your_question || '',
|
||||||
disease_describe:item.disease_describe || '',
|
disease_describe:item.disease_describe || '',
|
||||||
|
sex: item.sex || 0,
|
||||||
|
birthDate: item.birthday || '',
|
||||||
answer_num: item.answer_num || 0,
|
answer_num: item.answer_num || 0,
|
||||||
tag: item.disease_name || '',
|
tag: item.disease_name || '',
|
||||||
id:item.step1_uuid || ''
|
id:item.step1_uuid || ''
|
||||||
@@ -237,20 +284,22 @@ const listMyAnsweredInterrogation=async(isRefresh=false)=>{
|
|||||||
isRefreshing.value = false
|
isRefreshing.value = false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
onShow(()=>{
|
onLoad(()=>{
|
||||||
page.value = 1
|
page.value = 1
|
||||||
hasMore.value = true;
|
hasMore.value = true;
|
||||||
|
listNew.value = [];
|
||||||
|
listMine.value=[];
|
||||||
if(bottomActive.value==='quick'){
|
if(bottomActive.value==='quick'){
|
||||||
if(activeTab.value==='new'){
|
if(activeTab.value==='new'){
|
||||||
newConsultList(true)
|
newConsultList(false)
|
||||||
}else{
|
}else{
|
||||||
consultListHis(true)
|
consultListHis(false)
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if(activeTab.value==='new'){
|
if(activeTab.value==='new'){
|
||||||
listNewInterrogation(true)
|
listNewInterrogation(false)
|
||||||
}else{
|
}else{
|
||||||
listMyAnsweredInterrogation(true)
|
listMyAnsweredInterrogation(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -267,18 +316,20 @@ function switchTab(key) {
|
|||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
listNew.value = [];
|
listNew.value = [];
|
||||||
listMine.value=[];
|
listMine.value=[];
|
||||||
|
page.value = 1
|
||||||
|
hasMore.value = true;
|
||||||
if(bottomActive.value==='quick'){
|
if(bottomActive.value==='quick'){
|
||||||
if(activeTab.value==='new'){
|
if(activeTab.value==='new'){
|
||||||
newConsultList(true)
|
newConsultList(false)
|
||||||
}else{
|
}else{
|
||||||
consultListHis(true)
|
consultListHis(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
if(activeTab.value==='new'){
|
if(activeTab.value==='new'){
|
||||||
listNewInterrogation(true)
|
listNewInterrogation(false)
|
||||||
}else{
|
}else{
|
||||||
listMyAnsweredInterrogation(true)
|
listMyAnsweredInterrogation(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -294,25 +345,32 @@ function goBack() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 底部tab交互
|
// 底部tab交互
|
||||||
const bottomActive = ref('quick')
|
const bottomActive = ref('multi')
|
||||||
const switchBottomTab=(key)=>{
|
const switchBottomTab=(key)=>{
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
bottomActive.value = key;
|
bottomActive.value = key;
|
||||||
|
page.value = 1
|
||||||
|
hasMore.value = true;
|
||||||
listNew.value = [];
|
listNew.value = [];
|
||||||
listMine.value=[];
|
listMine.value=[];
|
||||||
if(key=='quick'){
|
if(key=='quick'){
|
||||||
|
try {
|
||||||
|
plus.runtime.quit();
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
}
|
||||||
if(activeTab.value==='new'){
|
if(activeTab.value==='new'){
|
||||||
newConsultList(true)
|
newConsultList(false)
|
||||||
}else{
|
}else{
|
||||||
consultListHis(true)
|
consultListHis(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
if(activeTab.value==='new'){
|
if(activeTab.value==='new'){
|
||||||
console.log('listNewInterrogation')
|
console.log('listNewInterrogation')
|
||||||
listNewInterrogation(true);
|
listNewInterrogation(false);
|
||||||
}else{
|
}else{
|
||||||
listMyAnsweredInterrogation(true)
|
listMyAnsweredInterrogation(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -322,6 +380,8 @@ function onRefresh(){
|
|||||||
isRefreshing.value = true
|
isRefreshing.value = true
|
||||||
page.value = 1
|
page.value = 1
|
||||||
hasMore.value = true
|
hasMore.value = true
|
||||||
|
listNew.value = [];
|
||||||
|
listMine.value=[];
|
||||||
if(bottomActive.value==='quick'){
|
if(bottomActive.value==='quick'){
|
||||||
if(activeTab.value==='new'){
|
if(activeTab.value==='new'){
|
||||||
newConsultList(true)
|
newConsultList(true)
|
||||||
@@ -372,35 +432,49 @@ function onReachBottom(){
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 44px;
|
height: 48px;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 140rpx;
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
box-shadow: 0 1px 0 rgba(0,0,0,0.06);
|
border-bottom: 1px solid #e5e5e5;
|
||||||
|
.bar{
|
||||||
|
width:1px;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #e5e5e5;
|
||||||
|
}
|
||||||
.tab {
|
.tab {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 16px;
|
font-size: 36rpx;
|
||||||
color: #7a7a7a;
|
color: #7a7a7a;
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
&.active { color: #8B2316; position: relative; }
|
&.active { color: #8B2316; position: relative; }
|
||||||
&.active::after { content: ''; position: absolute; left: 25%; right: 25%; bottom: 2px; height: 3px; background-color: #8B2316; border-radius: 2px; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.tabs-spacer { height: 44px; }
|
.tabs-spacer { height: 44px; }
|
||||||
|
.namebox{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
.user-avatar{
|
||||||
|
margin-left: 10rpx;
|
||||||
|
font-size:32rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
.list-scroll {
|
.list-scroll {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 228rpx;
|
top: calc(var(--status-bar-height) + 44px + 48px);
|
||||||
bottom: 136rpx;
|
bottom:56px;
|
||||||
padding: 8px 0px 0 0px;
|
margin: 20rpx rpx 0;
|
||||||
margin: 20rpx 30rpx 0;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width:auto;
|
width:100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.consult-card {
|
.consult-card {
|
||||||
@@ -412,8 +486,8 @@ function onReachBottom(){
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
.user-name { font-size: 16px; color: #a31712; }
|
.user-name { font-size: 36rpx; color: #a31712; }
|
||||||
.date { font-size: 14px; color: #9aa0a6; }
|
.date { font-size: 36rpx; color: #9aa0a6; }
|
||||||
}
|
}
|
||||||
.card-body {
|
.card-body {
|
||||||
background: #efefef;
|
background: #efefef;
|
||||||
@@ -443,31 +517,49 @@ function onReachBottom(){
|
|||||||
}
|
}
|
||||||
display: flex; align-items: center; justify-content: space-between; margin-top: 8px;
|
display: flex; align-items: center; justify-content: space-between; margin-top: 8px;
|
||||||
.reply-count { font-size:28rpx; color: #8B2316; }
|
.reply-count { font-size:28rpx; color: #8B2316; }
|
||||||
|
.reply-count-none{
|
||||||
|
font-size:28rpx;
|
||||||
|
color: #999;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 25rpx;
|
||||||
|
}
|
||||||
|
.reply-count-none::after{
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
left: 0;
|
||||||
|
width: 20rpx;
|
||||||
|
height: 20rpx;
|
||||||
|
background: red;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
.tag {
|
.tag {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 8rpx 16rpx; background: #fff5f5; color: #a31712; border-radius: 28rpx; font-size: 24rpx; border:2rpx solid #a31712;}
|
padding: 0rpx 16rpx; background: #fff; color: #a31712; border-radius: 28rpx; font-size: 24rpx; border:2rpx solid #a31712;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottom-bar {
|
.bottom-bar {
|
||||||
|
border-top: 1px solid #e5e5e5;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0; right: 0; bottom: 0;
|
left: 0; right: 0; bottom: 0;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
box-shadow: 0 -2px 8px rgba(0,0,0,0.06);
|
box-shadow: 0 -2px 8px rgba(0,0,0,0.06);
|
||||||
display: flex; align-items: center; justify-content: center;
|
display: flex;
|
||||||
padding: 8px 12px;
|
align-items: center;
|
||||||
gap: 12px;
|
justify-content: center;
|
||||||
.bottom-tab {
|
.bottom-tab {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 40px;
|
height: 56px;
|
||||||
line-height: 40px;
|
line-height: 56px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: 6px;
|
|
||||||
font-size: 16px;
|
font-size: 36rpx;
|
||||||
color: #a31712;
|
color: #999;
|
||||||
background-color: #fff5f5;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
.bottom-tab.active {
|
.bottom-tab.active {
|
||||||
background-color: #a31712;
|
background-color: #a31712;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,935 @@
|
|||||||
|
<template>
|
||||||
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
|
left-icon="left"
|
||||||
|
title="视频缓存"
|
||||||
|
@clickLeft="goBack"
|
||||||
|
color="#8B2316"
|
||||||
|
:border="false"
|
||||||
|
backgroundColor="#eeeeee"
|
||||||
|
>
|
||||||
|
<template #right>
|
||||||
|
<view class="nav-actions">
|
||||||
|
<view class="nav-edit" @click="toggleEdit">
|
||||||
|
<text>{{ isEditMode ? "取消" : "编辑" }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</uni-nav-bar>
|
||||||
|
</view>
|
||||||
|
<view class="download-video-page">
|
||||||
|
<!-- 标签页 -->
|
||||||
|
<view class="tabs-container">
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: activeTab === 'completed' }"
|
||||||
|
@click="switchTab('completed')"
|
||||||
|
>
|
||||||
|
已完成
|
||||||
|
</view>
|
||||||
|
<view class="tab-divider"></view>
|
||||||
|
<view
|
||||||
|
class="tab-item"
|
||||||
|
:class="{ active: activeTab === 'downloading' }"
|
||||||
|
@click="switchTab('downloading')"
|
||||||
|
>
|
||||||
|
缓存中
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 内容列表 -->
|
||||||
|
<scroll-view class="content-scroll" scroll-y :scroll-top="scrollTop">
|
||||||
|
<view v-if="currentList.length === 0" class="empty-state">
|
||||||
|
<text>暂无数据</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view
|
||||||
|
v-for="(item, index) in currentList"
|
||||||
|
:key="item.id || index"
|
||||||
|
class="video-item"
|
||||||
|
@click="handleItemClick(item)"
|
||||||
|
>
|
||||||
|
<!-- 编辑模式下的多选框 -->
|
||||||
|
<view
|
||||||
|
v-if="isEditMode"
|
||||||
|
class="checkbox-wrapper"
|
||||||
|
@click.stop="toggleSelectItem(item)"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="checkbox"
|
||||||
|
:class="{ checked: isItemSelected(item) }"
|
||||||
|
>
|
||||||
|
<uni-icons
|
||||||
|
v-if="isItemSelected(item)"
|
||||||
|
type="checkmarkempty"
|
||||||
|
size="16"
|
||||||
|
color="#ffffff"
|
||||||
|
></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 缩略图 -->
|
||||||
|
<image
|
||||||
|
class="video-thumbnail"
|
||||||
|
:src="docUrl + item.imgpath"
|
||||||
|
mode="aspectFill"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 内容信息 -->
|
||||||
|
<view class="video-info">
|
||||||
|
<view class="video-title">{{ item.name || "视频标题" }}</view>
|
||||||
|
<view class="video-author">{{ item.author || "作者" }}</view>
|
||||||
|
|
||||||
|
<!-- 时长和大小 -->
|
||||||
|
<view class="video-meta" v-if="item.status === 'completed'">
|
||||||
|
<uni-icons
|
||||||
|
type="clock"
|
||||||
|
size="12"
|
||||||
|
color="#999999"
|
||||||
|
class="meta-icon"
|
||||||
|
></uni-icons>
|
||||||
|
<text class="meta-text"><text v-if="item.duration">{{ formatDuration(item.duration) }}</text></text>
|
||||||
|
<text class="meta-size">{{ formatSize(item.size) }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="video-meta video-status" v-if="item.status == 'downloading' || item.status == 'paused'">
|
||||||
|
<view class="status-icon">
|
||||||
|
<image :src="item.status == 'paused' ? playImg : pauseImg" mode="aspectFill"></image>
|
||||||
|
<text>{{ item.status == 'paused' ? '继续' : '暂停' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="box">
|
||||||
|
<!-- <view class="video-progress-bar">
|
||||||
|
<view class="video-progress-bar-inner" :style="{ width: item.progress + '%' }"></view>
|
||||||
|
</view> -->
|
||||||
|
<!-- <text>{{ item.progress + '%' }}</text> -->
|
||||||
|
<view class="size-box">{{ formatSize(item.downloadSize) }}/{{ formatSize(item.totalSize) }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 编辑模式下的删除按钮 -->
|
||||||
|
<!-- <view
|
||||||
|
v-if="isEditMode"
|
||||||
|
class="delete-btn"
|
||||||
|
@click.stop="deleteItem(item, index)"
|
||||||
|
>
|
||||||
|
<text>删除</text>
|
||||||
|
</view> -->
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 底部存储信息 -->
|
||||||
|
<view class="bottom-box">
|
||||||
|
<view class="storage-info">
|
||||||
|
<text
|
||||||
|
>手机存储:总空间{{ storageInfo.total }}/剩余{{
|
||||||
|
storageInfo.available
|
||||||
|
}}可用</text
|
||||||
|
>
|
||||||
|
</view>
|
||||||
|
<view class="footer-btn" v-if="isEditMode">
|
||||||
|
<view class="footer-btn-item select" @click="clearAll">
|
||||||
|
<text v-if="!isAllSelect">全选</text>
|
||||||
|
<text v-else>取消全选</text>
|
||||||
|
</view>
|
||||||
|
<view class="bar"></view>
|
||||||
|
<view class="footer-btn-item del" @click="delTask">
|
||||||
|
删除<text v-if="selectedItems.length > 0">({{ selectedItems.length }})</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, onMounted, nextTick } from "vue";
|
||||||
|
import downloadStore from "@/store/downloadStoreVideo.js";
|
||||||
|
import { onLoad, onShow,onUnload,onBackPress} from "@dcloudio/uni-app";
|
||||||
|
import playImg from "@/static/down_true.png";
|
||||||
|
import pauseImg from "@/static/down_false.png";
|
||||||
|
import navTo from "@/utils/navTo";
|
||||||
|
import docUrl from "@/utils/docUrl";
|
||||||
|
const downloadTasks = ref([]);
|
||||||
|
const unsubscribe = ref(null);
|
||||||
|
const isAllSelect = ref(false);
|
||||||
|
const selectedItems = ref([]);
|
||||||
|
// 响应式数据
|
||||||
|
const activeTab = ref("completed"); // completed: 已完成, downloading: 缓存中
|
||||||
|
const isEditMode = ref(false);
|
||||||
|
const scrollTop = ref(0);
|
||||||
|
const storageInfo = ref({
|
||||||
|
total: "461.31G",
|
||||||
|
available: "312.92G",
|
||||||
|
});
|
||||||
|
const delTask=()=>{
|
||||||
|
if(selectedItems.value.length === 0){
|
||||||
|
uni.showToast({
|
||||||
|
title: "请选择要删除的缓存",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uni.showModal({
|
||||||
|
title: "提示",
|
||||||
|
content: "确定要删除选中的缓存吗?",
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
// 从后往前删除,避免索引变化问题
|
||||||
|
const idsToDelete = [...selectedItems.value];
|
||||||
|
idsToDelete.forEach(id => {
|
||||||
|
const taskIndex = downloadTasks.value.findIndex(t => t.id === id);
|
||||||
|
if (taskIndex !== -1) {
|
||||||
|
removeTask(taskIndex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 清空选择
|
||||||
|
selectedItems.value = [];
|
||||||
|
isAllSelect.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const clearAll=()=>{
|
||||||
|
if(!isAllSelect.value){
|
||||||
|
// 全选当前列表的所有项
|
||||||
|
selectedItems.value = currentList.value.map(item => item.id);
|
||||||
|
isAllSelect.value = true;
|
||||||
|
}else{
|
||||||
|
// 取消全选
|
||||||
|
selectedItems.value = [];
|
||||||
|
isAllSelect.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断项是否被选中
|
||||||
|
const isItemSelected = (item) => {
|
||||||
|
return selectedItems.value.includes(item.id);
|
||||||
|
}
|
||||||
|
onBackPress(() => {
|
||||||
|
if(from.value){
|
||||||
|
plus.runtime.quit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 切换项的选中状态
|
||||||
|
const toggleSelectItem = (item) => {
|
||||||
|
const index = selectedItems.value.indexOf(item.id);
|
||||||
|
if (index > -1) {
|
||||||
|
selectedItems.value.splice(index, 1);
|
||||||
|
} else {
|
||||||
|
selectedItems.value.push(item.id);
|
||||||
|
}
|
||||||
|
// 更新全选状态
|
||||||
|
isAllSelect.value = selectedItems.value.length === currentList.value.length && currentList.value.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算当前显示的列表
|
||||||
|
const currentList = computed(() => {
|
||||||
|
let list = [];
|
||||||
|
if (activeTab.value === "completed") {
|
||||||
|
list = downloadTasks.value.filter((task) => task.status === "completed");
|
||||||
|
} else {
|
||||||
|
list = downloadTasks.value.filter(
|
||||||
|
(task) => task.status === "downloading" || task.status === "paused"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// 当列表变化时,更新全选状态
|
||||||
|
nextTick(() => {
|
||||||
|
if (isAllSelect.value && selectedItems.value.length !== list.length) {
|
||||||
|
isAllSelect.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
// 方法
|
||||||
|
const goBack = () => {
|
||||||
|
if(from.value){
|
||||||
|
plus.runtime.quit();
|
||||||
|
}else{
|
||||||
|
uni.navigateBack()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const switchTab = (tab) => {
|
||||||
|
activeTab.value = tab;
|
||||||
|
isEditMode.value = false;
|
||||||
|
// 切换标签时清空选择
|
||||||
|
selectedItems.value = [];
|
||||||
|
isAllSelect.value = false;
|
||||||
|
// 切换到缓存中时,滚动到顶部
|
||||||
|
if (tab === 'downloading') {
|
||||||
|
// 先设置为一个非0值,然后在下一个tick设置为0,确保滚动触发
|
||||||
|
scrollTop.value = 0.01;
|
||||||
|
nextTick(() => {
|
||||||
|
scrollTop.value = 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const toggleEdit = () => {
|
||||||
|
isEditMode.value = !isEditMode.value;
|
||||||
|
// 退出编辑模式时清空选择
|
||||||
|
if (!isEditMode.value) {
|
||||||
|
selectedItems.value = [];
|
||||||
|
isAllSelect.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleItemClick = (item) => {
|
||||||
|
if (isEditMode.value) {
|
||||||
|
// 编辑模式下,点击项切换选中状态
|
||||||
|
toggleSelectItem(item);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 跳转到视频详情或播放页面
|
||||||
|
if (item.status === "completed") {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages_app/videoDetail/videoDetail?id=${item.id}&from=download`,
|
||||||
|
});
|
||||||
|
}else if(item.status === "downloading"){
|
||||||
|
let index=downloadTasks.value.findIndex(t => t.id === item.id);
|
||||||
|
if(index !== -1){
|
||||||
|
pauseTask(index);
|
||||||
|
}
|
||||||
|
}else if(item.status === "paused"){
|
||||||
|
let index=downloadTasks.value.findIndex(t => t.id === item.id);
|
||||||
|
if(index !== -1){
|
||||||
|
resumeTask(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteItem = (item, index) => {
|
||||||
|
uni.showModal({
|
||||||
|
title: "提示",
|
||||||
|
content: "确定要删除这个缓存吗?",
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
// 从store中删除
|
||||||
|
const taskIndex = downloadTasks.value.findIndex((t) => t.id === item.id);
|
||||||
|
if (taskIndex !== -1) {
|
||||||
|
removeTask(taskIndex);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatDuration = (duration) => {
|
||||||
|
if (!duration) return "00:00:00";
|
||||||
|
// 如果duration是秒数
|
||||||
|
if (typeof duration === "number") {
|
||||||
|
const hours = Math.floor(duration / 3600);
|
||||||
|
const minutes = Math.floor((duration % 3600) / 60);
|
||||||
|
const seconds = duration % 60;
|
||||||
|
return `${String(hours).padStart(2, "0")}:${String(minutes).padStart(
|
||||||
|
2,
|
||||||
|
"0"
|
||||||
|
)}:${String(seconds).padStart(2, "0")}`;
|
||||||
|
}
|
||||||
|
// 如果已经是格式化字符串
|
||||||
|
return duration;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatSize = (size) => {
|
||||||
|
if (!size) return "0M";
|
||||||
|
// 如果size是字节数
|
||||||
|
|
||||||
|
const mb = (Number(size) / 1024 / 1024).toFixed(2);
|
||||||
|
return `${mb}M`;
|
||||||
|
|
||||||
|
// 如果已经是格式化字符串
|
||||||
|
return size;
|
||||||
|
};
|
||||||
|
const from = ref('');
|
||||||
|
onLoad((options) => {
|
||||||
|
if(options.from){
|
||||||
|
from.value = options.from;
|
||||||
|
}
|
||||||
|
if(options.type){
|
||||||
|
switchTab('downloading')
|
||||||
|
}
|
||||||
|
// 从store同步任务列表
|
||||||
|
syncTasksFromStore();
|
||||||
|
// 监听store变化
|
||||||
|
unsubscribe.value = downloadStore.addListener((tasks) => {
|
||||||
|
downloadTasks.value = tasks;
|
||||||
|
});
|
||||||
|
console.log(11111);
|
||||||
|
console.log(downloadTasks.value);
|
||||||
|
// 恢复正在下载的任务
|
||||||
|
resumeDownloadingTasks();
|
||||||
|
}),
|
||||||
|
onShow(() => {
|
||||||
|
// 页面显示时同步最新任务列表
|
||||||
|
syncTasksFromStore();
|
||||||
|
// 检查并恢复下载任务
|
||||||
|
resumeDownloadingTasks();
|
||||||
|
}),
|
||||||
|
onUnload(() => {
|
||||||
|
// 页面 卸载时取消监听
|
||||||
|
if (unsubscribe.value) {
|
||||||
|
unsubscribe.value();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const getStorageInfo = () => {
|
||||||
|
// 获取手机存储信息
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
if (uni.getSystemInfoSync().platform !== 'android') {
|
||||||
|
uni.sendNativeEvent('getSysSpace',{
|
||||||
|
msg: 'getSysSpace'
|
||||||
|
},(res) => {
|
||||||
|
storageInfo.value = {
|
||||||
|
total: res.total,
|
||||||
|
available: res.available,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
// 1. 导入所需的Android类
|
||||||
|
const Environment = plus.android.importClass("android.os.Environment");
|
||||||
|
const StatFs = plus.android.importClass("android.os.StatFs");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 2. 获取内部存储的数据目录(File对象)
|
||||||
|
const dataDirectory = Environment.getDataDirectory(); // 这是一个Java File对象
|
||||||
|
|
||||||
|
// 3. 关键修正:使用 plus.android.invoke 调用 File 对象的 getPath 方法
|
||||||
|
const dataDirectoryPath = plus.android.invoke(dataDirectory, "getPath");
|
||||||
|
// 现在 dataDirectoryPath 是一个字符串,表示路径
|
||||||
|
|
||||||
|
// 4. 创建 StatFs 对象,传入路径字符串
|
||||||
|
const statFs = new StatFs(dataDirectoryPath);
|
||||||
|
|
||||||
|
// 5. 使用 invoke 调用 StatFs 的方法获取存储块信息
|
||||||
|
const blockSize = plus.android.invoke(statFs, "getBlockSize");
|
||||||
|
const availableBlocks = plus.android.invoke(statFs, "getAvailableBlocks");
|
||||||
|
const totalBlocks = plus.android.invoke(statFs, "getBlockCount");
|
||||||
|
|
||||||
|
|
||||||
|
// 6. 计算可用空间和总空间(单位:字节)
|
||||||
|
const availableSizeInBytes = blockSize * availableBlocks;
|
||||||
|
const totalSizeInBytes = blockSize * totalBlocks;
|
||||||
|
|
||||||
|
|
||||||
|
// 7. 转换为常用单位
|
||||||
|
const availableSizeInGB = (availableSizeInBytes / (1024 * 1024 * 1024)).toFixed(2);
|
||||||
|
const availableSizeInMB = (availableSizeInBytes / (1024 * 1024)).toFixed(2);
|
||||||
|
const totalSizeInGB = (totalSizeInBytes / (1024 * 1024 * 1024)).toFixed(2);
|
||||||
|
|
||||||
|
|
||||||
|
// console.log(`可用存储空间:${availableSizeInBytes} 字节`);
|
||||||
|
// console.log(`可用存储空间:${availableSizeInMB} MB`);
|
||||||
|
// console.log(`可用存储空间:${availableSizeInGB} GB`);
|
||||||
|
|
||||||
|
// 可以根据需要返回不同单位的值
|
||||||
|
storageInfo.value = {
|
||||||
|
total: totalSizeInGB+"G",
|
||||||
|
available: availableSizeInGB+"G",
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取存储信息时发生错误:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// #endif
|
||||||
|
};
|
||||||
|
const syncTasksFromStore=()=> {
|
||||||
|
downloadTasks.value = downloadStore.getTasks();
|
||||||
|
};
|
||||||
|
// 添加下载任务
|
||||||
|
const addDownloadTask = (item) => {
|
||||||
|
// 使用store添加任务
|
||||||
|
const taskIndex = downloadStore.addTask(item);
|
||||||
|
|
||||||
|
// 同步任务列表
|
||||||
|
syncTasksFromStore();
|
||||||
|
|
||||||
|
// 开始下载
|
||||||
|
startDownload(taskIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 开始下载
|
||||||
|
const startDownload = (index) => {
|
||||||
|
const taskItem = downloadStore.getTask(index);
|
||||||
|
if (!taskItem) return;
|
||||||
|
|
||||||
|
const task = uni.downloadFile({
|
||||||
|
url: taskItem.url,
|
||||||
|
success: (res) => {
|
||||||
|
if (res.statusCode === 200) {
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "completed",
|
||||||
|
filePath: res.tempFilePath,
|
||||||
|
});
|
||||||
|
uni.showToast({
|
||||||
|
title: "下载成功",
|
||||||
|
icon: "success",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(res);
|
||||||
|
uni.saveFile({
|
||||||
|
tempFilePath: res.tempFilePath,
|
||||||
|
success: function (res) {
|
||||||
|
uni.getSavedFileInfo({
|
||||||
|
filePath: res.savedFilePath,
|
||||||
|
success: function (res) {
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "completed",
|
||||||
|
realyPath: res.savedFilePath,
|
||||||
|
size: res.size,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "failed",
|
||||||
|
});
|
||||||
|
uni.showToast({
|
||||||
|
title: "下载失败",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "failed",
|
||||||
|
});
|
||||||
|
console.error("下载失败:", err);
|
||||||
|
uni.showToast({
|
||||||
|
title: "下载失败: " + (err.errMsg || "未知错误"),
|
||||||
|
icon: "none",
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 监听下载进度
|
||||||
|
task.onProgressUpdate((update) => {
|
||||||
|
const currentTask = downloadStore.getTask(index);
|
||||||
|
if (currentTask && currentTask.status === "downloading") {
|
||||||
|
console.log(update.progress);
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
progress: update.progress,
|
||||||
|
downloadSize: update.totalBytesWritten,
|
||||||
|
totalSize: update.totalBytesExpectedToWrite,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 保存task对象到store(用于暂停/继续)
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
task: task,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 暂停任务
|
||||||
|
const pauseTask = (index) => {
|
||||||
|
const taskItem = downloadStore.getTask(index);
|
||||||
|
if (taskItem && taskItem.task) {
|
||||||
|
taskItem.task.abort();
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "paused",
|
||||||
|
task: null,
|
||||||
|
});
|
||||||
|
uni.showToast({
|
||||||
|
title: "已暂停",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 继续任务
|
||||||
|
const resumeTask = (index) => {
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "downloading",
|
||||||
|
progress: 0, // 重新开始(uni.downloadFile不支持断点续传)
|
||||||
|
});
|
||||||
|
startDownload(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除任务
|
||||||
|
const removeTask = (index) => {
|
||||||
|
downloadStore.removeTask(index);
|
||||||
|
syncTasksFromStore();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 打开文件
|
||||||
|
const openFile = (filePath) => {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
plus.runtime.openFile(filePath);
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showToast({
|
||||||
|
title: "请在APP中打开",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取文件名
|
||||||
|
const getFileName = (url) => {
|
||||||
|
if (!url) return "未知文件";
|
||||||
|
try {
|
||||||
|
const urlObj = new URL(url);
|
||||||
|
const pathname = urlObj.pathname;
|
||||||
|
const fileName = pathname.split("/").pop();
|
||||||
|
return fileName || "下载文件";
|
||||||
|
} catch (e) {
|
||||||
|
// 如果不是完整URL,尝试从路径中提取
|
||||||
|
const parts = url.split("/");
|
||||||
|
return parts[parts.length - 1] || "下载文件";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取状态文本
|
||||||
|
const getStatusText = (status) => {
|
||||||
|
const statusMap = {
|
||||||
|
downloading: "下载中",
|
||||||
|
paused: "已暂停",
|
||||||
|
completed: "已完成",
|
||||||
|
failed: "下载失败",
|
||||||
|
};
|
||||||
|
return statusMap[status] || "未知";
|
||||||
|
};
|
||||||
|
|
||||||
|
// 恢复正在下载的任务
|
||||||
|
const resumeDownloadingTasks = () => {
|
||||||
|
// 使用 nextTick 确保在页面渲染后再恢复下载任务
|
||||||
|
nextTick(() => {
|
||||||
|
downloadStore.resumeDownloadingTasks((index) => {
|
||||||
|
// 重新开始下载(uni.downloadFile不支持断点续传,所以从0开始)
|
||||||
|
console.log("恢复下载任务:", downloadStore.getTask(index)?.url);
|
||||||
|
startDownload(index);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getStorageInfo();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
page{
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
.size-box{
|
||||||
|
display: flex;
|
||||||
|
white-space: nowrap;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color:#8b2316
|
||||||
|
}
|
||||||
|
.box{
|
||||||
|
display: flex;
|
||||||
|
white-space: nowrap;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-left: 30rpx;
|
||||||
|
text{
|
||||||
|
width: 40rpx;
|
||||||
|
display: flex;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color:#8b2316
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.download-video-page {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: calc(var(--status-bar-height) + 44px);
|
||||||
|
height: calc(100vh - var(--status-bar-height) - 44px);
|
||||||
|
background-color: #ffffff;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.footer-btn{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
height: 100rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-top: 1px solid #f0f0f0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
.select{
|
||||||
|
flex:1;
|
||||||
|
height: 100rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.del{
|
||||||
|
height: 100rpx;
|
||||||
|
flex:1;
|
||||||
|
color:red;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.bar{
|
||||||
|
width: 1px;
|
||||||
|
height: 40rpx;
|
||||||
|
|
||||||
|
background-color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.video-progress-bar {
|
||||||
|
flex:1;
|
||||||
|
height: 10rpx;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.video-progress-bar-inner {
|
||||||
|
height: 10rpx;
|
||||||
|
background-color: #8b2316;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.nav-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 44px;
|
||||||
|
padding: 0 15px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-back {
|
||||||
|
width: 40px;
|
||||||
|
height: 44px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back-icon {
|
||||||
|
font-size: 28px;
|
||||||
|
color: #8b2316;
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-title {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #8b2316;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-edit {
|
||||||
|
width: 40px;
|
||||||
|
height: 44px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tabs-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 50px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
position: sticky;
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
flex: 1;
|
||||||
|
height: 50px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #999999;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: #8b2316;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-divider {
|
||||||
|
width: 1px;
|
||||||
|
height: 20px;
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-scroll {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-bottom: 200rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 100px 0;
|
||||||
|
color: #999999;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 15px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-thumbnail {
|
||||||
|
width: 120px;
|
||||||
|
height: 80px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
margin-right: 12px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-info {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
min-height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-title {
|
||||||
|
font-size: 15px;
|
||||||
|
color: #333333;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-author {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #666666;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-meta {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
.video-status{
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
|
||||||
|
justify-content: space-between;
|
||||||
|
.status-icon{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
justify-content: center;
|
||||||
|
image{
|
||||||
|
width:30rpx;
|
||||||
|
height: 29rpx;
|
||||||
|
margin-right: 10rpx;
|
||||||
|
}
|
||||||
|
text{
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-icon {
|
||||||
|
margin-right: 4px;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-text {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-size {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox-wrapper {
|
||||||
|
margin-right: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checkbox {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: 1px solid #d0d0d0;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background-color: #ffffff;
|
||||||
|
transition: all 0.2s;
|
||||||
|
|
||||||
|
&.checked {
|
||||||
|
background-color: #8b2316;
|
||||||
|
border-color: #8b2316;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
padding: 8px 16px;
|
||||||
|
background-color: #ff4444;
|
||||||
|
color: #ffffff;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-box {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.storage-info {
|
||||||
|
padding: 12px 15px;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
border-top: 1px solid #f0f0f0;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666666;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
@@ -3,17 +3,18 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- 顶部导航栏 -->
|
<!-- 顶部导航栏 -->
|
||||||
<navBar title="意见反馈"></navBar>
|
<navBar :title="'投诉反馈'"></navBar>
|
||||||
|
|
||||||
<!-- 反馈输入区域 -->
|
<!-- 反馈输入区域 -->
|
||||||
<view class="feedback-input-container">
|
<view class="feedback-input-container">
|
||||||
<view class="input-area">
|
<view class="input-area">
|
||||||
<text class="input-placeholder" v-show="!feedbackText">欢迎对我们的软件提供建议,帮助我们更好更快的改进"肝胆相照"APP (200字以内)</text>
|
<!-- <text class="input-placeholder" v-show="!feedbackText">欢迎对我们的软件提供建议,帮助我们更好更快的改进"肝胆相照"APP (200字以内)</text> -->
|
||||||
<textarea
|
<textarea
|
||||||
class="feedback-textarea"
|
class="feedback-textarea"
|
||||||
v-model="feedbackText"
|
v-model="feedbackText"
|
||||||
:maxlength="200"
|
:maxlength="200"
|
||||||
placeholder=""
|
placeholder="尊敬的医生您好,若在交流过程中发现患者发布不适当内容,请您及时填写相关信息,我们将第一时间处理,谢谢您的支持。"
|
||||||
|
:adjust-position="false"
|
||||||
@input="onInput"
|
@input="onInput"
|
||||||
></textarea>
|
></textarea>
|
||||||
<!-- <view class="voice-button" @click="toggleVoiceInput">
|
<!-- <view class="voice-button" @click="toggleVoiceInput">
|
||||||
@@ -24,7 +25,7 @@
|
|||||||
|
|
||||||
<!-- 底部提交按钮 -->
|
<!-- 底部提交按钮 -->
|
||||||
<view class="submit-container">
|
<view class="submit-container">
|
||||||
<button class="submit-btn" @click="submitFeedback" :disabled="!feedbackText.trim()">
|
<button class="submit-btn" @click="submitFeedback" >
|
||||||
提交
|
提交
|
||||||
</button>
|
</button>
|
||||||
</view>
|
</view>
|
||||||
@@ -126,8 +127,15 @@
|
|||||||
|
|
||||||
/* 反馈输入区域 */
|
/* 反馈输入区域 */
|
||||||
.feedback-input-container {
|
.feedback-input-container {
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 160rpx;
|
||||||
|
overflow-y: scroll;
|
||||||
|
z-index: 1;
|
||||||
padding: 30rpx;
|
padding: 30rpx;
|
||||||
flex: 1;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-area {
|
.input-area {
|
||||||
@@ -199,10 +207,10 @@
|
|||||||
.submit-btn {
|
.submit-btn {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 88rpx;
|
height: 88rpx;
|
||||||
background-color: #ffffff;
|
background-color: #fff;
|
||||||
border: 2rpx solid #e0e0e0;
|
border: 2rpx solid #8B2316;
|
||||||
border-radius: 8rpx;
|
border-radius: 8rpx;
|
||||||
color: #ff0000;
|
color: #8B2316;
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="visit-note-page">
|
<view class="visit-note-page">
|
||||||
<uni-nav-bar
|
<navBar :title="'随访详情'" />
|
||||||
|
<!-- <uni-nav-bar
|
||||||
left-icon="left"
|
left-icon="left"
|
||||||
title="随访详情"
|
title="随访详情"
|
||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
fixed
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
height="180rpx"
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eee"
|
backgroundColor="#eee"
|
||||||
>
|
>
|
||||||
|
|
||||||
</uni-nav-bar>
|
</uni-nav-bar> -->
|
||||||
|
|
||||||
<!-- 患者行 -->
|
<!-- 患者行 -->
|
||||||
<view class="row" @click="noop">
|
<view class="contentbox">
|
||||||
|
<view class="row" @click="noop">
|
||||||
<text class="row-label">患者</text>
|
<text class="row-label">患者</text>
|
||||||
<text class="row-value">{{ patientName }}</text>
|
<text class="row-value">{{ patientName }}</text>
|
||||||
</view>
|
</view>
|
||||||
@@ -27,7 +29,8 @@
|
|||||||
|
|
||||||
<!-- 输入框区域 -->
|
<!-- 输入框区域 -->
|
||||||
<view class="note-box">
|
<view class="note-box">
|
||||||
<textarea class="note-textarea" v-model.trim="note" placeholder="请填写随访内容" auto-height :maxlength="200" />
|
<textarea class="note-textarea" v-model.trim="note" placeholder="请填写随访内容" auto-height :maxlength="200" :adjust-position="false"/>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<!-- 底部删除按钮 -->
|
<!-- 底部删除按钮 -->
|
||||||
<view class="fixed-footer">
|
<view class="fixed-footer">
|
||||||
@@ -41,6 +44,7 @@
|
|||||||
import { onLoad,onShow } from '@dcloudio/uni-app'
|
import { onLoad,onShow } from '@dcloudio/uni-app'
|
||||||
import api from '@/api/api.js'
|
import api from '@/api/api.js'
|
||||||
const patientName = ref('')
|
const patientName = ref('')
|
||||||
|
import navBar from '@/components/navBar/navBar.vue'
|
||||||
const note = ref('请近日来医院复诊、复查')
|
const note = ref('请近日来医院复诊、复查')
|
||||||
const datetime = ref('')
|
const datetime = ref('')
|
||||||
const followUpUuid = ref('')
|
const followUpUuid = ref('')
|
||||||
@@ -91,19 +95,29 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.contentbox{
|
||||||
|
position: fixed;
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
overflow-y: scroll;
|
||||||
|
bottom:128rpx;
|
||||||
|
z-index:1;
|
||||||
|
|
||||||
|
}
|
||||||
.visit-note-page{
|
.visit-note-page{
|
||||||
min-height: 100vh; background:#f5f5f5; padding-bottom: 120rpx;
|
background:#f5f5f5; padding-bottom: 120rpx;
|
||||||
}
|
}
|
||||||
.nav-right{ display:flex; align-items:center; }
|
.nav-right{ display:flex; align-items:center; }
|
||||||
.submit-text{ color:#8B2316; font-size: 30rpx; }
|
.submit-text{ color:#8B2316; font-size: 30rpx; }
|
||||||
|
|
||||||
.row{
|
.row{
|
||||||
margin-top: 20rpx; background:#fff; padding: 26rpx 30rpx; display:flex; align-items:center; justify-content:space-between; border-bottom: 1rpx solid #eee;
|
background:#fff; padding: 26rpx 30rpx; display:flex; align-items:center; justify-content:space-between; border-bottom: 1rpx solid #eee;
|
||||||
.row-label{ font-size: 32rpx; color:#8B2316; font-weight: 500; }
|
.row-label{ font-size: 32rpx; color:#8B2316; font-weight: 500; }
|
||||||
.row-value{ font-size: 32rpx; color:#333; }
|
.row-value{ font-size: 32rpx; color:#333; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-title{ background:#fff; padding: 22rpx 30rpx; color:#8B2316; font-size: 30rpx; border-top: 1rpx solid #eee; border-bottom: 1rpx solid #eee; }
|
.section-title{ background:#fff; padding: 22rpx 30rpx; color:#8B2316; font-size: 30rpx;border-bottom: 1rpx solid #eee; }
|
||||||
|
|
||||||
.note-box{ background:#fff; padding: 20rpx 24rpx; }
|
.note-box{ background:#fff; padding: 20rpx 24rpx; }
|
||||||
.note-textarea{
|
.note-textarea{
|
||||||
|
|||||||
@@ -0,0 +1,513 @@
|
|||||||
|
<template>
|
||||||
|
<view class="consult-detail-page">
|
||||||
|
<!-- 导航栏 -->
|
||||||
|
<navBar title="咨询详情" />
|
||||||
|
|
||||||
|
<!-- 内容区域 -->
|
||||||
|
<scroll-view scroll-y class="content-scroll">
|
||||||
|
<!-- 用户信息区域 -->
|
||||||
|
<view class="user-section">
|
||||||
|
<view class="user-info">
|
||||||
|
<image v-if="userInfo.avatar" :src="userInfo.avatar" class="user-avatar" mode="aspectFill" />
|
||||||
|
<view class="user-details">
|
||||||
|
<view class="user-name">
|
||||||
|
<text class="name">{{ userInfo.name }}</text>
|
||||||
|
<text class="gender-age" v-if="userInfo.gender !== '未知'">({{ userInfo.gender }} {{ userInfo.age }}岁)</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 疾病标签和日期 -->
|
||||||
|
<view class="tag-date-row">
|
||||||
|
<view class="disease-tag">
|
||||||
|
<text class="tag-text">{{ questionInfo.diseaseTag }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="date">{{ questionInfo.date }}</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 问题内容 -->
|
||||||
|
<view class="question-content">
|
||||||
|
<text class="content-text">{{ questionInfo.diseaseDescribe }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 疾病描述 -->
|
||||||
|
<!-- <view v-if="questionInfo.diseaseDescribe" class="disease-describe">
|
||||||
|
<view class="describe-title">疾病描述:</view>
|
||||||
|
<text class="describe-text">{{ questionInfo.diseaseDescribe }}</text>
|
||||||
|
</view> -->
|
||||||
|
|
||||||
|
<!-- 图片网格 -->
|
||||||
|
<view class="image-grid" v-if="questionInfo.images && questionInfo.images.length > 0">
|
||||||
|
<image
|
||||||
|
v-for="(img, index) in questionInfo.images"
|
||||||
|
:key="index"
|
||||||
|
:src="docUrl+img.path"
|
||||||
|
class="grid-image"
|
||||||
|
mode="aspectFill"
|
||||||
|
@click="previewImage(docUrl+img.path, index)"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
<view class="bar"></view>
|
||||||
|
|
||||||
|
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 底部固定区域 -->
|
||||||
|
<view class="bottom-fixed">
|
||||||
|
<!-- 特别声明 -->
|
||||||
|
<!-- 编辑按钮 -->
|
||||||
|
<view class="edit-btn" @click="answerConsult">
|
||||||
|
我要回答
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import navBar from '@/components/navBar/navBar.vue'
|
||||||
|
import detailImg from "@/static/iv_jiwangshi.png"
|
||||||
|
import navTo from '@/utils/navTo.js'
|
||||||
|
import { onLoad,onShow } from '@dcloudio/uni-app'
|
||||||
|
import docUrl from '@/utils/docUrl'
|
||||||
|
import api from "@/api/api.js"
|
||||||
|
const uuid = ref('');
|
||||||
|
const step1_uuid = ref('');
|
||||||
|
let patientUuid = ref('');
|
||||||
|
const status = ref(0);
|
||||||
|
const hasAnswer = ref(false);
|
||||||
|
onLoad((options) => {
|
||||||
|
uuid.value = options.uuid
|
||||||
|
status.value = options.status || 0
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
const consultDetail=()=>{
|
||||||
|
api.consultDetail({
|
||||||
|
uuid:uuid.value
|
||||||
|
}).then(res=>{
|
||||||
|
console.log('咨询详情数据:', res)
|
||||||
|
if(res.code === 200 && res.data && res.data.detail) {
|
||||||
|
const detail = res.data.detail
|
||||||
|
patientUuid.value = detail.patientUuid;
|
||||||
|
// 更新用户信息
|
||||||
|
userInfo.value = {
|
||||||
|
name: detail.patientName ,
|
||||||
|
gender: '未知', // 新数据结构中没有性别信息
|
||||||
|
age: '未知' // 新数据结构中没有年龄信息
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新问题信息
|
||||||
|
questionInfo.value = {
|
||||||
|
date: detail.createDate ? formatDate(detail.createDate) : '未知',
|
||||||
|
diseaseTag: detail.diseaseName || '未知疾病',
|
||||||
|
content: detail.content || '暂无问题描述',
|
||||||
|
images: res.data.imgList?res.data.imgList:[],
|
||||||
|
your_question: detail.content || '',
|
||||||
|
diseaseDescribe: detail.content || '' // 将咨询内容作为疾病描述显示
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新患者头像
|
||||||
|
if(detail.patientPhoto) {
|
||||||
|
userInfo.value.avatar = docUrl + detail.patientPhoto
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新状态信息
|
||||||
|
status.value = detail.state || 0
|
||||||
|
|
||||||
|
console.log('更新后的用户信息:', userInfo.value)
|
||||||
|
console.log('更新后的问题信息:', questionInfo.value)
|
||||||
|
} else {
|
||||||
|
console.error('获取咨询详情失败:', res)
|
||||||
|
uni.showToast({
|
||||||
|
title: res.msg || '获取咨询详情失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('请求咨询详情失败:', err)
|
||||||
|
uni.showToast({
|
||||||
|
title: '网络请求失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const countConsult=()=>{
|
||||||
|
api.countConsult({
|
||||||
|
consultUuid:uuid.value,
|
||||||
|
expertUuid:uni.getStorageSync('userInfo').uuid
|
||||||
|
}).then(res=>{
|
||||||
|
console.log('咨询数量:', res)
|
||||||
|
if(res.code ==200 && res.data){
|
||||||
|
if(res.data> 0){
|
||||||
|
uni.showModal({
|
||||||
|
title: '提示',
|
||||||
|
content: `您已回答过该患者${res.data}次公益咨询,是否确定回答`,
|
||||||
|
success: (res)=>{
|
||||||
|
if(res.confirm){
|
||||||
|
resConsult()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
resConsult();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const answerConsult=async()=>{
|
||||||
|
if(hasAnswer.value){
|
||||||
|
uni.sendNativeEvent('goConsultPage', {
|
||||||
|
msg: 'chat'
|
||||||
|
},ret => {
|
||||||
|
console.log(ret);
|
||||||
|
})
|
||||||
|
// let userId=uni.getStorageSync('userInfo').uuid.toLowerCase();
|
||||||
|
// let conversationId=userId+'|1|'+patientUuid.value.toLowerCase();
|
||||||
|
// await uni.$UIKitStore.uiStore.selectConversation(conversationId)
|
||||||
|
// navTo({
|
||||||
|
// url:'/pages_chat/chat/index?from=consult&patientUuid='+patientUuid.value
|
||||||
|
// })
|
||||||
|
}else{
|
||||||
|
countConsult()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const resConsult=()=>{
|
||||||
|
api.resConsult({
|
||||||
|
consultUuid:uuid.value,
|
||||||
|
expertUuid:uni.getStorageSync('userInfo').uuid
|
||||||
|
}).then(async(res)=>{
|
||||||
|
if(res.code ==200){
|
||||||
|
hasAnswer.value = true;
|
||||||
|
patientUuid.value = res.data.patient_uuid;
|
||||||
|
let userId=uni.getStorageSync('userInfo').uuid.toLowerCase();
|
||||||
|
let conversationId=userId+'|1|'+patientUuid.value.toLowerCase();
|
||||||
|
await uni.$UIKitStore.uiStore.selectConversation(conversationId)
|
||||||
|
navTo({
|
||||||
|
url:'/pages_chat/chat/index?from=consult&patientUuid='+patientUuid.value+'&uuid='+uuid.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onShow(()=>{
|
||||||
|
consultDetail()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 计算年龄
|
||||||
|
function calculateAge(birthday) {
|
||||||
|
const birthDate = new Date(birthday)
|
||||||
|
const today = new Date()
|
||||||
|
let age = today.getFullYear() - birthDate.getFullYear()
|
||||||
|
const monthDiff = today.getMonth() - birthDate.getMonth()
|
||||||
|
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
|
||||||
|
age--
|
||||||
|
}
|
||||||
|
return age.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化日期
|
||||||
|
function formatDate(dateString) {
|
||||||
|
const date = new Date(dateString)
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(date.getDate()).padStart(2, '0')
|
||||||
|
return `${year}-${month}-${day}`
|
||||||
|
}
|
||||||
|
// 用户信息
|
||||||
|
const userInfo = ref({
|
||||||
|
name: '提**',
|
||||||
|
gender: '未知',
|
||||||
|
age: '未知',
|
||||||
|
avatar: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 问题信息
|
||||||
|
const questionInfo = ref({
|
||||||
|
date: '2022-11-09',
|
||||||
|
diseaseTag: '甲型肝炎',
|
||||||
|
content: '为什么程序员总是分不清万圣节和圣诞节?因为Oct31==Dec25。\n任何我写的代码,超过6个月不去看它,当我再看时,都像是别人写的。',
|
||||||
|
diseaseDescribe: '', // 疾病描述
|
||||||
|
images: [
|
||||||
|
'/static/images/placeholder1.jpg',
|
||||||
|
'/static/images/placeholder2.jpg',
|
||||||
|
'/static/images/placeholder3.jpg',
|
||||||
|
'/static/images/placeholder4.jpg',
|
||||||
|
'/static/images/placeholder5.jpg',
|
||||||
|
'/static/images/placeholder6.jpg',
|
||||||
|
'/static/images/placeholder7.jpg',
|
||||||
|
'/static/images/placeholder8.jpg'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// 返回上一页
|
||||||
|
function goBack() {
|
||||||
|
uni.navigateBack()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 预览图片
|
||||||
|
function previewImage(current, index) {
|
||||||
|
uni.previewImage({
|
||||||
|
urls: questionInfo.value.images?questionInfo.value.images.map(item=> docUrl + item.path):[],
|
||||||
|
current: index
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 编辑问题
|
||||||
|
function editQuestion() {
|
||||||
|
navTo({
|
||||||
|
url:'/pages_app/myAnswer/myAnswer?uuid='+uuid.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.consult-detail-page {
|
||||||
|
background-color: #fff;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 88rpx;
|
||||||
|
padding: 0 32rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
|
.nav-left {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.back-icon {
|
||||||
|
font-size: 48rpx;
|
||||||
|
color: #8B2316;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #8B2316;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-right {
|
||||||
|
width: 80rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bar{
|
||||||
|
width:100%;
|
||||||
|
height:20rpx;
|
||||||
|
background-color: #efefef;
|
||||||
|
}
|
||||||
|
.content-scroll {
|
||||||
|
flex: 1;
|
||||||
|
position: fixed;
|
||||||
|
top: 135rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 30rpx 0;
|
||||||
|
bottom: 100rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-section {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
padding: 0 30rpx;
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
|
||||||
|
.user-avatar {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
margin-right: 24rpx;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-details {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.user-name {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #8B2316;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gender-age {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
margin-left: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-status {
|
||||||
|
.status-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
padding: 4rpx 12rpx;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-btn {
|
||||||
|
display: flex;
|
||||||
|
margin-left: 10rpx;
|
||||||
|
|
||||||
|
|
||||||
|
.detail-text {
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 24rpx;
|
||||||
|
margin-right: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-icon {
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-date-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
margin: 0 30rpx 30rpx;
|
||||||
|
.disease-tag {
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
.tag-text {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: #8B2316;
|
||||||
|
border: 2rpx solid #8B2316;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
padding: 7rpx 22rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.date {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.question-content {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 32rpx;
|
||||||
|
margin: 0 30rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
|
||||||
|
.content-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.disease-describe {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 32rpx;
|
||||||
|
margin: 0 30rpx 24rpx;
|
||||||
|
border-left: 6rpx solid #8B2316;
|
||||||
|
|
||||||
|
.describe-title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #8B2316;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.describe-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 8rpx;
|
||||||
|
margin: 0 30rpx 40rpx;
|
||||||
|
|
||||||
|
|
||||||
|
.grid-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 160rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.bottom-fixed {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
padding: 24rpx 32rpx;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.disclaimer {
|
||||||
|
background-color: #fff5f5;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
padding: 24rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
|
||||||
|
.disclaimer-title {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #8B2316;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disclaimer-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
text-align: center;
|
||||||
|
border: 1rpx solid #8B2316;
|
||||||
|
background-color: #fff;
|
||||||
|
color: #8B2316;
|
||||||
|
font-size: 32rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="group-edit-page">
|
<view class="group-edit-page">
|
||||||
<uni-nav-bar
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
left-icon="left"
|
left-icon="left"
|
||||||
:title="groupUuid ? '编辑分组' : '新建分组'"
|
:title="groupUuid ? '编辑分组' : '新建分组'"
|
||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eee"
|
backgroundColor="#eee"
|
||||||
>
|
>
|
||||||
@@ -15,7 +17,9 @@
|
|||||||
</template>
|
</template>
|
||||||
</uni-nav-bar>
|
</uni-nav-bar>
|
||||||
|
|
||||||
<!-- 分组名称 -->
|
</view>
|
||||||
|
<view class="contentbox">
|
||||||
|
<!-- 分组名称 -->
|
||||||
<view class="section-header">分组名称</view>
|
<view class="section-header">分组名称</view>
|
||||||
<view class="name-row">
|
<view class="name-row">
|
||||||
<input class="name-input" v-model.trim="groupName" placeholder="请输入分组名称" maxlength="20" />
|
<input class="name-input" v-model.trim="groupName" placeholder="请输入分组名称" maxlength="20" />
|
||||||
@@ -28,16 +32,14 @@
|
|||||||
<view class="section-header">分组成员</view>
|
<view class="section-header">分组成员</view>
|
||||||
|
|
||||||
<view class="add-member" @click="addMember">
|
<view class="add-member" @click="addMember">
|
||||||
<view class="add-circle">
|
<up-image :src="addImg" width="120rpx" height="120rpx" />
|
||||||
<up-icon name="plus" size="34" color="#bfbfbf" />
|
|
||||||
</view>
|
|
||||||
<text class="add-text">添加组患者</text>
|
<text class="add-text">添加组患者</text>
|
||||||
</view>
|
</view>
|
||||||
<!-- 已选中的成员 -->
|
<!-- 已选中的成员 -->
|
||||||
<view class="selected-members" v-if="members.length > 0">
|
<view class="selected-members" v-if="members.length > 0">
|
||||||
<view class="selected-item" v-for="(m, idx) in members" :key="m.uuid || idx">
|
<view class="selected-item" v-for="(m, idx) in members" :key="m.uuid || idx">
|
||||||
<image class="selected-avatar" :src="docUrl + (m.photo || '')" mode="aspectFill" />
|
<image class="selected-avatar" :src="getMemberAvatar(m)" mode="aspectFill" @error="handleMemberAvatarError(m)" />
|
||||||
<text class="selected-name">{{ m.realName || '未知' }}</text>
|
<text class="selected-name">{{ m.nickname || m.realName }}</text>
|
||||||
<view class="remove-selected" @click="removeMember(idx)">
|
<view class="remove-selected" @click="removeMember(idx)">
|
||||||
<text class="remove-text">——</text>
|
<text class="remove-text">——</text>
|
||||||
<!-- <up-icon name="minus" size="43rpx" color="#fff" bold /> -->
|
<!-- <up-icon name="minus" size="43rpx" color="#fff" bold /> -->
|
||||||
@@ -46,6 +48,7 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
<!-- 底部删除按钮 -->
|
<!-- 底部删除按钮 -->
|
||||||
@@ -63,12 +66,35 @@
|
|||||||
import navTo from '@/utils/navTo.js'
|
import navTo from '@/utils/navTo.js'
|
||||||
import docUrl from '@/utils/docUrl.js'
|
import docUrl from '@/utils/docUrl.js'
|
||||||
import delImg from "@/static/iv_delete.png"
|
import delImg from "@/static/iv_delete.png"
|
||||||
|
import addImg from "@/static/addpatient.png"
|
||||||
import api from '@/api/api.js'
|
import api from '@/api/api.js'
|
||||||
|
import defaultImg from "@/static/default.png"
|
||||||
import unidialog from '@/components/dialog/dialog.vue'
|
import unidialog from '@/components/dialog/dialog.vue'
|
||||||
const groupUuid = ref('')
|
const groupUuid = ref('')
|
||||||
const groupName = ref('')
|
const groupName = ref('')
|
||||||
const members = ref([])
|
const members = ref([])
|
||||||
const visible = ref(false)
|
const visible = ref(false)
|
||||||
|
const avatarErrorMap = ref({})
|
||||||
|
const getAvatarKey = (member = {}) => String(member.uuid || member.id || member.realName || '')
|
||||||
|
const normalizeAvatarUrl = (photo) => {
|
||||||
|
const raw = String(photo || '').trim()
|
||||||
|
if (!raw) return defaultImg
|
||||||
|
if (/^https?:\/\//i.test(raw)) return raw
|
||||||
|
return `${docUrl}${raw}`
|
||||||
|
}
|
||||||
|
const getMemberAvatar = (member = {}) => {
|
||||||
|
const key = getAvatarKey(member)
|
||||||
|
if (key && avatarErrorMap.value[key]) return defaultImg
|
||||||
|
return normalizeAvatarUrl(member.photo)
|
||||||
|
}
|
||||||
|
const handleMemberAvatarError = (member) => {
|
||||||
|
const key = getAvatarKey(member)
|
||||||
|
if (!key) return
|
||||||
|
avatarErrorMap.value = {
|
||||||
|
...avatarErrorMap.value,
|
||||||
|
[key]: true
|
||||||
|
}
|
||||||
|
}
|
||||||
const confirmDelete = () => {
|
const confirmDelete = () => {
|
||||||
deleteGroup();
|
deleteGroup();
|
||||||
}
|
}
|
||||||
@@ -182,6 +208,7 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
const patientListByGroup = async () => {
|
const patientListByGroup = async () => {
|
||||||
|
avatarErrorMap.value = {}
|
||||||
const res = await api.patientListByGroup({
|
const res = await api.patientListByGroup({
|
||||||
group_uuid: groupUuid.value,
|
group_uuid: groupUuid.value,
|
||||||
list_sort:0
|
list_sort:0
|
||||||
@@ -194,19 +221,22 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.contentbox{
|
||||||
|
margin-top: calc(var(--status-bar-height) + 44px);
|
||||||
|
}
|
||||||
.group-edit-page{
|
.group-edit-page{
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
padding-bottom: 160rpx;
|
padding-bottom: 160rpx;
|
||||||
}
|
}
|
||||||
.save-text{
|
.save-text{
|
||||||
background:#8B2316;
|
color:#8B2316;
|
||||||
font-size: 30rpx;
|
font-size: 30rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 15rpx 25rpx;
|
padding: 15rpx 25rpx;
|
||||||
color:#fff;
|
|
||||||
border-radius: 12rpx;
|
border-radius: 12rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="group-manage-page">
|
<view class="group-manage-page">
|
||||||
<uni-nav-bar
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
left-icon="left"
|
left-icon="left"
|
||||||
title="分组管理"
|
title="分组管理"
|
||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eee"
|
backgroundColor="#eee"
|
||||||
>
|
>
|
||||||
@@ -14,8 +14,10 @@
|
|||||||
<view class="save-text" @click="saveGroups">保存</view>
|
<view class="save-text" @click="saveGroups">保存</view>
|
||||||
</template>
|
</template>
|
||||||
</uni-nav-bar>
|
</uni-nav-bar>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 已选中的分组 -->
|
<view class="content-box">
|
||||||
|
<!-- 已选中的分组 -->
|
||||||
<view class="selected-section">
|
<view class="selected-section">
|
||||||
<view class="tag-list">
|
<view class="tag-list">
|
||||||
<view
|
<view
|
||||||
@@ -30,7 +32,7 @@
|
|||||||
|
|
||||||
<!-- 所有分组 -->
|
<!-- 所有分组 -->
|
||||||
<view class="all-groups-section">
|
<view class="all-groups-section">
|
||||||
<view class="section-title">所有分组(选择分组)</view>
|
<view class="section-title"><text calss="red">所有分组</text>(选择分组)</view>
|
||||||
<view class="tag-list">
|
<view class="tag-list">
|
||||||
<view
|
<view
|
||||||
class="tag-item"
|
class="tag-item"
|
||||||
@@ -43,6 +45,7 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 底部添加按钮 -->
|
<!-- 底部添加按钮 -->
|
||||||
<view class="bottom-bar">
|
<view class="bottom-bar">
|
||||||
@@ -80,7 +83,9 @@ const loadAllGroups = async () => {
|
|||||||
try {
|
try {
|
||||||
const res = await api.groupList();
|
const res = await api.groupList();
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
allGroups.value = res.data || [];
|
const hiddenGroupNames = new Set(['待分组患者', '肝系一生非患教组', '肝系一生患教组']);
|
||||||
|
const arr = (res.data || []).filter((item) => !hiddenGroupNames.has(String(item?.name || '').trim()));
|
||||||
|
allGroups.value = arr;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("加载分组列表失败:", e);
|
console.error("加载分组列表失败:", e);
|
||||||
@@ -165,10 +170,20 @@ const saveGroups = () => {
|
|||||||
font-size: 30rpx;
|
font-size: 30rpx;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
.content-box{
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
bottom: 140rpx;
|
||||||
|
overflow-y: scroll;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
.selected-section {
|
.selected-section {
|
||||||
|
|
||||||
min-height: 300rpx;
|
min-height: 300rpx;
|
||||||
padding: 30rpx;
|
padding: 30rpx;
|
||||||
border-bottom: 1rpx solid #f0f0f0;
|
border-bottom: 20rpx solid #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.all-groups-section {
|
.all-groups-section {
|
||||||
@@ -176,9 +191,12 @@ const saveGroups = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.section-title {
|
.section-title {
|
||||||
font-size: 28rpx;
|
font-size: 30rpx;
|
||||||
color: #666;
|
color: #999;
|
||||||
margin-bottom: 20rpx;
|
margin-bottom: 20rpx;
|
||||||
|
.red{
|
||||||
|
color: #8b2316;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag-list {
|
.tag-list {
|
||||||
@@ -233,7 +251,7 @@ const saveGroups = () => {
|
|||||||
bottom: 0;
|
bottom: 0;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-top: 1rpx solid #f0f0f0;
|
border-top: 1rpx solid #f0f0f0;
|
||||||
padding: 20rpx 30rpx env(safe-area-inset-bottom);
|
padding: 20rpx 30rpx 20rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-btn {
|
.add-btn {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
fixed
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
height="180rpx"
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
/>
|
/>
|
||||||
|
|||||||
+239
-84
@@ -1,18 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="zhinan-list-page">
|
<view class="zhinan-list-page">
|
||||||
<!-- 头部导航栏 -->
|
<!-- 头部导航栏 -->
|
||||||
<uni-nav-bar
|
<!-- <uni-nav-bar
|
||||||
left-icon="left"
|
left-icon="left"
|
||||||
:title="title"
|
:title="title"
|
||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
fixed
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
height="180rpx"
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
>
|
>
|
||||||
|
|
||||||
</uni-nav-bar>
|
</uni-nav-bar> -->
|
||||||
|
<navBar :title="title" />
|
||||||
|
|
||||||
<!-- 使用scroll-view实现列表 -->
|
<!-- 使用scroll-view实现列表 -->
|
||||||
<scroll-view
|
<scroll-view
|
||||||
@@ -39,20 +40,17 @@
|
|||||||
<view class="item-date">{{ formatDate(item.releaseTime) }}</view>
|
<view class="item-date">{{ formatDate(item.releaseTime) }}</view>
|
||||||
<!-- 操作按钮 -->
|
<!-- 操作按钮 -->
|
||||||
<view class="item-action">
|
<view class="item-action">
|
||||||
<view
|
<view class="download-btn" @click.stop="downLoad(item)" v-if="!downLoadtaskList.includes(item.uuid)">
|
||||||
class="download-btn"
|
<!-- <up-icon name="download" color="#8D2316" size="28" ></up-icon> -->
|
||||||
@click.stop="viewGuideline(item)"
|
<up-image :src="downIng" width="35rpx" height="35rpx"></up-image>
|
||||||
>
|
<!-- <uni-icons type="arrow-down" size="26" color="#8D2316"></uni-icons> -->
|
||||||
<up-icon name="download" color="#8D2316" size="28"></up-icon>
|
</view>
|
||||||
</view>
|
<view
|
||||||
<!-- <view
|
v-else
|
||||||
v-else
|
class="view-btn"
|
||||||
class="view-btn"
|
@click.stop="viewGuideline(item)"
|
||||||
@click.stop="viewGuideline(item)"
|
>查看</view>
|
||||||
>
|
</view>
|
||||||
查看
|
|
||||||
</view> -->
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -73,22 +71,25 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 无数据提示 -->
|
<!-- 无数据提示 -->
|
||||||
<view class="no-data" v-if="guidelinesList.length === 0 && !isLoading">
|
<empty v-if="guidelinesList.length === 0 && !isLoading"></empty>
|
||||||
|
<!-- <view class="no-data" v-if="guidelinesList.length === 0 && !isLoading">
|
||||||
<uni-icons type="info" size="60" color="#999"></uni-icons>
|
<uni-icons type="info" size="60" color="#999"></uni-icons>
|
||||||
<text>暂无诊疗指南数据</text>
|
<text>暂无诊疗指南数据</text>
|
||||||
</view>
|
</view> -->
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted} from 'vue'
|
import { ref, onMounted,computed,nextTick} from 'vue'
|
||||||
import api from '@/api/api.js'
|
import api from '@/api/api.js'
|
||||||
import { onShow,onLoad } from "@dcloudio/uni-app";
|
import { onShow,onLoad } from "@dcloudio/uni-app";
|
||||||
import docUrl from "@/utils/docUrl.js"
|
import docUrl from "@/utils/docUrl.js"
|
||||||
import navTo from "@/utils/navTo.js"
|
import navTo from "@/utils/navTo.js"
|
||||||
import hotImg from "@/static/hot_booklist.png"
|
import hotImg from "@/static/hot_booklist.png"
|
||||||
|
import navBar from "@/components/navBar/navBar.vue"
|
||||||
|
import empty from "@/components/empty/empty.vue"
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const guidelinesList = ref([])
|
const guidelinesList = ref([])
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
@@ -99,6 +100,7 @@ const isRefreshing = ref(false)
|
|||||||
const keywords=ref('');
|
const keywords=ref('');
|
||||||
import upImg from "@/static/triangle_green_theme.png"
|
import upImg from "@/static/triangle_green_theme.png"
|
||||||
import downImg from "@/static/triangle_normal.png"
|
import downImg from "@/static/triangle_normal.png"
|
||||||
|
import downIng from "@/static/icon_library_down.png";
|
||||||
const loadMoreStatus = ref('more') // 'loading', 'more', 'noMore'
|
const loadMoreStatus = ref('more') // 'loading', 'more', 'noMore'
|
||||||
const typeUuid=ref('');
|
const typeUuid=ref('');
|
||||||
const title=ref('');
|
const title=ref('');
|
||||||
@@ -107,6 +109,12 @@ const from=ref('');
|
|||||||
const name=ref('');
|
const name=ref('');
|
||||||
const showInnerSort=ref(false);
|
const showInnerSort=ref(false);
|
||||||
const innerSortTitle=ref('上传时间');
|
const innerSortTitle=ref('上传时间');
|
||||||
|
import downloadStore from "@/store/downloadStoreFile.js";
|
||||||
|
import isAndroid from '@/utils/platform';
|
||||||
|
const downloadTasks=ref([]);
|
||||||
|
const downLoadtaskList=computed(()=>{
|
||||||
|
return downloadTasks.value.filter((item)=>item.status == "completed" && item.type == "zhinan").map((item)=>item.id);
|
||||||
|
});
|
||||||
const chooseInnerSort=(index)=>{
|
const chooseInnerSort=(index)=>{
|
||||||
sort.value=index;
|
sort.value=index;
|
||||||
if(index==1){
|
if(index==1){
|
||||||
@@ -144,12 +152,20 @@ const toggleInnerSort=()=>{
|
|||||||
showInnerSort.value=!showInnerSort.value;
|
showInnerSort.value=!showInnerSort.value;
|
||||||
}
|
}
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
|
syncTasksFromStore();
|
||||||
|
// 监听store变化
|
||||||
|
downloadStore.addListener((tasks) => {
|
||||||
|
downloadTasks.value = tasks;
|
||||||
|
|
||||||
|
});
|
||||||
|
// 恢复正在下载的任务
|
||||||
|
resumeDownloadingTasks();
|
||||||
// 页面显示时,如果列表为空则加载数据
|
// 页面显示时,如果列表为空则加载数据
|
||||||
if (guidelinesList.value.length === 0) {
|
if (guidelinesList.value.length === 0) {
|
||||||
if(from.value){
|
if(from.value){
|
||||||
top10ByType();
|
top10ByType();
|
||||||
}else{
|
}else{
|
||||||
loadGuidelinesList(true)
|
loadGuidelinesList(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -246,15 +262,16 @@ const loadGuidelinesList = async (isRefresh = false) => {
|
|||||||
try {
|
try {
|
||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
loadMoreStatus.value = 'loading'
|
loadMoreStatus.value = 'loading'
|
||||||
|
let expertUuid=uni.getStorageSync('userInfo').uuid;
|
||||||
const params = {
|
const params = {
|
||||||
page: currentPage.value,
|
page: currentPage.value,
|
||||||
pageSize: pageSize.value,
|
pageSize: pageSize.value,
|
||||||
|
expertUUid:expertUuid,
|
||||||
type: 1, // 诊疗指南类型
|
type: 1, // 诊疗指南类型
|
||||||
sort:2,
|
sort:2,
|
||||||
name:name.value,
|
name:name.value,
|
||||||
typeUuid:typeUuid.value,
|
typeUuid:typeUuid.value,
|
||||||
keywords:keywords.value
|
keyWords:keywords.value
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await api.searchLibraryU(params)
|
const res = await api.searchLibraryU(params)
|
||||||
@@ -272,7 +289,7 @@ const loadGuidelinesList = async (isRefresh = false) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否还有更多数据
|
// 判断是否还有更多数据
|
||||||
if (newData.length < pageSize.value) {
|
if (newData.length < res.data.pageSize) {
|
||||||
loadMoreStatus.value = 'noMore'
|
loadMoreStatus.value = 'noMore'
|
||||||
hasMoreData.value = false
|
hasMoreData.value = false
|
||||||
console.log('没有更多数据了');
|
console.log('没有更多数据了');
|
||||||
@@ -359,66 +376,94 @@ const downloadGuideline = (item) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const downLoad = (item) => {
|
||||||
|
if(!item.path){
|
||||||
|
uni.showToast({
|
||||||
|
title: "暂无下载链接",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uni.sendNativeEvent("portraitReport",{
|
||||||
|
msg:{
|
||||||
|
event_nickname: "magazine_donwload",
|
||||||
|
page_type: "诊疗指南",
|
||||||
|
resource_name:item.title,
|
||||||
|
belong:title.value,
|
||||||
|
number:1,
|
||||||
|
resource_option:item.tags
|
||||||
|
},
|
||||||
|
},
|
||||||
|
(ret) => {
|
||||||
|
console.log(ret);
|
||||||
|
});
|
||||||
|
addDownloadTask({
|
||||||
|
url: docUrl + item.path,
|
||||||
|
title: item.title,
|
||||||
|
id: item.uuid,
|
||||||
|
type: 'zhinan',
|
||||||
|
releaseTime: item.releaseTime,
|
||||||
|
});
|
||||||
|
};
|
||||||
// 查看指南(支持常用文档直链:pdf/doc/docx/xls/xlsx/ppt/pptx/txt)
|
// 查看指南(支持常用文档直链:pdf/doc/docx/xls/xlsx/ppt/pptx/txt)
|
||||||
const viewGuideline = (item) => {
|
const viewGuideline = (cell) => {
|
||||||
const url = docUrl+item.path
|
console.log(cell);
|
||||||
if (url) {
|
if (!cell.path) {
|
||||||
const isPDF = /\.(pdf)(\?|$)/i.test(url)
|
uni.showToast({
|
||||||
const isOffice = /\.(docx?|xlsx?|pptx?)(\?|$)/i.test(url)
|
title: "暂无下载链接",
|
||||||
const isText = /\.(txt)(\?|$)/i.test(url)
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('下载列表');
|
||||||
|
console.log(downloadTasks.value);
|
||||||
|
downloadTasks.value.forEach(item => {
|
||||||
|
if(item.id == cell.uuid) {
|
||||||
|
|
||||||
// H5 端
|
uni.sendNativeEvent("portraitReport",{
|
||||||
// #ifdef H5
|
msg:{
|
||||||
if (isPDF) {
|
event_nickname: "detail_page",
|
||||||
try { window.open(url, '_blank') } catch (e) {
|
page_type: "诊疗指南",
|
||||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
resource_name:cell.title,
|
||||||
}
|
resource_option:cell.tags
|
||||||
return
|
},
|
||||||
}
|
},
|
||||||
if (isOffice) {
|
(ret) => {
|
||||||
const officeUrl = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`
|
console.log(ret);
|
||||||
try { window.open(officeUrl, '_blank') } catch (e) {
|
});
|
||||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(officeUrl)}` })
|
// if(isAndroid){
|
||||||
}
|
plus.runtime.openFile(item.localPath, function(e) {
|
||||||
return
|
console.log('打开成功');
|
||||||
}
|
}, function(e) {
|
||||||
if (isText) {
|
uni.showToast({
|
||||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
title: '打开失败:' + e.message,
|
||||||
return
|
icon: "none",
|
||||||
}
|
duration: 2000,
|
||||||
// 其他格式统一用 webview 打开
|
});
|
||||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
console.log('打开失败:' + e.message);
|
||||||
return
|
});
|
||||||
// #endif
|
// }else{
|
||||||
|
// uni.sendNativeEvent('openDocument', {
|
||||||
// 非 H5 端:下载后尝试用 openDocument,失败回退 webview
|
// msg: item.localPath.replaceAll('_doc/uniapp_save/',''),
|
||||||
// #ifndef H5
|
// }, ret => {
|
||||||
uni.showToast({ title: '正在打开...', icon: 'none' })
|
// console.log(ret);
|
||||||
uni.downloadFile({
|
// });
|
||||||
url,
|
// }
|
||||||
success: (res) => {
|
// uni.openDocument({
|
||||||
if (res.statusCode === 200 && res.tempFilePath) {
|
// filePath: item.localPath,
|
||||||
uni.openDocument({
|
// fileType: 'pdf',
|
||||||
filePath: res.tempFilePath,
|
// success: () => console.log('打开成功'),
|
||||||
showMenu: true,
|
// fail: (err) => {
|
||||||
success: () => {},
|
// uni.showToast({
|
||||||
fail: () => {
|
// title: err,
|
||||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
// icon: "none",
|
||||||
}
|
// });
|
||||||
})
|
// }
|
||||||
} else {
|
// });
|
||||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
}
|
||||||
}
|
});
|
||||||
},
|
|
||||||
fail: () => {
|
|
||||||
uni.navigateTo({ url: `/pages_app/webview/webview?url=${encodeURIComponent(url)}` })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
// 无直链,回退到详情页
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,6 +508,116 @@ const formatDate = (dateString) => {
|
|||||||
return dateString
|
return dateString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 添加下载任务
|
||||||
|
const addDownloadTask = (item) => {
|
||||||
|
// 使用store添加任务
|
||||||
|
const taskIndex = downloadStore.addTask(item);
|
||||||
|
// 同步任务列表
|
||||||
|
syncTasksFromStore();
|
||||||
|
// 开始下载
|
||||||
|
startDownload(taskIndex);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 开始下载
|
||||||
|
const startDownload = (index) => {
|
||||||
|
const taskItem = downloadStore.getTask(index);
|
||||||
|
if (!taskItem) return;
|
||||||
|
if(taskItem.status == "loading"){
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
uni.showToast({
|
||||||
|
title: "正在下载中",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "loading"
|
||||||
|
});
|
||||||
|
|
||||||
|
const task = uni.downloadFile({
|
||||||
|
url: taskItem.url,
|
||||||
|
success: (res1) => {
|
||||||
|
//console.log("res1:"+JSON.stringify(res1));
|
||||||
|
if (res1.statusCode === 200) {
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "completed",
|
||||||
|
filePath: res1.tempFilePath,
|
||||||
|
});
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: "下载成功",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
uni.saveFile({
|
||||||
|
tempFilePath: res1.tempFilePath,
|
||||||
|
success: function (res2) {
|
||||||
|
console.log("res2:"+JSON.stringify(res2));
|
||||||
|
uni.getSavedFileInfo({
|
||||||
|
filePath: res2.savedFilePath,
|
||||||
|
success: function (res) {
|
||||||
|
console.log("res:"+JSON.stringify(res));
|
||||||
|
console.log("size:"+res.size);
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "completed",
|
||||||
|
localPath: res2.savedFilePath,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "failed",
|
||||||
|
});
|
||||||
|
uni.showToast({
|
||||||
|
title: "下载失败",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
status: "failed",
|
||||||
|
});
|
||||||
|
uni.showToast({
|
||||||
|
title: "下载失败: " + (err.errMsg || "未知错误"),
|
||||||
|
icon: "none",
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听下载进度
|
||||||
|
task.onProgressUpdate((update) => {
|
||||||
|
const currentTask = downloadStore.getTask(index);
|
||||||
|
if (currentTask && currentTask.status === "downloading") {
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
progress: update.progress
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 保存task对象到store(用于暂停/继续)
|
||||||
|
downloadStore.updateTask(index, {
|
||||||
|
task: task,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const syncTasksFromStore = () => {
|
||||||
|
downloadTasks.value = downloadStore.getTasks();
|
||||||
|
};
|
||||||
|
// 恢复正在下载的任务
|
||||||
|
const resumeDownloadingTasks = () => {
|
||||||
|
// 使用 nextTick 确保在页面渲染后再恢复下载任务
|
||||||
|
nextTick(() => {
|
||||||
|
downloadStore.resumeDownloadingTasks((index) => {
|
||||||
|
// 重新开始下载(uni.downloadFile不支持断点续传,所以从0开始)
|
||||||
|
console.log("恢复下载任务:", downloadStore.getTask(index)?.url);
|
||||||
|
startDownload(index);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -534,18 +689,18 @@ $white: #ffffff;
|
|||||||
|
|
||||||
.guidelines-scroll-view {
|
.guidelines-scroll-view {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 140rpx;
|
top: 180rpx;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
height: calc(100vh - 140rpx);
|
height: calc(100vh - 180rpx);
|
||||||
background-color: $bg-color;
|
background-color: $bg-color;
|
||||||
}
|
}
|
||||||
// 固定搜索容器
|
// 固定搜索容器
|
||||||
.search-container-fixed {
|
.search-container-fixed {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 140rpx; // 导航栏高度
|
top: 180rpx; // 导航栏高度
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 90;
|
z-index: 90;
|
||||||
|
|||||||
@@ -1,35 +1,63 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="bank-card-page">
|
<view class="bank-card-page">
|
||||||
<!-- 顶部导航栏 -->
|
<!-- 顶部导航栏 -->
|
||||||
<uni-nav-bar
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
left-icon="left"
|
left-icon="left"
|
||||||
title="常用银行卡"
|
title="常用银行卡"
|
||||||
@clickLeft="goBack()"
|
@clickLeft="goBack"
|
||||||
right-text="添加"
|
right-icon="plusempty"
|
||||||
|
right-icon-color="#8B2316"
|
||||||
@clickRight="addBankCard"
|
@clickRight="addBankCard"
|
||||||
fixed
|
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
>
|
>
|
||||||
</uni-nav-bar>
|
</uni-nav-bar>
|
||||||
|
|
||||||
|
</view>
|
||||||
<!-- 银行卡列表 -->
|
<!-- 银行卡列表 -->
|
||||||
<view class="card-list">
|
<view class="card-list">
|
||||||
<view class="card-item" v-for="(card, index) in bankCards" :key="card.uuid">
|
<uni-swipe-action>
|
||||||
<view class="card-logo">
|
<uni-swipe-action-item
|
||||||
<view class="logo-bg">
|
v-for="(card, index) in bankCards"
|
||||||
<text class="logo-text">{{ getBankLogo(card.open_bank) }}</text>
|
:key="card.uuid"
|
||||||
|
|
||||||
|
@change="onSwipeChange($event, card)"
|
||||||
|
>
|
||||||
|
<template v-slot:right>
|
||||||
|
<view class="swipe-right">
|
||||||
|
|
||||||
|
<view class="card-delete-btn" @click.stop="handleDeleteBankCard(card)">删除</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<view class="card-item" :class="{ 'is-swiping': openedSwipeUuid === card.uuid }">
|
||||||
|
<view class="card-logo">
|
||||||
|
<image
|
||||||
|
v-if="getBankLogoImg(card.open_bank)"
|
||||||
|
class="bank-logo-img"
|
||||||
|
:src="getBankLogoImg(card.open_bank)"
|
||||||
|
mode="aspectFit"
|
||||||
|
></image>
|
||||||
|
<view v-else class="logo-bg">
|
||||||
|
<text class="logo-text">{{ getBankLogo(card.open_bank) }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="card-info">
|
||||||
|
<view class="card-number">尾号{{ card.card_number }}储蓄卡</view>
|
||||||
|
<view class="bank-name">{{ card.open_bank }}</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</uni-swipe-action-item>
|
||||||
<view class="card-info">
|
</uni-swipe-action>
|
||||||
<view class="card-number">尾号{{ card.card_number }}储蓄卡</view>
|
|
||||||
<view class="bank-name">{{ card.open_bank }}</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
<empty v-if="bankCards.length === 0"></empty>
|
<view class="empty-container" v-if="bankCards.length === 0">
|
||||||
|
<image :src="emptyBankImg" class="empty-image"></image>
|
||||||
|
<text class="empty-text">使用常用卡,支付更快捷</text>
|
||||||
|
</view>
|
||||||
|
<!-- <empty v-if="bankCards.length === 0" :imgWidth="'218rpx'" :imgHeight="'164rpx'" :emptyImage="emptyBankImg" emptyDesc="使用常用卡,支付更快捷"></empty> -->
|
||||||
|
|
||||||
<!-- 底部导航指示器 -->
|
<!-- 底部导航指示器 -->
|
||||||
<view class="bottom-indicator"></view>
|
<view class="bottom-indicator"></view>
|
||||||
@@ -41,27 +69,127 @@ import { ref, onMounted } from 'vue';
|
|||||||
import navTo from '@/utils/navTo';
|
import navTo from '@/utils/navTo';
|
||||||
import api from '@/api/api';
|
import api from '@/api/api';
|
||||||
import empty from "@/components/empty/empty.vue"
|
import empty from "@/components/empty/empty.vue"
|
||||||
|
import emptyBankImg from "@/static/empty_bank.png"
|
||||||
const bankCards = ref([]);
|
const bankCards = ref([]);
|
||||||
|
const openedSwipeUuid = ref('');
|
||||||
|
import { onLoad,onBackPress,onShow } from '@dcloudio/uni-app';
|
||||||
|
const from = ref('');
|
||||||
|
const returnTo = ref('');
|
||||||
|
onLoad((options) => {
|
||||||
|
if(options.from){
|
||||||
|
from.value = options.from;
|
||||||
|
}
|
||||||
|
if (options.returnTo) {
|
||||||
|
returnTo.value = decodeURIComponent(options.returnTo);
|
||||||
|
}
|
||||||
|
uni.sendNativeEvent("portraitReport",{
|
||||||
|
msg:{
|
||||||
|
event_nickname: "list_page",
|
||||||
|
page_type: "常用银行卡",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
onShow(() => {
|
||||||
|
getBankCardList();
|
||||||
|
});
|
||||||
|
onBackPress(() => {
|
||||||
|
if(!from.value){
|
||||||
|
plus.runtime.quit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
// 银行卡数据
|
// 银行卡数据
|
||||||
const getBankCardList = () => {
|
const getBankCardList = () => {
|
||||||
api.bankCardList({}).then(res => {
|
api.bankCardList({}).then(res => {
|
||||||
if (res.code === 200 && res.data.bankList) {
|
|
||||||
bankCards.value = res.data.bankList;
|
if (res.code === 200 && res.data) {
|
||||||
|
bankCards.value = res.data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
uni.navigateBack();
|
if(!from.value){
|
||||||
|
plus.runtime.quit();
|
||||||
|
}else{
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const addBankCard = () => {
|
const addBankCard = () => {
|
||||||
|
const target = returnTo.value
|
||||||
|
? `/pages_app/idcardAuth/idcardAuth?returnTo=${encodeURIComponent(returnTo.value)}`
|
||||||
|
: '/pages_app/idcardAuth/idcardAuth';
|
||||||
navTo({
|
navTo({
|
||||||
url: '/pages_app/idcardAuth/idcardAuth'
|
url: target
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const bankLogoMap = {
|
||||||
|
'工商银行': '/static/icon_bankcard_gongshang.png',
|
||||||
|
'中国银行': '/static/icon_bankcard_zhongguo.png',
|
||||||
|
'建设银行': '/static/icon_bankcard_jianseyinhang.png',
|
||||||
|
'农业银行': '/static/icon_bankcard_nongyeyinhang.png',
|
||||||
|
'交通银行': '/static/icon_bankcard_jiatong.png',
|
||||||
|
'招商银行': '/static/icon_bankcard_zhaoshangyinhang.png',
|
||||||
|
'民生银行': '/static/icon_bankcard_minshneg.png',
|
||||||
|
'兴业银行': '/static/icon_bankcard_xingye.png',
|
||||||
|
'浦发银行': '/static/icon_bankcard_shanghaipudongfazhanyinhang.png',
|
||||||
|
'光大银行': '/static/icon_bankcard_guangda.png',
|
||||||
|
'华夏银行': '/static/icon_bankcard_huaxiayinhnag.png',
|
||||||
|
'中信银行': '/static/icon_bankcard_zhongxinshiye.png',
|
||||||
|
'平安银行': '/static/icon_bankcard_pingan.png',
|
||||||
|
'广发银行': '/static/icon_bankcard_guangfa.png',
|
||||||
|
'邮储银行': '/static/icon_bankcard_youzheng.png',
|
||||||
|
'上海银行': '/static/icon_bankcard_shanghai.png',
|
||||||
|
'北京银行': '/static/icon_bankcard_beijingyinhang.png'
|
||||||
|
};
|
||||||
|
|
||||||
|
const getBankLogoImg = (bankName) => {
|
||||||
|
let name1=bankName.split(',')[0];
|
||||||
|
let name2=bankName.split(',')[1];
|
||||||
|
return bankLogoMap[name1] || bankLogoMap[name2];
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteBankCard = (card) => {
|
||||||
|
uni.showModal({
|
||||||
|
title: '确认删除',
|
||||||
|
content: `确定删除尾号${card.card_number}的银行卡吗?`,
|
||||||
|
success: async (modalRes) => {
|
||||||
|
if (!modalRes.confirm) return;
|
||||||
|
try {
|
||||||
|
const res = await api.deleteBankCard({
|
||||||
|
uuid: card.uuid
|
||||||
|
});
|
||||||
|
if (res.code === 200) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '删除成功',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
getBankCardList();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uni.showToast({
|
||||||
|
title: res.msg || '删除失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '网络错误,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSwipeChange = (e, card) => {
|
||||||
|
const state = typeof e === 'string'
|
||||||
|
? e
|
||||||
|
: e?.position || e?.show || e?.detail?.position || e?.detail?.show || 'none';
|
||||||
|
openedSwipeUuid.value = state === 'right' ? card.uuid : '';
|
||||||
|
};
|
||||||
|
|
||||||
// 获取银行logo文字
|
// 获取银行logo文字
|
||||||
const getBankLogo = (bankName) => {
|
const getBankLogo = (bankName) => {
|
||||||
const bankLogos = {
|
const bankLogos = {
|
||||||
@@ -84,33 +212,95 @@ const getBankLogo = (bankName) => {
|
|||||||
return bankLogos[bankName] || bankName.charAt(0);
|
return bankLogos[bankName] || bankName.charAt(0);
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getBankCardList();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.empty-container {
|
||||||
|
height:800rpx;
|
||||||
|
min-width:600rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
.empty-image {
|
||||||
|
width: 218rpx;
|
||||||
|
height: 164rpx;
|
||||||
|
}
|
||||||
|
.empty-text {
|
||||||
|
margin-top: 20rpx;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
.bank-card-page {
|
.bank-card-page {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background: #F5F5F5;
|
background: #F5F5F5;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
:deep(.uni-nav-bar-right-text) {
|
||||||
|
font-size: 32rpx;
|
||||||
|
}
|
||||||
|
:deep(.uni-swipe){
|
||||||
|
margin-bottom: 20rpx!important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 银行卡列表样式 */
|
/* 银行卡列表样式 */
|
||||||
.card-list {
|
.card-list {
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0rpx;
|
||||||
|
overflow-y: scroll;
|
||||||
|
z-index: 1;
|
||||||
padding: 30rpx;
|
padding: 30rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.swipe-right {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
padding-right: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-delete-btn {
|
||||||
|
min-width: 112rpx;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 24rpx;
|
||||||
|
border-radius: 0 16rpx 16rpx 0;
|
||||||
|
background: #E60012;
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
.card-item {
|
.card-item {
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
border-radius: 16rpx;
|
border-radius: 16rpx;
|
||||||
padding: 30rpx;
|
padding: 30rpx;
|
||||||
margin-bottom: 20rpx;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
&.is-swiping {
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.card-logo {
|
.card-logo {
|
||||||
margin-right: 30rpx;
|
margin-right: 30rpx;
|
||||||
|
|
||||||
|
.bank-logo-img {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
.logo-bg {
|
.logo-bg {
|
||||||
width: 80rpx;
|
width: 80rpx;
|
||||||
@@ -145,6 +335,7 @@ onMounted(() => {
|
|||||||
color: #666666;
|
color: #666666;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="idcard-auth-page">
|
<view class="idcard-auth-page">
|
||||||
<!-- 顶部导航栏 -->
|
<!-- 顶部导航栏 -->
|
||||||
<uni-nav-bar
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
left-icon="left"
|
left-icon="left"
|
||||||
:title="currentStep === 1 ? '身份验证' : '添加银行卡'"
|
:title="currentStep === 1 ? '身份验证' : '添加银行卡'"
|
||||||
@clickLeft="goBack()"
|
@clickLeft="goBack"
|
||||||
fixed
|
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
>
|
>
|
||||||
</uni-nav-bar>
|
</uni-nav-bar>
|
||||||
|
</view>
|
||||||
<!-- 内容区域 -->
|
<!-- 内容区域 -->
|
||||||
<view class="content-area">
|
<view class="content-area">
|
||||||
<!-- 进度指示器 -->
|
<!-- 进度指示器 -->
|
||||||
@@ -65,6 +68,7 @@
|
|||||||
class="form-input"
|
class="form-input"
|
||||||
placeholder="请输入您的姓名"
|
placeholder="请输入您的姓名"
|
||||||
v-model="formData.name"
|
v-model="formData.name"
|
||||||
|
:adjust-position="false"
|
||||||
placeholder-style="color: #cccccc"
|
placeholder-style="color: #cccccc"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
@@ -73,6 +77,7 @@
|
|||||||
<input
|
<input
|
||||||
class="form-input"
|
class="form-input"
|
||||||
placeholder="请输入您的身份证号"
|
placeholder="请输入您的身份证号"
|
||||||
|
:adjust-position="false"
|
||||||
v-model="formData.idNumber"
|
v-model="formData.idNumber"
|
||||||
placeholder-style="color: #cccccc"
|
placeholder-style="color: #cccccc"
|
||||||
/>
|
/>
|
||||||
@@ -85,28 +90,34 @@
|
|||||||
<text class="form-label">银行卡号</text>
|
<text class="form-label">银行卡号</text>
|
||||||
<view class="input-container">
|
<view class="input-container">
|
||||||
<input
|
<input
|
||||||
class="form-input"
|
class="form-input card-number-input"
|
||||||
|
:class="{ 'is-filled': !!formData.cardNumber }"
|
||||||
placeholder="仅限借记卡"
|
placeholder="仅限借记卡"
|
||||||
v-model="formData.cardNumber"
|
:value="cardNumberDisplay"
|
||||||
|
:adjust-position="false"
|
||||||
|
@input="onCardNumberInput"
|
||||||
placeholder-style="color: #cccccc"
|
placeholder-style="color: #cccccc"
|
||||||
/>
|
/>
|
||||||
<view class="info-icon">
|
|
||||||
|
</view>
|
||||||
|
<view class="info-icon" @click="showInfo('card')">
|
||||||
<text class="icon-text">!</text>
|
<text class="icon-text">!</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="form-item">
|
<view class="form-item">
|
||||||
<text class="form-label">手机号</text>
|
<text class="form-label">手机号</text>
|
||||||
<view class="input-container">
|
<view class="input-container">
|
||||||
<input
|
<input
|
||||||
class="form-input"
|
class="form-input card-number-input"
|
||||||
placeholder="银行预留手机号"
|
placeholder="银行预留手机号"
|
||||||
v-model="formData.mobile"
|
v-model="formData.mobile"
|
||||||
|
:adjust-position="false"
|
||||||
placeholder-style="color: #cccccc"
|
placeholder-style="color: #cccccc"
|
||||||
/>
|
/>
|
||||||
<view class="info-icon">
|
|
||||||
|
</view>
|
||||||
|
<view class="info-icon" @click="showInfo('phone')">
|
||||||
<text class="icon-text">!</text>
|
<text class="icon-text">!</text>
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -145,6 +156,18 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<unidialog
|
||||||
|
:visible="cardVisible"
|
||||||
|
:showCancel="false"
|
||||||
|
:title="cardTitle"
|
||||||
|
:content="cardContent"
|
||||||
|
:showConfirm="true"
|
||||||
|
:confirmText="'知道了'"
|
||||||
|
@close="cardVisible=false"
|
||||||
|
@confirm="cardVisible=false"
|
||||||
|
>
|
||||||
|
|
||||||
|
</unidialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -153,7 +176,11 @@ import stepImg from "@/static/add_card_no.png"
|
|||||||
import stepActiveImg from "@/static/add_card_yes.png"
|
import stepActiveImg from "@/static/add_card_yes.png"
|
||||||
import navTo from '@/utils/navTo';
|
import navTo from '@/utils/navTo';
|
||||||
import api from '@/api/api';
|
import api from '@/api/api';
|
||||||
|
import unidialog from '@/components/dialog/dialog.vue';
|
||||||
|
import { onLoad } from '@dcloudio/uni-app';
|
||||||
|
const cardContent = ref('暂支持以下银行:农业银行、建设银行、光大银行、平安银行、兴业银行、中信银行、邮政储蓄银行、民生银行、中国银行、工商银行、交通银行、浦发银行、广发银行、华夏银行、招商银行、北京银行、上海银行。');
|
||||||
|
const cardTitle = ref('银行卡说明');
|
||||||
|
const cardVisible = ref(false);
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
name: '',
|
name: '',
|
||||||
idNumber: '',
|
idNumber: '',
|
||||||
@@ -163,13 +190,29 @@ const formData = ref({
|
|||||||
|
|
||||||
const isLoading = ref(false);
|
const isLoading = ref(false);
|
||||||
const currentStep = ref(1); // 当前步骤,1表示身份信息,2表示添加银行卡
|
const currentStep = ref(1); // 当前步骤,1表示身份信息,2表示添加银行卡
|
||||||
|
const showInfo = (type) => {
|
||||||
|
if (type === 'card') {
|
||||||
|
cardTitle.value = '银行卡说明';
|
||||||
|
cardContent.value = '暂支持以下银行:农业银行、建设银行、光大银行、平安银行、兴业银行、中信银行、邮政储蓄银行、民生银行、中国银行、工商银行、交通银行、浦发银行、广发银行、华夏银行、招商银行、北京银行、上海银行。';
|
||||||
|
} else if (type === 'phone') {
|
||||||
|
cardTitle.value = '手机号说明';
|
||||||
|
cardContent.value = '银行预留的手机号码是办理银行卡时所填写的手机号码。没有预留,手机号码已经忘记或者已经停用,请联系银行客服更新处理';
|
||||||
|
}
|
||||||
|
cardVisible.value = true;
|
||||||
|
};
|
||||||
// 短信弹框相关
|
// 短信弹框相关
|
||||||
const showSmsDialog = ref(false);
|
const showSmsDialog = ref(false);
|
||||||
const smsCode = ref('');
|
const smsCode = ref('');
|
||||||
const sendingCode = ref(false);
|
const sendingCode = ref(false);
|
||||||
const countdown = ref(0);
|
const countdown = ref(0);
|
||||||
let countdownTimer = null;
|
let countdownTimer = null;
|
||||||
|
const returnTo = ref('');
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
if (options.returnTo) {
|
||||||
|
returnTo.value = decodeURIComponent(options.returnTo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const maskedMobile = computed(() => {
|
const maskedMobile = computed(() => {
|
||||||
const m = formData.value.mobile || '';
|
const m = formData.value.mobile || '';
|
||||||
@@ -178,6 +221,18 @@ const maskedMobile = computed(() => {
|
|||||||
}
|
}
|
||||||
return m || '***********';
|
return m || '***********';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const formatCardNumber = (value) => {
|
||||||
|
const digits = String(value || '').replace(/\D/g, '').slice(0, 19);
|
||||||
|
return digits.replace(/(\d{4})(?=\d)/g, '$1 ');
|
||||||
|
};
|
||||||
|
|
||||||
|
const cardNumberDisplay = computed(() => formatCardNumber(formData.value.cardNumber));
|
||||||
|
|
||||||
|
const onCardNumberInput = (e) => {
|
||||||
|
const value = e?.detail?.value || '';
|
||||||
|
formData.value.cardNumber = String(value).replace(/\D/g, '').slice(0, 19);
|
||||||
|
};
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
uni.navigateBack();
|
uni.navigateBack();
|
||||||
};
|
};
|
||||||
@@ -246,7 +301,7 @@ const onNextStep = async () => {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('身份验证失败:', error);
|
console.error('身份验证失败:', error);
|
||||||
uni.showToast({ title: '网络错误,请重试', icon: 'none' });
|
uni.showToast({ title: error.data.message || error.message, icon: 'none' });
|
||||||
isLoading.value = false;
|
isLoading.value = false;
|
||||||
}
|
}
|
||||||
} else if (currentStep.value === 2) {
|
} else if (currentStep.value === 2) {
|
||||||
@@ -296,7 +351,9 @@ const onGetSmsCode = async () => {
|
|||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({ title: res.msg || '短信验证码发送失败', icon: 'none' });
|
uni.showToast({
|
||||||
|
title: res.msg || res.data.message, icon: 'none'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -315,9 +372,16 @@ const onConfirmSms = async () => {
|
|||||||
});
|
});
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
uni.showToast({ title: '银行卡添加成功', icon: 'none' });
|
uni.showToast({ title: '银行卡添加成功', icon: 'none' });
|
||||||
navTo({
|
uni.navigateBack();
|
||||||
url: '/pages_app/idcardAuth/bankCardList'
|
// if (returnTo.value) {
|
||||||
});
|
// uni.redirectTo({
|
||||||
|
// url: returnTo.value
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// navTo({
|
||||||
|
// url: '/pages_app/idcardAuth/bankCardList'
|
||||||
|
// });
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({ title: res.msg || '银行卡添加失败', icon: 'none' });
|
uni.showToast({ title: res.msg || '银行卡添加失败', icon: 'none' });
|
||||||
}
|
}
|
||||||
@@ -332,12 +396,17 @@ const onCancelSms = () => {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.idcard-auth-page {
|
.idcard-auth-page {
|
||||||
min-height: 100vh;
|
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-area {
|
.content-area {
|
||||||
padding-top: 160rpx;
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
overflow-y: scroll;
|
||||||
|
z-index: 1;
|
||||||
padding: 0rpx 0rpx 0;
|
padding: 0rpx 0rpx 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,78 +524,98 @@ const onCancelSms = () => {
|
|||||||
|
|
||||||
|
|
||||||
.form-item {
|
.form-item {
|
||||||
margin-bottom: 30rpx;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
border-bottom: 2rpx solid #eee;
|
border-bottom: 2rpx solid #eee;
|
||||||
padding: 0 30rpx 20rpx;
|
height: 92rpx;
|
||||||
|
padding: 0 30rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-label {
|
.form-label {
|
||||||
display: block;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
height: 80rpx;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
width: 120rpx;
|
width: 120rpx;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
text-align: right;
|
||||||
|
text-align-last: auto;
|
||||||
|
letter-spacing: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-right: 10rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-input {
|
.form-input {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 80rpx;
|
height: 80rpx;
|
||||||
|
min-height: 80rpx;
|
||||||
|
line-height: 80rpx;
|
||||||
padding: 0 20rpx;
|
padding: 0 20rpx;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
border-color: #8B2316;
|
border-color: #8B2316;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.info-icon {
|
||||||
|
position: absolute;
|
||||||
|
right: 30rpx;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 2rpx solid #8B2316;
|
||||||
|
|
||||||
|
.icon-text {
|
||||||
|
font-size: 20rpx;
|
||||||
|
color: #8B2316;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
.input-container {
|
.input-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 80%;
|
height: 80rpx;
|
||||||
|
flex: 1;
|
||||||
|
padding-right: 56rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
.form-input {
|
.form-input {
|
||||||
flex: 9;
|
flex: 1;
|
||||||
height: 80rpx;
|
height: 100%;
|
||||||
padding: 0 20rpx;
|
min-height: 100%;
|
||||||
|
line-height: 80rpx;
|
||||||
|
padding: 0;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
outline: none;
|
outline: none;
|
||||||
|
box-sizing: border-box;
|
||||||
&:focus {
|
|
||||||
/* 去除边框后无需变更边框颜色 */
|
&.card-number-input.is-filled {
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-icon {
|
|
||||||
flex:1;
|
|
||||||
position: absolute;
|
|
||||||
right: 20rpx;
|
|
||||||
width: 40rpx;
|
|
||||||
height: 40rpx;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: #f0f0f0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
.icon-text {
|
|
||||||
font-size: 20rpx;
|
|
||||||
color: #cccccc;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -644,6 +733,10 @@ const onCancelSms = () => {
|
|||||||
background: #eeeeee;
|
background: #eeeeee;
|
||||||
color: #8B2316;
|
color: #8B2316;
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sms-actions {
|
.sms-actions {
|
||||||
|
|||||||
+1177
-1057
File diff suppressed because it is too large
Load Diff
+65
-32
@@ -11,14 +11,14 @@
|
|||||||
<up-image :src="logo" width="164rpx" height="167rpx" ></up-image>
|
<up-image :src="logo" width="164rpx" height="167rpx" ></up-image>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
<text class="app-name">专家端</text>
|
<text class="app-name">专家版</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 手机号显示 -->
|
<!-- 手机号显示 -->
|
||||||
<!-- #ifdef APP -->
|
<!-- #ifdef APP -->
|
||||||
<view class="phone-display">
|
<!-- <view class="phone-display">
|
||||||
<text class="phone-number">176****8628</text>
|
<text class="phone-number">176****8628</text>
|
||||||
</view>
|
</view> -->
|
||||||
|
|
||||||
<!-- 登录按钮 -->
|
<!-- 登录按钮 -->
|
||||||
<view class="login-button" @click="onOneClickLogin">
|
<view class="login-button" @click="onOneClickLogin">
|
||||||
@@ -129,34 +129,16 @@
|
|||||||
};
|
};
|
||||||
// 一键登录
|
// 一键登录
|
||||||
const onOneClickLogin = () => {
|
const onOneClickLogin = () => {
|
||||||
if (!isAgreed.value) {
|
const res = checkUniverifyLogin()
|
||||||
uni.showToast({
|
if(res){
|
||||||
title: '请先同意相关协议',
|
uni.redirectTo({
|
||||||
icon: 'none'
|
url: '/pages/univerify/univerify'
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
uni.redirectTo({
|
||||||
|
url: '/pages_app/smsLogin/smsLogin'
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('一键登录');
|
|
||||||
uni.showLoading({
|
|
||||||
title: '登录中2...'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 模拟登录过程
|
|
||||||
setTimeout(() => {
|
|
||||||
uni.hideLoading();
|
|
||||||
uni.showToast({
|
|
||||||
title: '登录成功',
|
|
||||||
icon: 'none'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 跳转到首页
|
|
||||||
setTimeout(() => {
|
|
||||||
uni.switchTab({
|
|
||||||
url: '/pages/index/index'
|
|
||||||
});
|
|
||||||
}, 1500);
|
|
||||||
}, 2000);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 短信验证码登录
|
// 短信验证码登录
|
||||||
@@ -179,7 +161,7 @@
|
|||||||
|
|
||||||
// #ifdef APP
|
// #ifdef APP
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '微信登录 11',
|
title: '微信登录',
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
});
|
});
|
||||||
// #endif
|
// #endif
|
||||||
@@ -235,9 +217,10 @@
|
|||||||
uni.setStorageSync('DEV_AUTH_YX_TOKEN_App', res.data.YX_token);
|
uni.setStorageSync('DEV_AUTH_YX_TOKEN_App', res.data.YX_token);
|
||||||
uni.setStorageSync('userInfo', res.data);
|
uni.setStorageSync('userInfo', res.data);
|
||||||
}
|
}
|
||||||
|
const app = getApp()
|
||||||
|
//app.initNim({appkey: "885dea390870814acf3ba8558c717572", account:result.data.YX_accid, token: result.data.YX_token })
|
||||||
// 跳转到首页
|
// 跳转到首页
|
||||||
navTo({
|
uni.redirectTo({
|
||||||
url: '/pages/index/index'
|
url: '/pages/index/index'
|
||||||
})
|
})
|
||||||
}).catch(err=>{
|
}).catch(err=>{
|
||||||
@@ -339,11 +322,61 @@
|
|||||||
url:'/pages/index/index'
|
url:'/pages/index/index'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const univerify = ref(1)
|
||||||
// 页面加载
|
// 页面加载
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
console.log('登录页面加载完成');
|
console.log('登录页面加载完成');
|
||||||
|
onLoad((options) => {
|
||||||
|
if(options.univerify){
|
||||||
|
univerify.value = options.univerify // 已支持 App-Plus
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const res = checkUniverifyLogin()
|
||||||
|
if(res){
|
||||||
|
uni.redirectTo({
|
||||||
|
url: '/pages/univerify/univerify'
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
uni.redirectTo({
|
||||||
|
url: '/pages_app/smsLogin/smsLogin'
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const checkUniverifyLogin=()=>{
|
||||||
|
let res = false
|
||||||
|
// #ifdef APP
|
||||||
|
uni.getProvider({
|
||||||
|
service: 'oauth',
|
||||||
|
success: function (res) {
|
||||||
|
console.log(res.provider)// ['qq', 'univerify']
|
||||||
|
if(res.provider.indexOf('univerify') !== -1){
|
||||||
|
uni.preLogin({
|
||||||
|
provider: 'univerify',
|
||||||
|
success(){ //预登录成功
|
||||||
|
// 显示一键登录选项
|
||||||
|
if(univerify.value == 1){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail(res){ // 预登录失败
|
||||||
|
// 不显示一键登录选项(或置灰)
|
||||||
|
// 根据错误信息判断失败原因,如有需要可将错误提交给统计服务器
|
||||||
|
console.log(res.errCode)
|
||||||
|
console.log(res.errMsg)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
// 页面显示
|
// 页面显示
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
// #ifdef APP
|
// #ifdef APP
|
||||||
|
|||||||
@@ -0,0 +1,582 @@
|
|||||||
|
<template>
|
||||||
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
|
left-icon="left"
|
||||||
|
title="过往会议"
|
||||||
|
@clickLeft="goBack"
|
||||||
|
color="#8B2316"
|
||||||
|
:border="false"
|
||||||
|
backgroundColor="#eee"
|
||||||
|
>
|
||||||
|
<template #right>
|
||||||
|
<view class="nav-right">
|
||||||
|
<uni-icons type="search" size="24" color="#8B2316" @click="searchMeetHistroy"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</uni-nav-bar>
|
||||||
|
</view>
|
||||||
|
<view class="page">
|
||||||
|
<!-- 筛选标签栏 -->
|
||||||
|
<view class="filter-bar">
|
||||||
|
<view class="filter-item" :class="{active:monthName}" @click="showTimePopup">
|
||||||
|
<text>{{ monthName?monthName:'会议年份' }}</text>
|
||||||
|
<up-image :src="monthName?selectOn:select" width="26rpx" height="26rpx"></up-image>
|
||||||
|
</view>
|
||||||
|
<view class="filter-divider"></view>
|
||||||
|
<view class="filter-item" :class="{active:typeName}" @click="showLocationPopup">
|
||||||
|
<text>{{ typeName?typeName:'会议月份' }}</text>
|
||||||
|
<up-image :src="typeName?selectOn:select" width="26rpx" height="26rpx"></up-image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 可滚动内容区域 -->
|
||||||
|
<scroll-view
|
||||||
|
class="scroll-content"
|
||||||
|
scroll-y="true"
|
||||||
|
refresher-enabled="true"
|
||||||
|
:refresher-triggered="isRefreshing"
|
||||||
|
:refresher-threshold="100"
|
||||||
|
@refresherrefresh="onRefresh"
|
||||||
|
@scrolltolower="onLoadMore"
|
||||||
|
:lower-threshold="100"
|
||||||
|
>
|
||||||
|
<!-- 会议列表 -->
|
||||||
|
<view class="meeting-list" v-if="meetingList.length > 0">
|
||||||
|
<view
|
||||||
|
class="meeting-item" @click="goDetail(meeting)"
|
||||||
|
v-for="(meeting, index) in meetingList"
|
||||||
|
:key="meeting.id || index"
|
||||||
|
>
|
||||||
|
<view class="meeting-content">
|
||||||
|
<text class="meeting-title">{{
|
||||||
|
meeting.title || meeting.name
|
||||||
|
}}</text>
|
||||||
|
<view class="meeting-info">
|
||||||
|
<view class="meeting-time">
|
||||||
|
<view class="timebox">
|
||||||
|
<up-image
|
||||||
|
:src="timeImg"
|
||||||
|
width="24rpx"
|
||||||
|
height="24rpx"
|
||||||
|
></up-image>
|
||||||
|
</view>
|
||||||
|
<view class="text"> {{ formatDate(meeting.begin_date) }}</view>
|
||||||
|
</view>
|
||||||
|
<view class="meeting-location">
|
||||||
|
<uni-icons type="location" size="14" color="#999"></uni-icons>
|
||||||
|
{{ meeting.location }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<view class="empty-state" v-else-if="!isRefreshing">
|
||||||
|
<empty></empty>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 加载更多提示 -->
|
||||||
|
<view class="load-more" v-if="showLoadMore">
|
||||||
|
<view class="load-more-content" v-if="isLoadingMore">
|
||||||
|
<uni-icons type="spinner-cycle" size="20" color="#999"></uni-icons>
|
||||||
|
<text class="load-more-text">加载中...</text>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="load-more-content"
|
||||||
|
v-else-if="hasMoreData && meetingList.length > 0"
|
||||||
|
>
|
||||||
|
<text class="load-more-text">上拉加载更多</text>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="load-more-content"
|
||||||
|
v-else-if="meetingList.length > 0 && !isLoadingMore"
|
||||||
|
>
|
||||||
|
<text class="load-more-text">没有更多数据了</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 时间选择弹窗 -->
|
||||||
|
<view class="time-popup" v-if="isTimePopupShow" @click="hideTimePopup">
|
||||||
|
<view class="popup-mask"></view>
|
||||||
|
<view class="time-popup-content" @click.stop>
|
||||||
|
<view class="time-list">
|
||||||
|
<view
|
||||||
|
class="time-item"
|
||||||
|
v-for="(month, index) in monthList"
|
||||||
|
:key="index"
|
||||||
|
:class="{ active: selectedMonth === month.value }"
|
||||||
|
@click="selectMonth(month)"
|
||||||
|
>
|
||||||
|
<text>{{ month.label }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 地区选择弹窗 -->
|
||||||
|
<view
|
||||||
|
class="time-popup"
|
||||||
|
v-if="isLocationPopupShow"
|
||||||
|
@click="hideLocationPopup"
|
||||||
|
>
|
||||||
|
<view class="popup-mask"></view>
|
||||||
|
<view class="time-popup-content" @click.stop>
|
||||||
|
<view class="time-list">
|
||||||
|
<view
|
||||||
|
class="time-item"
|
||||||
|
v-for="(location, index) in locationList"
|
||||||
|
:key="index"
|
||||||
|
:class="{ active: selectedType === location.code }"
|
||||||
|
@click="selectLocation(location)"
|
||||||
|
>
|
||||||
|
<text>{{ location.name }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
import { onShow,onLoad,onHide} from "@dcloudio/uni-app";
|
||||||
|
import api from "@/api/api.js";
|
||||||
|
import navBar from "@/components/navBar/navBar.vue";
|
||||||
|
import select from "@/static/triangle_normal.png";
|
||||||
|
import selectOn from "@/static/triangle_green_theme.png"
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import timeImg from "@/static/play_long.png"
|
||||||
|
import navTo from "@/utils/navTo";
|
||||||
|
import empty from '@/components/empty/empty.vue';
|
||||||
|
// 弹窗状态
|
||||||
|
const isTimePopupShow = ref(false);
|
||||||
|
const isLocationPopupShow = ref(false);
|
||||||
|
const selectedMonth = ref("");
|
||||||
|
const monthName = ref("");
|
||||||
|
const selectedType = ref("");
|
||||||
|
const typeName = ref("");
|
||||||
|
// 下拉刷新和上拉加载状态
|
||||||
|
const isRefreshing = ref(false);
|
||||||
|
const isLoadingMore = ref(false);
|
||||||
|
const hasMoreData = ref(true);
|
||||||
|
const showLoadMore = ref(true);
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
|
||||||
|
// 会议列表数据
|
||||||
|
const meetingList = ref([]);
|
||||||
|
const goBack=()=>{
|
||||||
|
uni.navigateBack({
|
||||||
|
fail:()=>{
|
||||||
|
uni.redirectTo({
|
||||||
|
url:'/pages/index/index'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
onShow(() => {
|
||||||
|
|
||||||
|
});
|
||||||
|
onHide(() => {
|
||||||
|
|
||||||
|
});
|
||||||
|
// 年份数据
|
||||||
|
const monthList = ref([]);
|
||||||
|
const generateYearList = () => {
|
||||||
|
const years = [];
|
||||||
|
const currentDate = new Date();
|
||||||
|
const currentYear = currentDate.getFullYear();
|
||||||
|
// 从今年到过去10年
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
const year = currentYear - i;
|
||||||
|
years.push({
|
||||||
|
value: year.toString(),
|
||||||
|
label: `${year}年`,
|
||||||
|
year: year,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
monthList.value = years;
|
||||||
|
console.log("生成年份列表:", monthList.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 月份数据
|
||||||
|
const locationList = ref([]);
|
||||||
|
|
||||||
|
// 生成月份列表
|
||||||
|
const generateMonthList = () => {
|
||||||
|
const months = [];
|
||||||
|
const currentDate = new Date();
|
||||||
|
const currentYear = currentDate.getFullYear();
|
||||||
|
const currentMonth = currentDate.getMonth() + 1; // 当前月份(1-12)
|
||||||
|
|
||||||
|
// 如果选择的是今年,只显示到当前月份
|
||||||
|
if (selectedMonth.value && selectedMonth.value === currentYear.toString()) {
|
||||||
|
for (let i = 1; i <= currentMonth; i++) {
|
||||||
|
months.push({
|
||||||
|
code: i,
|
||||||
|
name: `${i}月`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 其他年份显示完整的12个月
|
||||||
|
for (let i = 1; i <= 12; i++) {
|
||||||
|
months.push({
|
||||||
|
code: i,
|
||||||
|
name: `${i}月`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
locationList.value = months;
|
||||||
|
console.log("生成月份列表:", locationList.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面加载
|
||||||
|
onMounted(() => {
|
||||||
|
generateYearList();
|
||||||
|
generateMonthList();
|
||||||
|
});
|
||||||
|
const searchMeetHistroy=()=>{
|
||||||
|
navTo({
|
||||||
|
url:'/pages_app/meetHistroySearch/meetHistroySearch'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onLoad(() => {
|
||||||
|
currentPage.value = 1;
|
||||||
|
hasMoreData.value = true;
|
||||||
|
loadMeetingData();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 加载会议数据
|
||||||
|
const loadMeetingData = async (isRefresh = false) => {
|
||||||
|
if (isLoadingMore.value && !isRefresh) return;
|
||||||
|
|
||||||
|
if (isRefresh) {
|
||||||
|
isRefreshing.value = true;
|
||||||
|
} else {
|
||||||
|
isLoadingMore.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
page: currentPage.value,
|
||||||
|
pageSize: pageSize.value,
|
||||||
|
year: selectedMonth.value,
|
||||||
|
title: "",
|
||||||
|
month: selectedType.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log("获取会议列表参数:", params);
|
||||||
|
const response = await api.meetingHistoryList(params);
|
||||||
|
|
||||||
|
if (response && response.code === 200) {
|
||||||
|
const { list, totalPage, pageNumber } = response.data || {};
|
||||||
|
|
||||||
|
if (isRefresh) {
|
||||||
|
meetingList.value = list || [];
|
||||||
|
currentPage.value = 1;
|
||||||
|
} else {
|
||||||
|
meetingList.value = [...meetingList.value, ...(list || [])];
|
||||||
|
}
|
||||||
|
|
||||||
|
hasMoreData.value = totalPage > pageNumber;
|
||||||
|
showLoadMore.value = meetingList.value.length > 0;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("加载会议数据失败:", error);
|
||||||
|
} finally {
|
||||||
|
isRefreshing.value = false;
|
||||||
|
isLoadingMore.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 下拉刷新
|
||||||
|
const onRefresh = () => {
|
||||||
|
currentPage.value = 1;
|
||||||
|
hasMoreData.value = true;
|
||||||
|
loadMeetingData(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 上拉加载更多
|
||||||
|
const onLoadMore = () => {
|
||||||
|
if (!hasMoreData.value || isLoadingMore.value) return;
|
||||||
|
currentPage.value++;
|
||||||
|
loadMeetingData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 显示时间选择弹窗
|
||||||
|
const showTimePopup = () => {
|
||||||
|
isTimePopupShow.value = !isTimePopupShow.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 隐藏时间选择弹窗
|
||||||
|
const hideTimePopup = () => {
|
||||||
|
isTimePopupShow.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择年份
|
||||||
|
const selectMonth = (month) => {
|
||||||
|
selectedMonth.value = month.value;
|
||||||
|
monthName.value = month.label;
|
||||||
|
console.log("选择年份:", month.label);
|
||||||
|
|
||||||
|
// 选择年份后重新生成月份列表
|
||||||
|
generateMonthList();
|
||||||
|
|
||||||
|
// 重置月份选择
|
||||||
|
selectedType.value = "";
|
||||||
|
|
||||||
|
// 选择年份后重新加载数据
|
||||||
|
loadMeetingData(true);
|
||||||
|
hideTimePopup();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 显示地区选择弹窗
|
||||||
|
const showLocationPopup = () => {
|
||||||
|
if (selectedMonth.value === "") {
|
||||||
|
uni.showToast({
|
||||||
|
title: "请先选择年份",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isLocationPopupShow.value = !isLocationPopupShow.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 隐藏地区选择弹窗
|
||||||
|
const hideLocationPopup = () => {
|
||||||
|
isLocationPopupShow.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择月份
|
||||||
|
const selectLocation = (location) => {
|
||||||
|
selectedType.value = location.code;
|
||||||
|
typeName.value = location.name;
|
||||||
|
console.log("选择月份:", location.name);
|
||||||
|
// 选择月份后重新加载数据
|
||||||
|
loadMeetingData(true);
|
||||||
|
hideLocationPopup();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 格式化日期
|
||||||
|
const formatDate = (dateStr) => {
|
||||||
|
if (!dateStr) return "";
|
||||||
|
return dayjs(dateStr).format("YYYY.MM.DD");
|
||||||
|
};
|
||||||
|
const goDetail=(item)=>{
|
||||||
|
const encoded = encodeURIComponent(item.path);
|
||||||
|
let imgPath=encodeURIComponent('https://doc.igandan.com/app/html/img/2016/20160714132557.png');
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages_app/webview/webview?url=${encoded}&sharetitle=${item.title}&bg=1&type=live_old&imgPath=${imgPath}&share=1&title=会议详情`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
$white: #fff;
|
||||||
|
$gray: #999;
|
||||||
|
$gray-dark: #666;
|
||||||
|
$gray-light: #eee;
|
||||||
|
$border-color: #e0e0e0;
|
||||||
|
$theme-color: #8b2316;
|
||||||
|
// .nav-right{
|
||||||
|
// margin-top: 50rpx;
|
||||||
|
// }
|
||||||
|
.page {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 筛选标签栏
|
||||||
|
.filter-bar {
|
||||||
|
position: fixed;
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
width: 100%;
|
||||||
|
z-index: 2;
|
||||||
|
background-color: $white;
|
||||||
|
height: 88rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 30rpx;
|
||||||
|
border-bottom: 2rpx solid $gray-light;
|
||||||
|
|
||||||
|
.filter-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color:$gray-dark;
|
||||||
|
|
||||||
|
text {
|
||||||
|
margin-right: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: #8B2316;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-divider {
|
||||||
|
width: 2rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
background-color: $border-color;
|
||||||
|
margin: 0 60rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 滚动内容区域
|
||||||
|
.scroll-content {
|
||||||
|
position: fixed;
|
||||||
|
top: calc(var(--status-bar-height) + 44px + 88rpx);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
background-color: $white;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 会议列表
|
||||||
|
.meeting-list {
|
||||||
|
padding: 0 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meeting-item {
|
||||||
|
padding: 30rpx 0;
|
||||||
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.meeting-content {
|
||||||
|
.meeting-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meeting-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 8rpx;
|
||||||
|
|
||||||
|
.meeting-time,
|
||||||
|
.meeting-location {
|
||||||
|
.timebox{
|
||||||
|
margin-top: -4rpx;
|
||||||
|
margin-right: 8rpx;
|
||||||
|
}
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 空状态
|
||||||
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 100rpx 0;
|
||||||
|
|
||||||
|
.empty-icon {
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
color: #999;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载更多
|
||||||
|
.load-more {
|
||||||
|
padding: 30rpx 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.load-more-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
|
||||||
|
.load-more-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时间选择弹窗
|
||||||
|
.time-popup {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.popup-mask {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-popup-content {
|
||||||
|
margin-top: calc(var(--status-bar-height) + 44px + 90rpx);;
|
||||||
|
position: relative;
|
||||||
|
background-color: $white;
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100vh - calc(var(--status-bar-height) - 44px - 88rpx));
|
||||||
|
|
||||||
|
.time-list {
|
||||||
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.time-item {
|
||||||
|
padding: 25rpx 60rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #666;
|
||||||
|
border-bottom: 2rpx solid #f0f0f0;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
color: $theme-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,493 @@
|
|||||||
|
<template>
|
||||||
|
<view class="page">
|
||||||
|
<!-- 头部搜索栏 -->
|
||||||
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<view class="search-header ">
|
||||||
|
|
||||||
|
<view class="back-icon" @click="goBack">
|
||||||
|
<uni-icons type="left" size="30" color="#8B2316"></uni-icons>
|
||||||
|
</view>
|
||||||
|
<view class="search-input-wrapper">
|
||||||
|
<view class="search-icon">
|
||||||
|
<uni-icons type="search" size="20" color="#999"></uni-icons>
|
||||||
|
</view>
|
||||||
|
<input
|
||||||
|
class="search-input"
|
||||||
|
placeholder="搜索会议关键字"
|
||||||
|
v-model="searchKeyword"
|
||||||
|
@input="onSearchInput"
|
||||||
|
@confirm="onSearchConfirm"
|
||||||
|
confirm-type="search"
|
||||||
|
/>
|
||||||
|
<view class="clear-icon" v-if="searchKeyword" @click="clearSearch">
|
||||||
|
<uni-icons type="clear" size="20" color="#999"></uni-icons>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="cancel-btn" @click="goSearch">
|
||||||
|
<text class="cancel-text">搜索</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 可滚动内容区域 -->
|
||||||
|
<scroll-view
|
||||||
|
class="scroll-content"
|
||||||
|
scroll-y="true"
|
||||||
|
refresher-enabled="true"
|
||||||
|
:refresher-triggered="isRefreshing"
|
||||||
|
:refresher-threshold="100"
|
||||||
|
@refresherrefresh="onRefresh"
|
||||||
|
@scrolltolower="onLoadMore"
|
||||||
|
:lower-threshold="100"
|
||||||
|
>
|
||||||
|
<!-- 会议列表 -->
|
||||||
|
<view class="meeting-list" v-if="meetingList.length > 0">
|
||||||
|
<view
|
||||||
|
class="meeting-item" @click="goDetail(meeting)"
|
||||||
|
v-for="(meeting, index) in meetingList"
|
||||||
|
:key="meeting.id || index"
|
||||||
|
>
|
||||||
|
<view class="meeting-content">
|
||||||
|
<text class="meeting-title">{{
|
||||||
|
meeting.title || meeting.name
|
||||||
|
}}</text>
|
||||||
|
<view class="meeting-info">
|
||||||
|
<view class="meeting-time">
|
||||||
|
<view class="timebox">
|
||||||
|
<up-image
|
||||||
|
:src="timeImg"
|
||||||
|
width="24rpx"
|
||||||
|
height="24rpx"
|
||||||
|
></up-image>
|
||||||
|
</view>
|
||||||
|
<view class="text" >{{ formatDate(meeting.begin_date,'YYYY.MM.DD')}}</view>
|
||||||
|
<view class="text" v-if="formatDate(meeting.end_date,'YYYY.MM.DD')!=formatDate(meeting.begin_date,'YYYY.MM.DD')">{{ '-'+formatDate(meeting.end_date,'YYYY.MM.DD')}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="meeting-location">
|
||||||
|
<uni-icons type="location" size="14" color="#999"></uni-icons>
|
||||||
|
{{ meeting.location }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<view class="empty-state" v-else-if="!isRefreshing">
|
||||||
|
<empty></empty>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 加载更多提示 -->
|
||||||
|
<view class="load-more" v-if="showLoadMore">
|
||||||
|
<view class="load-more-content" v-if="isLoadingMore">
|
||||||
|
<uni-icons type="spinner-cycle" size="20" color="#999"></uni-icons>
|
||||||
|
<text class="load-more-text">加载中...</text>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="load-more-content"
|
||||||
|
v-else-if="hasMoreData && meetingList.length > 0"
|
||||||
|
>
|
||||||
|
<text class="load-more-text">上拉加载更多</text>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="load-more-content"
|
||||||
|
v-else-if="meetingList.length > 0 && !isLoadingMore"
|
||||||
|
>
|
||||||
|
<text class="load-more-text">没有更多数据了</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
import { onShow } from "@dcloudio/uni-app";
|
||||||
|
import api from "@/api/api.js";
|
||||||
|
import navBar from "@/components/navBar/navBar.vue";
|
||||||
|
import select from "@/static/triangle_normal.png";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import timeImg from "@/static/play_long.png"
|
||||||
|
import empty from "@/components/empty/empty.vue";
|
||||||
|
|
||||||
|
const searchKeyword = ref('');
|
||||||
|
// 下拉刷新和上拉加载状态
|
||||||
|
const isRefreshing = ref(false);
|
||||||
|
const isLoadingMore = ref(false);
|
||||||
|
const hasMoreData = ref(true);
|
||||||
|
const showLoadMore = ref(true);
|
||||||
|
const currentPage = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
|
||||||
|
// 会议列表数据
|
||||||
|
const meetingList = ref([]);
|
||||||
|
|
||||||
|
const goSearch=()=>{
|
||||||
|
if(!searchKeyword.value){
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入搜索内容',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentPage.value = 1;
|
||||||
|
hasMoreData.value = true;
|
||||||
|
meetingList.value = [];
|
||||||
|
loadMeetingData();
|
||||||
|
}
|
||||||
|
|
||||||
|
const goBack=()=>{
|
||||||
|
uni.navigateBack({
|
||||||
|
fail:()=>{
|
||||||
|
uni.redirectTo({
|
||||||
|
url:'/pages/index/index'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 加载会议数据
|
||||||
|
const loadMeetingData = async (isRefresh = false) => {
|
||||||
|
if (isLoadingMore.value && !isRefresh) return;
|
||||||
|
|
||||||
|
if (isRefresh) {
|
||||||
|
isRefreshing.value = true;
|
||||||
|
} else {
|
||||||
|
isLoadingMore.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
page: currentPage.value,
|
||||||
|
pageSize: pageSize.value,
|
||||||
|
year:'',
|
||||||
|
title: searchKeyword.value,
|
||||||
|
month: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log("获取会议列表参数:", params);
|
||||||
|
const response = await api.meetingHistoryList(params);
|
||||||
|
|
||||||
|
if (response && response.code === 200) {
|
||||||
|
const { list, totalPage, pageNumber } = response.data || {};
|
||||||
|
|
||||||
|
if (isRefresh) {
|
||||||
|
meetingList.value = list || [];
|
||||||
|
currentPage.value = 1;
|
||||||
|
} else {
|
||||||
|
meetingList.value = [...meetingList.value, ...(list || [])];
|
||||||
|
}
|
||||||
|
console.log("会议列表数据:", meetingList.value);
|
||||||
|
hasMoreData.value = totalPage > pageNumber;
|
||||||
|
showLoadMore.value = meetingList.value.length > 0;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("加载会议数据失败:", error);
|
||||||
|
} finally {
|
||||||
|
isRefreshing.value = false;
|
||||||
|
isLoadingMore.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 下拉刷新
|
||||||
|
const onRefresh = () => {
|
||||||
|
currentPage.value = 1;
|
||||||
|
hasMoreData.value = true;
|
||||||
|
loadMeetingData(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 上拉加载更多
|
||||||
|
const onLoadMore = () => {
|
||||||
|
if (!hasMoreData.value || isLoadingMore.value) return;
|
||||||
|
currentPage.value++;
|
||||||
|
loadMeetingData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 显示时间选择弹窗
|
||||||
|
const showTimePopup = () => {
|
||||||
|
isTimePopupShow.value = !isTimePopupShow.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 隐藏时间选择弹窗
|
||||||
|
const hideTimePopup = () => {
|
||||||
|
isTimePopupShow.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择年份
|
||||||
|
const selectMonth = (month) => {
|
||||||
|
selectedMonth.value = month.value;
|
||||||
|
console.log("选择年份:", month.label);
|
||||||
|
|
||||||
|
// 选择年份后重新生成月份列表
|
||||||
|
generateMonthList();
|
||||||
|
|
||||||
|
// 重置月份选择
|
||||||
|
selectedType.value = "";
|
||||||
|
|
||||||
|
// 选择年份后重新加载数据
|
||||||
|
loadMeetingData(true);
|
||||||
|
hideTimePopup();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 显示地区选择弹窗
|
||||||
|
const showLocationPopup = () => {
|
||||||
|
if (selectedMonth.value === "") {
|
||||||
|
uni.showToast({
|
||||||
|
title: "请先选择年份",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isLocationPopupShow.value = !isLocationPopupShow.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 隐藏地区选择弹窗
|
||||||
|
const hideLocationPopup = () => {
|
||||||
|
isLocationPopupShow.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择月份
|
||||||
|
const selectLocation = (location) => {
|
||||||
|
selectedType.value = location.code;
|
||||||
|
console.log("选择月份:", location.name);
|
||||||
|
// 选择月份后重新加载数据
|
||||||
|
loadMeetingData(true);
|
||||||
|
hideLocationPopup();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 格式化日期
|
||||||
|
const formatDate = (dateStr) => {
|
||||||
|
if (!dateStr) return "";
|
||||||
|
return dayjs(dateStr).format("YYYY.MM.DD");
|
||||||
|
};
|
||||||
|
const goDetail=(item)=>{
|
||||||
|
const encoded = encodeURIComponent(item.path);
|
||||||
|
let imgPath=encodeURIComponent('https://doc.igandan.com/app/html/img/2016/20160714132557.png');
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages_app/webview/webview?url=${encoded}&sharetitle=${item.title}&bg=1&type=live_old&imgPath=${imgPath}&share=1&title=会议详情`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
$white: #fff;
|
||||||
|
$gray: #999;
|
||||||
|
$gray-dark: #666;
|
||||||
|
$gray-light: #eee;
|
||||||
|
$border-color: #e0e0e0;
|
||||||
|
$theme-color: #8b2316;
|
||||||
|
|
||||||
|
.page {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
// 头部搜索栏
|
||||||
|
.search-header {
|
||||||
|
|
||||||
|
background-color: #eeeeee;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
height:44px;
|
||||||
|
align-items: center;
|
||||||
|
padding:0 30rpx;
|
||||||
|
gap: 20rpx;
|
||||||
|
|
||||||
|
|
||||||
|
.search-input-wrapper {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
height:70rpx;
|
||||||
|
|
||||||
|
.search-icon {
|
||||||
|
margin-right: 15rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
flex: 1;
|
||||||
|
height: 80rpx;
|
||||||
|
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear-icon {
|
||||||
|
margin-left: 15rpx;
|
||||||
|
padding: 10rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-btn {
|
||||||
|
padding: 10rpx 20rpx;
|
||||||
|
background:#8B2316;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
|
||||||
|
.cancel-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 滚动内容区域
|
||||||
|
.scroll-content {
|
||||||
|
position: fixed;
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
background-color: $white;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 会议列表
|
||||||
|
.meeting-list {
|
||||||
|
padding: 0 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meeting-item {
|
||||||
|
padding: 30rpx 0;
|
||||||
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.meeting-content {
|
||||||
|
.meeting-title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
line-clamp: 2;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.meeting-info {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 8rpx;
|
||||||
|
|
||||||
|
.meeting-time,
|
||||||
|
.meeting-location {
|
||||||
|
.timebox{
|
||||||
|
margin-top: -4rpx;
|
||||||
|
margin-right: 8rpx;
|
||||||
|
}
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 空状态
|
||||||
|
.empty-state {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 100rpx 0;
|
||||||
|
|
||||||
|
.empty-icon {
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-text {
|
||||||
|
color: #999;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载更多
|
||||||
|
.load-more {
|
||||||
|
padding: 30rpx 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.load-more-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
|
||||||
|
.load-more-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时间选择弹窗
|
||||||
|
.time-popup {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.popup-mask {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-popup-content {
|
||||||
|
margin-top: 271rpx;
|
||||||
|
position: relative;
|
||||||
|
background-color: $white;
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100vh - 275rpx);
|
||||||
|
|
||||||
|
.time-list {
|
||||||
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.time-item {
|
||||||
|
padding: 25rpx 60rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #666;
|
||||||
|
border-bottom: 2rpx solid #f0f0f0;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
color: $theme-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
+291
-83
@@ -1,47 +1,53 @@
|
|||||||
<template>
|
<template>
|
||||||
|
|
||||||
<!-- 顶部导航栏 -->
|
<!-- 顶部导航栏 -->
|
||||||
<uni-nav-bar
|
<view class="navbox">
|
||||||
left-icon="left"
|
<view class="status_bar"></view>
|
||||||
title="消息"
|
<uni-nav-bar
|
||||||
right-text="清除"
|
left-icon="left"
|
||||||
@clickRight="clearMsg"
|
:title="'消息'"
|
||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
color="#8B2316"
|
||||||
color="#8B2316"
|
:border="false"
|
||||||
height="140rpx"
|
backgroundColor="#eeeeee"
|
||||||
:border="false"
|
>
|
||||||
backgroundColor="#eeeeee"
|
<template v-slot:right>
|
||||||
></uni-nav-bar>
|
<view class="nav-right" >
|
||||||
|
<view class="collect-img" @click="clearMsg" >
|
||||||
|
<image class="img-icon" :src="clearImg" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</uni-nav-bar>
|
||||||
|
</view>
|
||||||
<view class="msg-page">
|
<view class="msg-page">
|
||||||
|
|
||||||
|
|
||||||
<!-- 四宫格入口 -->
|
<!-- 四宫格入口 -->
|
||||||
<view class="shortcut-grid">
|
<view class="shortcut-grid">
|
||||||
<view class="grid-item" @click="goBenefit">
|
<view class="grid-item" @click="goBenefit">
|
||||||
<view class="icon-wrap gift">
|
<view class="icon-wrap">
|
||||||
<uni-icons type="gift" size="34" color="#fff"></uni-icons>
|
<image :src="fuliImg" class="imgcell"/>
|
||||||
<view class="badge" v-if="badgeData.Module_Welfare > 0">{{ badgeData.Module_Welfare }}</view>
|
<view class="badge" v-if="badgeData.Module_Welfare > 0">{{ badgeData.Module_Welfare }}</view>
|
||||||
</view>
|
</view>
|
||||||
<text class="label">福利</text>
|
<text class="label">福利</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="grid-item" @click="goOrder">
|
<view class="grid-item" @click="goOrder">
|
||||||
<view class="icon-wrap order">
|
<view class="icon-wrap ">
|
||||||
<uni-icons type="list" size="34" color="#fff"></uni-icons>
|
<image :src="orderImg" class="imgcell"/>
|
||||||
<view class="badge" v-if="badgeData.Module_Order > 0">{{ badgeData.Module_Order }}</view>
|
<view class="badge" v-if="badgeData.Module_Order > 0">{{ badgeData.Module_Order }}</view>
|
||||||
</view>
|
</view>
|
||||||
<text class="label">订单</text>
|
<text class="label">订单</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="grid-item" @click="goFollow">
|
<view class="grid-item" @click="goFollow">
|
||||||
<view class="icon-wrap visit">
|
<view class="icon-wrap">
|
||||||
<uni-icons type="heart" size="34" color="#fff"></uni-icons>
|
<image :src="followImg" class="imgcell"/>
|
||||||
<view class="badge" v-if="badgeData.Module_Relation > 0">{{ badgeData.Module_Relation }}</view>
|
<view class="badge" v-if="badgeData.Module_Relation > 0">{{ badgeData.Module_Relation }}</view>
|
||||||
</view>
|
</view>
|
||||||
<text class="label">随访</text>
|
<text class="label">随访</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="grid-item" @click="goReply">
|
<view class="grid-item" @click="goReply">
|
||||||
<view class="icon-wrap reply">
|
<view class="icon-wrap">
|
||||||
<uni-icons type="chatbubble" size="34" color="#fff"></uni-icons>
|
<image :src="replyImg" class="imgcell"/>
|
||||||
<view class="badge" v-if="badgeData.Module_Comment > 0">{{ badgeData.Module_Comment }}</view>
|
<view class="badge" v-if="badgeData.Module_Comment > 0">{{ badgeData.Module_Comment }}</view>
|
||||||
</view>
|
</view>
|
||||||
<text class="label">回复我的</text>
|
<text class="label">回复我的</text>
|
||||||
@@ -53,15 +59,15 @@
|
|||||||
class="msg-list"
|
class="msg-list"
|
||||||
scroll-y="true"
|
scroll-y="true"
|
||||||
:show-scrollbar="false"
|
:show-scrollbar="false"
|
||||||
refresher-enabled="true"
|
:refresher-enabled="true"
|
||||||
:refresher-triggered="refreshing"
|
:refresher-triggered="refreshing"
|
||||||
@refresherrefresh="onRefresh"
|
@refresherrefresh="onRefresh"
|
||||||
@scrolltolower="onLoadMore"
|
@scrolltolower="onLoadMore"
|
||||||
lower-threshold="80"
|
:lower-threshold="100"
|
||||||
>
|
>
|
||||||
<!-- 回复我的模块 - 聊天列表样式 -->
|
<!-- 回复我的模块 - 聊天列表样式 -->
|
||||||
<view v-if="currentModule === 4" class="chat-list">
|
<view v-if="currentModule === 4" class="chat-list">
|
||||||
<view class="chat-item" v-for="(msg, idx) in msgList" :key="msg.id">
|
<view class="chat-item" v-for="(msg, idx) in msgList" :key="msg.id" @click="goMsgDetail(msg)">
|
||||||
<view class="avatar">
|
<view class="avatar">
|
||||||
<image :src="msg.avatar || '/static/default-avatar.png'" mode="aspectFill" @error="handleImageError"></image>
|
<image :src="msg.avatar || '/static/default-avatar.png'" mode="aspectFill" @error="handleImageError"></image>
|
||||||
</view>
|
</view>
|
||||||
@@ -77,24 +83,28 @@
|
|||||||
|
|
||||||
<!-- 其他模块 - 卡片样式 -->
|
<!-- 其他模块 - 卡片样式 -->
|
||||||
<view v-else>
|
<view v-else>
|
||||||
<view class="card" v-for="(msg, idx) in msgList" :key="msg.id">
|
<view class="card-cell" v-for="(msg, idx) in msgList" :key="msg.id" @click="goMsgDetail(msg)">
|
||||||
<view class="card-title">{{ msg.title }}</view>
|
|
||||||
<view class="card-content">{{ msg.content }}</view>
|
|
||||||
<view class="card-time">{{ msg.create_date }}</view>
|
<view class="card-time">{{ msg.create_date }}</view>
|
||||||
|
<view class="card" >
|
||||||
|
<view class="card-title" :class="{'active':msg.is_read==0}">{{ msg.title }}</view>
|
||||||
|
<view class="card-content">{{ msg.content }}</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 空状态 -->
|
<!-- 空状态 -->
|
||||||
<view v-if="msgList.length === 0" class="empty-state">
|
<view v-if="msgList.length === 0 && !loading && !refreshing" class="empty-state">
|
||||||
<text class="empty-text">暂无消息</text>
|
<empty></empty>
|
||||||
</view>
|
</view>
|
||||||
<!-- 加载更多提示 -->
|
<!-- 加载更多提示 -->
|
||||||
<view v-if="loading" class="loading-more">
|
<view v-if="loading && msgList.length > 0" class="loading-more">
|
||||||
|
<view class="loading-spinner"></view>
|
||||||
<text class="loading-text">加载中...</text>
|
<text class="loading-text">加载中...</text>
|
||||||
</view>
|
</view>
|
||||||
<!-- 没有更多数据提示 -->
|
<!-- 没有更多数据提示 -->
|
||||||
<view v-if="noMore" class="no-more">
|
<view v-if="noMore && msgList.length > 0 && !loading" class="no-more">
|
||||||
<text class="no-more-text">没有更多数据了</text>
|
<text class="no-more-text">— 没有更多数据了 —</text>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
@@ -104,6 +114,18 @@
|
|||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
import api from '@/api/api.js';
|
import api from '@/api/api.js';
|
||||||
import docUrl from '@/utils/docUrl';
|
import docUrl from '@/utils/docUrl';
|
||||||
|
import navTo from '@/utils/navTo';
|
||||||
|
import clearImg from '@/static/clear_message.png';
|
||||||
|
import empty from '@/components/empty/empty.vue';
|
||||||
|
import fuliImg from '@/static/fu_message_big.png';
|
||||||
|
import orderImg from '@/static/ding_message_big.png';
|
||||||
|
import followImg from '@/static/sui_message_big.png';
|
||||||
|
import replyImg from '@/static/hui_message_big.png';
|
||||||
|
import {onBackPress} from '@dcloudio/uni-app';
|
||||||
|
onBackPress(() => {
|
||||||
|
plus.runtime.quit();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
// 角标数据
|
// 角标数据
|
||||||
const badgeData = ref({
|
const badgeData = ref({
|
||||||
@@ -122,81 +144,183 @@
|
|||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const noMore = ref(false);
|
const noMore = ref(false);
|
||||||
const page = ref(1);
|
const page = ref(1);
|
||||||
const pageSize = ref(10);
|
const pageSize = 10;
|
||||||
|
|
||||||
|
// 重置分页状态
|
||||||
|
const resetPagination = () => {
|
||||||
|
page.value = 1;
|
||||||
|
noMore.value = false;
|
||||||
|
msgList.value = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
uni.navigateBack({
|
plus.runtime.quit();
|
||||||
fail() {
|
};
|
||||||
uni.redirectTo({
|
|
||||||
url: '/pages/index/index'
|
// 切换模块
|
||||||
|
const switchModule = (module) => {
|
||||||
|
if (currentModule.value === module && msgList.value.length > 0) return; // 避免重复加载
|
||||||
|
currentModule.value = module;
|
||||||
|
resetPagination();
|
||||||
|
getAppMesageList(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const goBenefit = () => switchModule(1);
|
||||||
|
const goOrder = () => switchModule(2);
|
||||||
|
const goFollow = () => switchModule(3);
|
||||||
|
const goReply = () => switchModule(4);
|
||||||
|
const readMsg = (id) => {
|
||||||
|
api.appMesageRead({
|
||||||
|
id: id
|
||||||
|
}).then(res => {
|
||||||
|
if(res.code==200){
|
||||||
|
msgList.value.forEach(item => {
|
||||||
|
if(item.id==id){
|
||||||
|
uni.sendNativeEvent("portraitReport",{
|
||||||
|
msg:{
|
||||||
|
event_nickname: "read_message",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
(ret) => {
|
||||||
|
console.log(ret);
|
||||||
|
});
|
||||||
|
item.is_read=1;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
const goBenefit = () => {
|
|
||||||
currentModule.value = 1;
|
|
||||||
getAppMesageList(1);
|
|
||||||
};
|
|
||||||
const goOrder = () => {
|
|
||||||
currentModule.value = 2;
|
|
||||||
getAppMesageList(2);
|
|
||||||
};
|
|
||||||
const goFollow = () => {
|
|
||||||
currentModule.value = 3;
|
|
||||||
getAppMesageList(3);
|
|
||||||
};
|
|
||||||
const goReply = () => {
|
|
||||||
currentModule.value = 4;
|
|
||||||
getAppMesageList(4);
|
|
||||||
};
|
|
||||||
|
|
||||||
const clearMsg = () => {
|
const clearMsg = () => {
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '提醒',
|
title: '提醒',
|
||||||
content: '是否要清除所有未读消息?',
|
content: '是否要清除所有未读消息?',
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
api.appMesageRead({}).then(res => {
|
api.appMesageRead().then(res => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
|
|
||||||
|
getUnReadList();
|
||||||
|
|
||||||
|
uni.sendNativeEvent("portraitReport",{
|
||||||
|
msg:{
|
||||||
|
event_nickname: "clear_message",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
(ret) => {
|
||||||
|
console.log(ret);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
getUnReadList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const goMsgDetail = (msg) => {
|
||||||
|
console.log(msg);
|
||||||
|
if(msg.is_read==0){
|
||||||
|
readMsg(msg.id);
|
||||||
|
};
|
||||||
|
//readMsg(msg.id);
|
||||||
|
if(msg.extra.module==4){
|
||||||
|
if(msg.extra.type==17 || msg.extra.type==40){
|
||||||
|
uni.showToast({
|
||||||
|
title: '暂停中',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
uni.sendNativeEvent('goCourseDetail', {
|
||||||
|
msg: {
|
||||||
|
id:msg.extra.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}else if(msg.extra.module==2){
|
||||||
|
if(msg.extra.type==19){
|
||||||
|
let url=`/pages_app/myCourseware/myCourseware?from=msg`
|
||||||
|
navTo({
|
||||||
|
url: url
|
||||||
|
})
|
||||||
|
}else if(msg.extra.type==18){
|
||||||
|
let url=`/pages_app/myFlower/myFlower?from=msg`
|
||||||
|
navTo({
|
||||||
|
url: url
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
let url="";
|
||||||
|
if(msg.extra.module==1 && msg.extra.type==36){
|
||||||
|
url=`/pages_app/myPoint/myPoint?from=msg`
|
||||||
|
navTo({
|
||||||
|
url: url
|
||||||
|
})
|
||||||
|
}else if(msg.extra.module==1 && msg.extra.type==31){
|
||||||
|
url=`/pages_app/myPoint/myPoint?from=msg`
|
||||||
|
navTo({
|
||||||
|
url: url
|
||||||
|
})
|
||||||
|
}else if(msg.extra.module==1 && msg.extra.type==35){
|
||||||
|
//uni.setStorageSync('lookWelfare', 'useWelfare');
|
||||||
|
url=`/pages_app/myWelfareCard/myWelfareCard?from=msg`
|
||||||
|
navTo({
|
||||||
|
url: url
|
||||||
|
})
|
||||||
|
}else if(msg.extra.module==3 && msg.extra.type==12){
|
||||||
|
url=`/pages_app/myPatient/myPatient?from=msg`
|
||||||
|
navTo({
|
||||||
|
url: url
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
// 下拉刷新
|
// 下拉刷新
|
||||||
const onRefresh = async () => {
|
const onRefresh = async () => {
|
||||||
if (refreshing.value) return;
|
if (refreshing.value) return;
|
||||||
refreshing.value = true;
|
refreshing.value = true;
|
||||||
try {
|
try {
|
||||||
// 重新获取当前模块的消息列表
|
// 重置分页并重新获取数据
|
||||||
getAppMesageList(currentModule.value);
|
resetPagination();
|
||||||
// 重新获取未读消息数量
|
await Promise.all([
|
||||||
getUnReadList();
|
getAppMesageList(true),
|
||||||
|
getUnReadList()
|
||||||
|
]);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('刷新失败:', err);
|
||||||
|
uni.showToast({
|
||||||
|
title: '刷新失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
refreshing.value = false;
|
refreshing.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 上拉加载
|
// 上拉加载更多
|
||||||
const onLoadMore = async () => {
|
const onLoadMore = async () => {
|
||||||
if (loading.value || noMore.value) return;
|
if (loading.value || noMore.value || refreshing.value) return;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
// 这里可以根据需要实现分页加载
|
page.value++;
|
||||||
// 目前接口返回的数据已经包含了分页信息
|
await getAppMesageList(false);
|
||||||
// 如果需要加载更多,可以调用 getAppMesageList 并传入页码参数
|
} catch (err) {
|
||||||
noMore.value = true; // 暂时设置为没有更多数据
|
// 加载失败时回退页码
|
||||||
|
page.value = Math.max(1, page.value - 1);
|
||||||
|
console.error('加载更多失败:', err);
|
||||||
|
uni.showToast({
|
||||||
|
title: '加载失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getUnReadList = () => {
|
const getUnReadList = () => {
|
||||||
api.unReadList({}).then(res => {
|
return api.unReadList({}).then(res => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
if (res.code === 200 && res.data) {
|
if (res.code === 200 && res.data) {
|
||||||
// 更新角标数据
|
// 更新角标数据
|
||||||
@@ -207,17 +331,24 @@
|
|||||||
Module_Relation: parseInt(res.data.Module_Relation) || 0
|
Module_Relation: parseInt(res.data.Module_Relation) || 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
return res;
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error('获取未读消息列表失败:', err);
|
console.error('获取未读消息列表失败:', err);
|
||||||
|
throw err;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAppMesageList = (module) => {
|
// 获取消息列表
|
||||||
api.appMesageList({module: module}).then(res => {
|
// isRefresh: true 表示刷新,false 表示加载更多
|
||||||
|
const getAppMesageList = (isRefresh = false) => {
|
||||||
|
return api.appMesageList({
|
||||||
|
module: currentModule.value,
|
||||||
|
page: page.value,
|
||||||
|
pageSize: pageSize
|
||||||
|
}).then(res => {
|
||||||
console.log(res);
|
console.log(res);
|
||||||
if (res.code === 200 && res.data && res.data.list) {
|
if (res.code === 200 && res.data && res.data.list) {
|
||||||
// 更新消息列表数据
|
const newList = res.data.list.map(item => ({
|
||||||
msgList.value = res.data.list.map(item => ({
|
|
||||||
id: item.id,
|
id: item.id,
|
||||||
title: item.title,
|
title: item.title,
|
||||||
content: item.content,
|
content: item.content,
|
||||||
@@ -232,9 +363,31 @@
|
|||||||
`${getBaseUrl()}${item.extra.user_photo}`) :
|
`${getBaseUrl()}${item.extra.user_photo}`) :
|
||||||
'/static/default-avatar.png'
|
'/static/default-avatar.png'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// 刷新时替换数据,加载更多时追加数据
|
||||||
|
if (isRefresh || page.value === 1) {
|
||||||
|
msgList.value = newList;
|
||||||
|
} else {
|
||||||
|
msgList.value = [...msgList.value, ...newList];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否还有更多数据
|
||||||
|
if (res.isLastPage || newList.length < pageSize) {
|
||||||
|
noMore.value = true;
|
||||||
|
} else {
|
||||||
|
noMore.value = false;
|
||||||
|
}
|
||||||
|
} else if (res.code === 200 && (!res.data || !res.data.list || res.data.list.length === 0)) {
|
||||||
|
// 没有数据的情况
|
||||||
|
if (isRefresh || page.value === 1) {
|
||||||
|
msgList.value = [];
|
||||||
|
}
|
||||||
|
noMore.value = true;
|
||||||
}
|
}
|
||||||
|
return res;
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error('获取消息列表失败:', err);
|
console.error('获取消息列表失败:', err);
|
||||||
|
throw err;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -251,7 +404,7 @@
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getUnReadList();
|
getUnReadList();
|
||||||
getAppMesageList(1);
|
getAppMesageList(true); // 初始加载视为刷新
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -270,16 +423,31 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
.imgcell{
|
||||||
|
width:74rpx;
|
||||||
|
height: 74rpx;
|
||||||
|
}
|
||||||
|
.nav-right{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.collect-img {
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
.img-icon{
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.msg-page {
|
.msg-page {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background: $bg;
|
background: $bg;
|
||||||
padding-top: $nav-h; // 与导航栏高度一致
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.shortcut-grid {
|
.shortcut-grid {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: $nav-h;
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 9;
|
z-index: 9;
|
||||||
@@ -333,7 +501,7 @@
|
|||||||
.msg-list {
|
.msg-list {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
// 减去导航与宫格的高度
|
// 减去导航与宫格的高度
|
||||||
top: 360rpx; // 让列表起始位置在宫格下方
|
top: calc(var(--status-bar-height) + 44px + 230rpx);
|
||||||
padding: 20rpx 24rpx 40rpx;
|
padding: 20rpx 24rpx 40rpx;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
bottom: 0rpx;
|
bottom: 0rpx;
|
||||||
@@ -347,6 +515,47 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 空状态样式
|
||||||
|
.empty-state {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 100rpx 0;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载动画
|
||||||
|
.loading-more {
|
||||||
|
gap: 16rpx;
|
||||||
|
|
||||||
|
.loading-spinner {
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
border: 3rpx solid #eee;
|
||||||
|
border-top-color: $theme;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 0.8s linear infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-cell{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.card-time {
|
||||||
|
width:100%;
|
||||||
|
margin:10rpx 0;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
.card {
|
.card {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 16rpx;
|
border-radius: 16rpx;
|
||||||
@@ -359,6 +568,9 @@
|
|||||||
color: $text-primary;
|
color: $text-primary;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
margin-bottom: 14rpx;
|
margin-bottom: 14rpx;
|
||||||
|
&.active{
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-content {
|
.card-content {
|
||||||
@@ -368,11 +580,7 @@
|
|||||||
margin-bottom: 14rpx;
|
margin-bottom: 14rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-time {
|
|
||||||
font-size: 24rpx;
|
|
||||||
color: $muted;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 聊天列表样式
|
// 聊天列表样式
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
<template>
|
||||||
|
<view class="bill-detail-page">
|
||||||
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
|
left-icon="left"
|
||||||
|
title="详情"
|
||||||
|
@clickLeft="goBack"
|
||||||
|
color="#8B2316"
|
||||||
|
:border="false"
|
||||||
|
backgroundColor="#eeeeee"
|
||||||
|
></uni-nav-bar>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="detail-content">
|
||||||
|
<view class="detail-row">
|
||||||
|
<text class="label">交易号:</text>
|
||||||
|
<text class="value">{{ detail.tradeNo || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-row">
|
||||||
|
<text class="label">类型:</text>
|
||||||
|
<text class="value">{{ detail.typeName || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-row">
|
||||||
|
<text class="label">金额:</text>
|
||||||
|
<text class="value amount" :class="amountClass">{{ detail.accountStr || '-' }}元</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-row">
|
||||||
|
<text class="label">用户:</text>
|
||||||
|
<text class="value">{{ detail.userName || '-' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-row">
|
||||||
|
<text class="label">时间:</text>
|
||||||
|
<text class="value">{{ formatDateTime(detail.createTime) }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="detail-row">
|
||||||
|
<text class="label">备注:</text>
|
||||||
|
<text class="value">{{ detail.remark || '' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, computed, onMounted } from 'vue'
|
||||||
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
|
|
||||||
|
const detail = ref({})
|
||||||
|
const from = ref('')
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
if (options.from) {
|
||||||
|
from.value = decodeURIComponent(options.from)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const amountClass = computed(() => {
|
||||||
|
const amount = Number(detail.value?.accountStr || 0)
|
||||||
|
return amount < 0 ? 'negative' : 'positive'
|
||||||
|
})
|
||||||
|
|
||||||
|
const formatDateTime = (value) => {
|
||||||
|
if (!value) return '-'
|
||||||
|
const text = String(value).trim()
|
||||||
|
const date = new Date(text)
|
||||||
|
if (Number.isNaN(date.getTime())) return text
|
||||||
|
const y = date.getFullYear()
|
||||||
|
const m = String(date.getMonth() + 1).padStart(2, '0')
|
||||||
|
const d = String(date.getDate()).padStart(2, '0')
|
||||||
|
const hh = String(date.getHours()).padStart(2, '0')
|
||||||
|
const mm = String(date.getMinutes()).padStart(2, '0')
|
||||||
|
const ss = String(date.getSeconds()).padStart(2, '0')
|
||||||
|
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const goBack = () => {
|
||||||
|
if (from.value === 'billDetails') {
|
||||||
|
uni.navigateBack()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uni.redirectTo({
|
||||||
|
url: '/pages_app/myAccount/billDetails?from=myAccount'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const cache = uni.getStorageSync('billDetailItem')
|
||||||
|
detail.value = cache || {}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.bill-detail-page {
|
||||||
|
min-height: 100vh;
|
||||||
|
background: #f3f3f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-content {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
bottom: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: #ffffff;
|
||||||
|
padding: 0 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-row {
|
||||||
|
min-height: 88rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-bottom: 1rpx solid #efefef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #2c2c2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
flex: 1;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #666666;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.amount {
|
||||||
|
&.positive {
|
||||||
|
color: #8B2316;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.negative {
|
||||||
|
color: #3f3f3f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,16 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="bill-details-page">
|
<view class="bill-details-page">
|
||||||
<!-- 顶部导航栏 -->
|
<!-- 顶部导航栏 -->
|
||||||
<uni-nav-bar
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
left-icon="left"
|
left-icon="left"
|
||||||
title="账单明细"
|
title="账单明细"
|
||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
></uni-nav-bar>
|
></uni-nav-bar>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 表格头部 -->
|
<!-- 表格头部 -->
|
||||||
<view class="table-header">
|
<view class="table-header">
|
||||||
@@ -32,7 +35,7 @@
|
|||||||
@scrolltolower="onLoadMore"
|
@scrolltolower="onLoadMore"
|
||||||
:lower-threshold="100"
|
:lower-threshold="100"
|
||||||
>
|
>
|
||||||
<view class="transaction-item" v-for="(item, index) in orderList" :key="item.id">
|
<view class="transaction-item" v-for="(item, index) in orderList" :key="item.id" @click="goToDetail(item)">
|
||||||
<view class="cell business-type">{{ item.typeName }}</view>
|
<view class="cell business-type">{{ item.typeName }}</view>
|
||||||
<view class="cell user">{{ item.userName }}</view>
|
<view class="cell user">{{ item.userName }}</view>
|
||||||
<view class="cell date-amount">
|
<view class="cell date-amount">
|
||||||
@@ -62,6 +65,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import api from '@/api/api.js'
|
import api from '@/api/api.js'
|
||||||
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
|
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const orderList = ref([])
|
const orderList = ref([])
|
||||||
@@ -71,10 +75,24 @@ const page = ref(1)
|
|||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
const isFirstPage = ref(true)
|
const isFirstPage = ref(true)
|
||||||
const isLastPage = ref(false)
|
const isLastPage = ref(false)
|
||||||
|
const from = ref('')
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
if (options.from) {
|
||||||
|
from.value = decodeURIComponent(options.from)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const stopRefresh = () => {
|
||||||
|
refreshing.value = false
|
||||||
|
}
|
||||||
|
|
||||||
// 获取订单列表
|
// 获取订单列表
|
||||||
const getOrderList = async (isRefresh = false) => {
|
const getOrderList = async (isRefresh = false) => {
|
||||||
if (loading.value) return
|
if (loading.value) {
|
||||||
|
if (isRefresh) stopRefresh()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
loading.value = true
|
loading.value = true
|
||||||
|
|
||||||
@@ -93,15 +111,18 @@ const getOrderList = async (isRefresh = false) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 处理订单数据
|
// 处理订单数据
|
||||||
const processedList = list.map(item => ({
|
const safeList = Array.isArray(list) ? list : []
|
||||||
|
const processedList = safeList.map(item => ({
|
||||||
id: item.trade_no,
|
id: item.trade_no,
|
||||||
|
tradeNo: item.trade_no,
|
||||||
typeName: item.type_name,
|
typeName: item.type_name,
|
||||||
userName: item.user_name,
|
userName: item.user_name,
|
||||||
createTime: item.create_time,
|
createTime: item.create_time,
|
||||||
accountStr: item.accountstr,
|
accountStr: item.accountstr,
|
||||||
payChannel: item.pay_channel,
|
payChannel: item.pay_channel,
|
||||||
orderType: item.order_type,
|
orderType: item.order_type,
|
||||||
status: item.status
|
status: item.status,
|
||||||
|
remark: item.remark || item.message || ''
|
||||||
}))
|
}))
|
||||||
|
|
||||||
orderList.value.push(...processedList)
|
orderList.value.push(...processedList)
|
||||||
@@ -117,12 +138,16 @@ const getOrderList = async (isRefresh = false) => {
|
|||||||
})
|
})
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
refreshing.value = false
|
stopRefresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 刷新数据
|
// 刷新数据
|
||||||
const onRefresh = () => {
|
const onRefresh = () => {
|
||||||
|
if (loading.value) {
|
||||||
|
stopRefresh()
|
||||||
|
return
|
||||||
|
}
|
||||||
refreshing.value = true
|
refreshing.value = true
|
||||||
page.value = 1
|
page.value = 1
|
||||||
isLastPage.value = false
|
isLastPage.value = false
|
||||||
@@ -149,9 +174,23 @@ const formatDate = (dateStr) => {
|
|||||||
|
|
||||||
// 返回上一页
|
// 返回上一页
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
|
if (from.value === 'myAccount') {
|
||||||
|
uni.redirectTo({
|
||||||
|
url: '/pages_app/myAccount/myAccount?from=billDetails'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
uni.navigateBack()
|
uni.navigateBack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const goToDetail = (item) => {
|
||||||
|
uni.setStorageSync('billDetailItem', item || {})
|
||||||
|
const fromPage = encodeURIComponent('billDetails')
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages_app/myAccount/billDetail?from=${fromPage}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getOrderList()
|
getOrderList()
|
||||||
})
|
})
|
||||||
@@ -182,14 +221,17 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 表格头部样式
|
// 表格头部样式
|
||||||
.table-header {
|
.table-header {
|
||||||
background-color: #e0e0e0;
|
background-color: #fff;
|
||||||
|
position: fixed;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
padding: 20rpx 30rpx;
|
padding: 20rpx 30rpx;
|
||||||
margin-top: 170rpx; /* 为固定导航栏留出空间 */
|
box-sizing: border-box;
|
||||||
|
top:calc(var(--status-bar-height) + 44px); /* 为固定导航栏留出空间 */
|
||||||
border-bottom: 1rpx solid #ccc;
|
border-bottom: 1rpx solid #ccc;
|
||||||
|
|
||||||
.header-cell {
|
.header-cell {
|
||||||
font-size: 28rpx;
|
font-size: 30rpx;
|
||||||
color: #333;
|
color: #333;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
||||||
@@ -224,17 +266,22 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 交易记录列表样式
|
// 交易记录列表样式
|
||||||
.transaction-list {
|
.transaction-list {
|
||||||
background-color: #f5f5f5;
|
top:calc(var(--status-bar-height) + 44px + 130rpx);
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0rpx;
|
||||||
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.transaction-item {
|
.transaction-item {
|
||||||
background-color: #f8f8f8;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 20rpx 30rpx;
|
padding: 20rpx 30rpx;
|
||||||
border-bottom: 1rpx solid #e5e5e5;
|
border-bottom: 1rpx solid #e5e5e5;
|
||||||
|
|
||||||
.cell {
|
.cell {
|
||||||
font-size: 26rpx;
|
font-size: 30rpx;
|
||||||
|
|
||||||
&.business-type {
|
&.business-type {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@@ -245,7 +292,7 @@ onMounted(() => {
|
|||||||
&.user {
|
&.user {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #ff0000;
|
color: #8B2316;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.date-amount {
|
&.date-amount {
|
||||||
@@ -257,7 +304,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
.date {
|
.date {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: #666;
|
color: #999;
|
||||||
margin-bottom: 4rpx;
|
margin-bottom: 4rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,11 +312,11 @@ onMounted(() => {
|
|||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
|
|
||||||
&.positive {
|
&.positive {
|
||||||
color: #ff0000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.negative {
|
&.negative {
|
||||||
color: #666;
|
color: #000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="my-account-page">
|
<view class="my-account-page">
|
||||||
<!-- 顶部导航栏 -->
|
<!-- 顶部导航栏 -->
|
||||||
<uni-nav-bar
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
left-icon="left"
|
left-icon="left"
|
||||||
title="我的账户"
|
title="我的账户"
|
||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
></uni-nav-bar>
|
></uni-nav-bar>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 账户余额区域 -->
|
<view class="contentbox">
|
||||||
|
<!-- 账户余额区域 -->
|
||||||
<view class="account-summary">
|
<view class="account-summary">
|
||||||
<view class="profile-section">
|
<view class="profile-section">
|
||||||
<image class="profile-avatar" :src="avatar" mode="aspectFill"></image>
|
<image class="profile-avatar" :src="avatar" mode="aspectFill"></image>
|
||||||
@@ -21,7 +23,7 @@
|
|||||||
<text class="balance-amount">{{ (accountBalance/100).toFixed(2) }}</text>
|
<text class="balance-amount">{{ (accountBalance/100).toFixed(2) }}</text>
|
||||||
|
|
||||||
<!-- 账户信息详情 -->
|
<!-- 账户信息详情 -->
|
||||||
<view class="account-details">
|
<!-- <view class="account-details">
|
||||||
<view class="detail-item">
|
<view class="detail-item">
|
||||||
<text class="detail-label">单次提现限额</text>
|
<text class="detail-label">单次提现限额</text>
|
||||||
<text class="detail-value">{{ (withdrawalBalanceMaxOnce/100).toFixed(2) }}元</text>
|
<text class="detail-value">{{ (withdrawalBalanceMaxOnce/100).toFixed(2) }}元</text>
|
||||||
@@ -34,35 +36,36 @@
|
|||||||
<text class="detail-label">最低提现金额</text>
|
<text class="detail-label">最低提现金额</text>
|
||||||
<text class="detail-value">{{ (lessWithdrawalBalance/100).toFixed(2) }}元</text>
|
<text class="detail-value">{{ (lessWithdrawalBalance/100).toFixed(2) }}元</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view> -->
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 操作选项 -->
|
<!-- 操作选项 -->
|
||||||
<view class="action-items">
|
<view class="action-items">
|
||||||
<view class="action-item" @click="handleWithdrawal">
|
<view class="action-item" @click="handleWithdrawal">
|
||||||
<view class="action-icon withdrawal-icon">
|
<view class="action-icon withdrawal-icon">
|
||||||
<text class="icon-text">💰</text>
|
<image class="icon-img" :src="withdrawalsIcon" mode="aspectFit"></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="action-content">
|
<view class="action-content">
|
||||||
<text class="action-title">提现</text>
|
<text class="action-title">提现</text>
|
||||||
<text class="action-subtitle">提现金额不得少于{{ (lessWithdrawalBalance/100).toFixed(2) }}元</text>
|
<text class="action-subtitle">提现金额不得少于{{ (lessWithdrawalBalance/100).toFixed(2) }}元</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="action-arrow">></text>
|
<uni-icons type="right" size="25" color="#999"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="action-item" @click="handleBillDetails">
|
<view class="action-item" @click="handleBillDetails">
|
||||||
<view class="action-icon bill-icon">
|
<view class="action-icon bill-icon">
|
||||||
<text class="icon-text">📋</text>
|
<image class="icon-img" :src="accountIcon" mode="aspectFit"></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="action-content">
|
<view class="action-content">
|
||||||
<text class="action-title">账单明细</text>
|
<text class="action-title">账单明细</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="action-arrow">></text>
|
<uni-icons type="right" size="25" color="#999"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 底部指示器 -->
|
<!-- 底部指示器 -->
|
||||||
<view class="bottom-indicator"></view>
|
<!-- <view class="bottom-indicator"></view> -->
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -70,6 +73,27 @@
|
|||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import api from '@/api/api.js'
|
import api from '@/api/api.js'
|
||||||
import docUrl from '@/utils/docUrl'
|
import docUrl from '@/utils/docUrl'
|
||||||
|
import withdrawalsIcon from '@/static/withdrawals.png'
|
||||||
|
import accountIcon from '@/static/account_icon.png'
|
||||||
|
import { onLoad,onBackPress,onShow } from '@dcloudio/uni-app';
|
||||||
|
const from = ref('');
|
||||||
|
onLoad((options) => {
|
||||||
|
if(options.from){
|
||||||
|
from.value = options.from;
|
||||||
|
}
|
||||||
|
uni.sendNativeEvent("portraitReport",{
|
||||||
|
msg:{
|
||||||
|
event_nickname: "list_page",
|
||||||
|
page_type: "我的账户",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
onBackPress(() => {
|
||||||
|
if(!from.value){
|
||||||
|
plus.runtime.quit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const accountBalance = ref(0)
|
const accountBalance = ref(0)
|
||||||
const withdrawalBalanceMaxOnce = ref(0)
|
const withdrawalBalanceMaxOnce = ref(0)
|
||||||
@@ -77,7 +101,7 @@ const withdrawalBalanceFee = ref(0)
|
|||||||
const lessWithdrawalBalance = ref(0)
|
const lessWithdrawalBalance = ref(0)
|
||||||
const avatar = ref('')
|
const avatar = ref('')
|
||||||
|
|
||||||
onMounted(() => {
|
onShow(() => {
|
||||||
getMyAccount()
|
getMyAccount()
|
||||||
|
|
||||||
let userInfo= uni.getStorageSync('userInfo')
|
let userInfo= uni.getStorageSync('userInfo')
|
||||||
@@ -86,13 +110,17 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 方法
|
// 方法
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
uni.navigateBack()
|
if(!from.value){
|
||||||
|
plus.runtime.quit();
|
||||||
|
}else{
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleWithdrawal = () => {
|
const handleWithdrawal = () => {
|
||||||
if(accountBalance.value < lessWithdrawalBalance.value){
|
if(accountBalance.value < lessWithdrawalBalance.value){
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: `提现金额不得少于${(lessWithdrawalBalance/100).toFixed(2)}元`,
|
title: `提现金额不得少于${(lessWithdrawalBalance.value/100).toFixed(2)}元`,
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -111,8 +139,9 @@ const handleWithdrawal = () => {
|
|||||||
cancelText: '取消',
|
cancelText: '取消',
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if(res.confirm){
|
if(res.confirm){
|
||||||
|
const returnTo = encodeURIComponent('/pages_app/myAccount/myAccount')
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages_app/idcardAuth/bankCardList'
|
url: `/pages_app/idcardAuth/idcardAuth?returnTo=${returnTo}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,8 +152,9 @@ const handleWithdrawal = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleBillDetails = () => {
|
const handleBillDetails = () => {
|
||||||
|
const from = encodeURIComponent('myAccount')
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages_app/myAccount/billDetails'
|
url: `/pages_app/myAccount/billDetails?from=${from}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,6 +172,14 @@ const getMyAccount = async () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.contentbox{
|
||||||
|
position: fixed;
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
|
||||||
|
}
|
||||||
.my-account-page {
|
.my-account-page {
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
@@ -151,20 +189,19 @@ const getMyAccount = async () => {
|
|||||||
// 账户余额区域样式
|
// 账户余额区域样式
|
||||||
.account-summary {
|
.account-summary {
|
||||||
background: linear-gradient(135deg, #8B2316, #A0522D);
|
background: linear-gradient(135deg, #8B2316, #A0522D);
|
||||||
margin: 30rpx;
|
// margin: 30rpx;
|
||||||
border-radius: 20rpx;
|
// border-radius: 20rpx;
|
||||||
padding: 60rpx 40rpx;
|
padding: 30rpx 40rpx 10rpx;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
box-shadow: 0 8rpx 24rpx rgba(139, 35, 22, 0.3);
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.profile-section {
|
.profile-section {
|
||||||
margin-bottom: 40rpx;
|
margin-bottom: 10rpx;
|
||||||
|
|
||||||
.profile-avatar {
|
.profile-avatar {
|
||||||
width: 120rpx;
|
width: 120rpx;
|
||||||
height: 120rpx;
|
height: 120rpx;
|
||||||
border-radius: 60rpx;
|
border-radius: 20rpx;
|
||||||
border: 4rpx solid rgba(255, 255, 255, 0.3);
|
border: 4rpx solid rgba(255, 255, 255, 0.3);
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
@@ -174,18 +211,18 @@ const getMyAccount = async () => {
|
|||||||
display: block;
|
display: block;
|
||||||
color: rgba(255, 255, 255, 0.9);
|
color: rgba(255, 255, 255, 0.9);
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
margin-bottom: 20rpx;
|
margin-bottom: 10rpx;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.balance-amount {
|
.balance-amount {
|
||||||
display: block;
|
display: block;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-size: 72rpx;
|
font-size: 50rpx;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.2);
|
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.2);
|
||||||
letter-spacing: 2rpx;
|
letter-spacing: 2rpx;
|
||||||
margin-bottom: 40rpx;
|
margin-bottom: 0rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 账户信息详情样式
|
// 账户信息详情样式
|
||||||
@@ -223,15 +260,15 @@ const getMyAccount = async () => {
|
|||||||
// 操作选项样式
|
// 操作选项样式
|
||||||
.action-items {
|
.action-items {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
margin: 0 30rpx;
|
margin-top: 0rpx;
|
||||||
border-radius: 20rpx;
|
// border-radius: 20rpx;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
// box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||||
|
|
||||||
.action-item {
|
.action-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 40rpx 30rpx;
|
padding: 20rpx 30rpx;
|
||||||
border-bottom: 1rpx solid #f0f0f0;
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
transition: background-color 0.2s ease;
|
transition: background-color 0.2s ease;
|
||||||
|
|
||||||
@@ -256,6 +293,11 @@ const getMyAccount = async () => {
|
|||||||
.icon-text {
|
.icon-text {
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-img {
|
||||||
|
width: 34rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.withdrawal-icon {
|
.withdrawal-icon {
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="withdrawal-page">
|
<view class="withdrawal-page">
|
||||||
<!-- 顶部导航栏 -->
|
<!-- 顶部导航栏 -->
|
||||||
<uni-nav-bar
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
left-icon="left"
|
left-icon="left"
|
||||||
title="提现"
|
title="提现"
|
||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
></uni-nav-bar>
|
></uni-nav-bar>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 主内容区域 -->
|
<!-- 主内容区域 -->
|
||||||
<view class="main-content">
|
<view class="main-content">
|
||||||
@@ -25,20 +26,27 @@
|
|||||||
<text class="section-title">结算银行卡</text>
|
<text class="section-title">结算银行卡</text>
|
||||||
<text class="withdrawal-rules" @click="showWithdrawalRules">提现规则</text>
|
<text class="withdrawal-rules" @click="showWithdrawalRules">提现规则</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="divider"></view>
|
|
||||||
<view class="bank-card-info" @click="selectBankCard" v-if="selectedBankCard">
|
<view class="bank-card-info" @click="selectBankCard" v-if="selectedBankCard">
|
||||||
<view class="bank-logo">
|
<view class="bank-logo">
|
||||||
<text class="bank-icon">{{ selectedBankCard.bankName ? selectedBankCard.bankName.charAt(0) : '工' }}</text>
|
<image
|
||||||
|
v-if="getBankLogoImg(getBankName(selectedBankCard))"
|
||||||
|
class="bank-logo-img"
|
||||||
|
:src="getBankLogoImg(getBankName(selectedBankCard))"
|
||||||
|
mode="aspectFit"
|
||||||
|
></image>
|
||||||
|
<view v-else class="logo-bg">
|
||||||
|
<text class="bank-icon">{{ getBankLogo(getBankName(selectedBankCard)) }}</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="bank-details">
|
<view class="bank-details">
|
||||||
<text class="bank-name">{{ selectedBankCard.bankName || '工商银行' }}</text>
|
<text class="bank-name">{{ getBankName(selectedBankCard) || '工商银行' }}</text>
|
||||||
<text class="bank-card-number">尾号为{{ selectedBankCard.cardNumber ? selectedBankCard.cardNumber.slice(-4) : '8937' }}储蓄卡</text>
|
<text class="bank-card-number">尾号为{{ getCardTail(selectedBankCard) }}储蓄卡</text>
|
||||||
</view>
|
</view>
|
||||||
<text class="arrow-icon">›</text>
|
<uni-icons type="right" size="25" color="#999"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
<view class="no-bank-card" v-else>
|
<view class="no-bank-card" v-else>
|
||||||
<text class="no-card-text">请先添加银行卡</text>
|
<text class="no-card-text">请先添加银行卡</text>
|
||||||
<text class="arrow-icon">›</text>
|
<uni-icons type="right" size="25" color="#999"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
<view class="divider"></view>
|
<view class="divider"></view>
|
||||||
</view>
|
</view>
|
||||||
@@ -48,12 +56,12 @@
|
|||||||
<text class="amount-title">提现金额</text>
|
<text class="amount-title">提现金额</text>
|
||||||
<view class="amount-display">
|
<view class="amount-display">
|
||||||
<text class="currency-symbol">¥</text>
|
<text class="currency-symbol">¥</text>
|
||||||
<text class="amount-value">{{ withdrawalAmount }}</text>
|
<text class="amount-value">{{ withdrawalAmount}}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="amount-details">
|
<view class="amount-details">
|
||||||
<text class="tax-info">扣除个人所得税<text class="highlight-red">{{ (incomeTax / 100).toFixed(2) }}元</text></text>
|
<text class="tax-info">扣除个人所得税<text class="highlight-red">{{ incomeTax}}元</text></text>
|
||||||
<text class="fee-info">扣除提现手续费<text class="highlight-red">{{ (withdrawalBalanceFee / 100).toFixed(2) }}元</text></text>
|
<!-- <text class="fee-info">扣除提现手续费<text class="highlight-red">{{ (withdrawalBalanceFee / 100).toFixed(2) }}元</text></text> -->
|
||||||
<text class="actual-amount">此次提现实际到账<text class="highlight-red">{{ actualAmount }}元</text></text>
|
<text class="actual-amount">此次提现实际到账<text class="highlight-red">{{ actualAmount}}元</text></text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -132,10 +140,11 @@ onMounted(() => {
|
|||||||
// 计算提现金额
|
// 计算提现金额
|
||||||
const calculateAmounts = () => {
|
const calculateAmounts = () => {
|
||||||
// 提现金额 = 账户余额 - 个人所得税 - 提现手续费
|
// 提现金额 = 账户余额 - 个人所得税 - 提现手续费
|
||||||
const totalDeduction = incomeTax.value + withdrawalBalanceFee.value
|
// const totalDeduction = incomeTax.value + withdrawalBalanceFee.value
|
||||||
const amount = accountBalance.value - totalDeduction
|
// const amount = accountBalance.value - totalDeduction
|
||||||
withdrawalAmount.value = accountBalance.value > 0 ? (accountBalance.value/100).toFixed(2) : '0.00'
|
// withdrawalAmount.value = accountBalance.value > 0 ? (accountBalance.value/100).toFixed(2) : '0.00'
|
||||||
actualAmount.value = amount > 0 ? (amount/100).toFixed(2) : '0.00'
|
// actualAmount.value = amount > 0 ? (amount/100).toFixed(2) : '0.00'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
@@ -162,6 +171,63 @@ const goBack = () => {
|
|||||||
uni.navigateBack()
|
uni.navigateBack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bankLogoMap = {
|
||||||
|
'工商银行': '/static/icon_bankcard_gongshang.png',
|
||||||
|
'中国银行': '/static/icon_bankcard_zhongguo.png',
|
||||||
|
'建设银行': '/static/icon_bankcard_jianseyinhang.png',
|
||||||
|
'农业银行': '/static/icon_bankcard_nongyeyinhang.png',
|
||||||
|
'交通银行': '/static/icon_bankcard_jiatong.png',
|
||||||
|
'招商银行': '/static/icon_bankcard_zhaoshangyinhang.png',
|
||||||
|
'民生银行': '/static/icon_bankcard_minshneg.png',
|
||||||
|
'兴业银行': '/static/icon_bankcard_xingye.png',
|
||||||
|
'浦发银行': '/static/icon_bankcard_shanghaipudongfazhanyinhang.png',
|
||||||
|
'光大银行': '/static/icon_bankcard_guangda.png',
|
||||||
|
'华夏银行': '/static/icon_bankcard_huaxiayinhnag.png',
|
||||||
|
'中信银行': '/static/icon_bankcard_zhongxinshiye.png',
|
||||||
|
'平安银行': '/static/icon_bankcard_pingan.png',
|
||||||
|
'广发银行': '/static/icon_bankcard_guangfa.png',
|
||||||
|
'邮储银行': '/static/icon_bankcard_youzheng.png',
|
||||||
|
'上海银行': '/static/icon_bankcard_shanghai.png',
|
||||||
|
'北京银行': '/static/icon_bankcard_beijingyinhang.png'
|
||||||
|
}
|
||||||
|
|
||||||
|
const getBankName = (card) => {
|
||||||
|
if (!card) return ''
|
||||||
|
return card.bankName || card.open_bank || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCardTail = (card) => {
|
||||||
|
if (!card) return '8937'
|
||||||
|
const raw = card.cardNumber || card.card_number || ''
|
||||||
|
return raw ? String(raw).slice(-4) : '8937'
|
||||||
|
}
|
||||||
|
|
||||||
|
const getBankLogoImg = (bankName) => {
|
||||||
|
return bankLogoMap[bankName] || ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const getBankLogo = (bankName) => {
|
||||||
|
const bankLogos = {
|
||||||
|
'工商银行': '工',
|
||||||
|
'中国银行': '中',
|
||||||
|
'建设银行': '建',
|
||||||
|
'农业银行': '农',
|
||||||
|
'交通银行': '交',
|
||||||
|
'招商银行': '招',
|
||||||
|
'民生银行': '民',
|
||||||
|
'兴业银行': '兴',
|
||||||
|
'浦发银行': '浦',
|
||||||
|
'光大银行': '光',
|
||||||
|
'华夏银行': '华',
|
||||||
|
'中信银行': '信',
|
||||||
|
'平安银行': '平',
|
||||||
|
'广发银行': '广',
|
||||||
|
'邮储银行': '邮'
|
||||||
|
}
|
||||||
|
if (!bankName) return '工'
|
||||||
|
return bankLogos[bankName] || bankName.charAt(0)
|
||||||
|
}
|
||||||
|
|
||||||
// 获取我的账户信息
|
// 获取我的账户信息
|
||||||
const getMyAccount = async () => {
|
const getMyAccount = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -173,7 +239,7 @@ const getMyAccount = async () => {
|
|||||||
withdrawalBalanceFee.value = res.data.withdrawalBalanceFee
|
withdrawalBalanceFee.value = res.data.withdrawalBalanceFee
|
||||||
lessWithdrawalBalance.value = res.data.lessWithdrawalBalance
|
lessWithdrawalBalance.value = res.data.lessWithdrawalBalance
|
||||||
// 获取账户信息后计算金额
|
// 获取账户信息后计算金额
|
||||||
calculateAmounts()
|
//calculateAmounts()
|
||||||
// 然后获取个人所得税
|
// 然后获取个人所得税
|
||||||
getIncomeTax(accountBalance.value)
|
getIncomeTax(accountBalance.value)
|
||||||
}
|
}
|
||||||
@@ -187,10 +253,13 @@ const getIncomeTax = async (amount) => {
|
|||||||
try {
|
try {
|
||||||
const res = await api.getIncomeTax({amount: amount})
|
const res = await api.getIncomeTax({amount: amount})
|
||||||
console.log('个人所得税:', res)
|
console.log('个人所得税:', res)
|
||||||
if (res && res.code === 200 && res.data) {
|
if (res.code ==200) {
|
||||||
incomeTax.value = res.data.incomeTax || 0
|
incomeTax.value = (res.data.tax/100).toFixed(2) || 0
|
||||||
|
withdrawalAmount.value = (amount/100).toFixed(2) || 0
|
||||||
|
actualAmount.value = (res.data.actual_amount/100).toFixed(2) || 0
|
||||||
|
|
||||||
// 获取税费后重新计算金额
|
// 获取税费后重新计算金额
|
||||||
calculateAmounts()
|
//calculateAmounts()
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取个人所得税失败:', error)
|
console.error('获取个人所得税失败:', error)
|
||||||
@@ -214,8 +283,9 @@ const getBankCardList = async () => {
|
|||||||
confirmText: '去添加',
|
confirmText: '去添加',
|
||||||
success: (modalRes) => {
|
success: (modalRes) => {
|
||||||
if (modalRes.confirm) {
|
if (modalRes.confirm) {
|
||||||
|
const returnTo = encodeURIComponent('/pages_app/myAccount/withdrawal?from=bankCardList')
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages_app/idcardAuth/bankCardList'
|
url: `/pages_app/idcardAuth/bankCardList?from=withdrawal&returnTo=${returnTo}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,7 +308,7 @@ const selectBankCard = () => {
|
|||||||
|
|
||||||
// 这里可以实现银行卡选择逻辑
|
// 这里可以实现银行卡选择逻辑
|
||||||
uni.showActionSheet({
|
uni.showActionSheet({
|
||||||
itemList: bankCardList.value.map(card => `${card.bankName} 尾号${card.cardNumber.slice(-4)}`),
|
itemList: bankCardList.value.map(card => `${getBankName(card)} 尾号${getCardTail(card)}`),
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
selectedBankCard.value = bankCardList.value[res.tapIndex]
|
selectedBankCard.value = bankCardList.value[res.tapIndex]
|
||||||
}
|
}
|
||||||
@@ -252,8 +322,8 @@ const showWithdrawalRules = () => {
|
|||||||
const feeAmount = (withdrawalBalanceFee.value / 100).toFixed(2)
|
const feeAmount = (withdrawalBalanceFee.value / 100).toFixed(2)
|
||||||
|
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '提现规则',
|
title: '温馨提示',
|
||||||
content: `1. 提现金额不得少于${minAmount}元\n2. 单次提现限额为${maxAmount}元\n3. 提现手续费为${feeAmount}元\n4. 工作日24小时内到账`,
|
content: `提交成功后会有工作人员与您联系`,
|
||||||
showCancel: false,
|
showCancel: false,
|
||||||
confirmText: '我知道了'
|
confirmText: '我知道了'
|
||||||
})
|
})
|
||||||
@@ -278,15 +348,7 @@ const confirmWithdrawal = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查单次提现限额
|
|
||||||
const maxAmount = withdrawalBalanceMaxOnce.value / 100
|
|
||||||
if (parseFloat(withdrawalAmount.value) > maxAmount) {
|
|
||||||
uni.showToast({
|
|
||||||
title: `单次提现限额为${maxAmount.toFixed(2)}元`,
|
|
||||||
icon: 'none'
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 弹出短信验证码弹框
|
// 弹出短信验证码弹框
|
||||||
showSmsDialog.value = true
|
showSmsDialog.value = true
|
||||||
@@ -337,7 +399,8 @@ const onGetSmsCode = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('发送短信验证码失败:', error)
|
console.error('发送短信验证码失败:', error)
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '网络错误,请重试',
|
title:error.data.message || error.message || error.data.msg || error.msg || '频繁发送短信,请稍后再试'
|
||||||
|
,
|
||||||
icon: 'none'
|
icon: 'none'
|
||||||
})
|
})
|
||||||
} finally {
|
} finally {
|
||||||
@@ -405,7 +468,9 @@ const onCancelSms = () => {
|
|||||||
|
|
||||||
// 主内容区域
|
// 主内容区域
|
||||||
.main-content {
|
.main-content {
|
||||||
padding: 0 30rpx;
|
padding-top: calc(var(--status-bar-height) + 44px);
|
||||||
|
padding-bottom: 180rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@@ -433,7 +498,7 @@ const onCancelSms = () => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 30rpx 0;
|
padding: 30rpx;
|
||||||
|
|
||||||
.section-title {
|
.section-title {
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
@@ -448,30 +513,43 @@ const onCancelSms = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.divider {
|
.divider {
|
||||||
height: 1rpx;
|
height: 2rpx;
|
||||||
background-color: #f0f0f0;
|
background-color: #bab7b7;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bank-card-info {
|
.bank-card-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 30rpx 0;
|
padding: 30rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
|
|
||||||
.bank-logo {
|
.bank-logo {
|
||||||
width: 60rpx;
|
width: 60rpx;
|
||||||
height: 60rpx;
|
height: 60rpx;
|
||||||
background-color: #8B2316;
|
|
||||||
border-radius: 8rpx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
margin-right: 24rpx;
|
margin-right: 24rpx;
|
||||||
|
|
||||||
.bank-icon {
|
.bank-logo-img {
|
||||||
font-size: 32rpx;
|
width: 60rpx;
|
||||||
color: #ffffff;
|
height: 60rpx;
|
||||||
font-weight: bold;
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-bg {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
background: #E60012;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 2rpx solid #E60012;
|
||||||
|
|
||||||
|
.bank-icon {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -493,7 +571,7 @@ const onCancelSms = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.arrow-icon {
|
.arrow-icon {
|
||||||
font-size: 32rpx;
|
font-size: 62rpx;
|
||||||
color: #cccccc;
|
color: #cccccc;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
@@ -520,8 +598,8 @@ const onCancelSms = () => {
|
|||||||
|
|
||||||
// 金额区域
|
// 金额区域
|
||||||
.amount-section {
|
.amount-section {
|
||||||
padding: 40rpx 0;
|
padding: 40rpx 30rpx;
|
||||||
|
background-color: #ffffff;
|
||||||
.amount-title {
|
.amount-title {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
@@ -556,7 +634,7 @@ const onCancelSms = () => {
|
|||||||
margin-bottom: 12rpx;
|
margin-bottom: 12rpx;
|
||||||
|
|
||||||
.highlight-red {
|
.highlight-red {
|
||||||
color: #8B2316;
|
color: red;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -668,6 +746,10 @@ const onCancelSms = () => {
|
|||||||
color: #8B2316;
|
color: #8B2316;
|
||||||
font-size: 26rpx;
|
font-size: 26rpx;
|
||||||
border: none;
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
|
|||||||
+436
-238
@@ -1,272 +1,470 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="my-answer-page">
|
<view class="my-answer-page">
|
||||||
<navBar title="我的意见" />
|
<navBar title="我的意见" />
|
||||||
|
|
||||||
<scroll-view scroll-y class="content-scroll">
|
<scroll-view scroll-y class="content-scroll">
|
||||||
<!-- 文本输入 -->
|
<!-- 文本输入 -->
|
||||||
<view class="card">
|
<view class="card">
|
||||||
<view class="card-title">我的意见 <text class="required">*</text></view>
|
<view class="card-title">我的意见 <text class="required">*</text></view>
|
||||||
<view class="textarea-wrap">
|
<view class="textarea-wrap">
|
||||||
<textarea
|
<textarea
|
||||||
v-model="form.note"
|
v-model="note"
|
||||||
class="textarea"
|
class="textarea"
|
||||||
:maxlength="300"
|
:maxlength="300"
|
||||||
placeholder="请依据患者的个人信息、疾病资料及患者所咨询的问题详细解答患者的问题(信息仅提问患者及医生可见,最多输入300个字)"
|
placeholder="请依据患者的个人信息、疾病资料及患者所咨询的问题详细解答患者的问题(信息仅提问患者及医生可见,最多输入300个字)"
|
||||||
placeholder-class="ph"
|
placeholder-class="ph"
|
||||||
auto-height
|
auto-height
|
||||||
/>
|
:adjust-position="false"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 图片上传 -->
|
<!-- 图片上传 -->
|
||||||
<view class="card">
|
<view class="card">
|
||||||
<view class="card-title">相关图片</view>
|
<view class="card-title">相关图片</view>
|
||||||
<view class="sub-tip">可以用部分科普或文献来协助回答问题,最多6张</view>
|
<view class="sub-tip">可以用部分科普或文献来协助回答问题,最多6张</view>
|
||||||
<view class="img-grid">
|
<!-- <view class="imgbox">
|
||||||
<view
|
<uni-file-picker limit="6" v-model="tempImageList" file-mediatype="image" :auto-upload="false" @select="selectImages" @delete="deleteImages" ></uni-file-picker>
|
||||||
v-if="imgList.length>0"
|
</view> -->
|
||||||
v-for="(img, index) in imgList"
|
<view class="img-grid">
|
||||||
:key="index"
|
<view
|
||||||
class="img-item"
|
v-if="tempImageList.length > 0"
|
||||||
@click="preview(index)"
|
v-for="(img, index) in tempImageList"
|
||||||
>
|
:key="index"
|
||||||
<image :src="docUrl+img" mode="aspectFill" class="img" />
|
class="img-item"
|
||||||
<view class="del" @click.stop="remove(index)">×</view>
|
@click="preview(index)"
|
||||||
</view>
|
>
|
||||||
<view v-if="imgList.length < maxImages" class="img-item add" @click="addImages">
|
<image :src="img" mode="aspectFill" class="img" />
|
||||||
<view class="plus">+</view>
|
<view class="del" @click.stop="remove(index)">×</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
<view
|
||||||
</view>
|
v-if="tempImageList.length < maxImages"
|
||||||
</scroll-view>
|
class="img-item add"
|
||||||
|
@click="beforeAddImages"
|
||||||
<!-- 底部提交 -->
|
>
|
||||||
<view class="bottom-fixed">
|
<view class="plus">+</view>
|
||||||
<view class="submit-btn" @click="submit">提交</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
<!-- <button style="position: fixed;bottom: 200rpx;left: 50%;transform: translateX(-50%);z-index: 99999999999;" @click="test" >测试</button> -->
|
||||||
|
<!-- 底部提交 -->
|
||||||
|
<view class="bottom-fixed">
|
||||||
|
<view class="submit-btn" @click="submit">提交</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from "vue";
|
||||||
import navBar from '@/components/navBar/navBar.vue'
|
import navBar from "@/components/navBar/navBar.vue";
|
||||||
import api from '@/api/api'
|
import api from "@/api/api";
|
||||||
import docUrl from '@/utils/docUrl'
|
import docUrl from "@/utils/docUrl";
|
||||||
import { onLoad,onShow } from '@dcloudio/uni-app'
|
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||||
const uuid=ref('');
|
import { pathToBase64 } from "image-tools";
|
||||||
|
import { getCameraPermission } from "@/utils/permission.js";
|
||||||
|
import isAndroid from "@/utils/platform.js";
|
||||||
|
const uuid = ref("");
|
||||||
|
const answer_uuid = ref("");
|
||||||
const maxImages = 6;
|
const maxImages = 6;
|
||||||
const imgList = ref([]);
|
const imgList = ref([]);
|
||||||
const form = ref({
|
const isLock = ref(false);
|
||||||
note: '',
|
const tempImageList = ref([]);
|
||||||
images: []
|
const note = ref("");
|
||||||
})
|
|
||||||
onLoad((options) => {
|
onLoad((options) => {
|
||||||
uuid.value = options.uuid || ''
|
uuid.value = options.uuid || "";
|
||||||
})
|
answer_uuid.value = options.answer_uuid || "";
|
||||||
const getInterrogation=()=>{
|
getInterrogation();
|
||||||
api.getInterrogation({
|
});
|
||||||
uuid:uuid.value
|
const beforeAddImages = () => {
|
||||||
}).then(res=>{
|
if (isAndroid) {
|
||||||
console.log(res)
|
getCameraPermission(addImages);
|
||||||
if(res.code === '200' && res.data) {
|
} else {
|
||||||
let user=uni.getStorageSync('userInfo');
|
addImages();
|
||||||
let arr=res.data.AnswerList.filter(item=>{
|
}
|
||||||
return user.uuid == item.expert_uuid
|
};
|
||||||
})
|
const getInterrogation = () => {
|
||||||
|
api
|
||||||
form.value= arr[0];
|
.getInterrogation({
|
||||||
imgList.value= form.value.imgs?form.value.imgs.split(','):[];
|
uuid: uuid.value,
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const updateInterrogationAnswer=()=>{
|
|
||||||
let imgobj={};
|
|
||||||
if(imgList.value.length>0){
|
|
||||||
let count=0;
|
|
||||||
imgList.value.forEach(item=>{
|
|
||||||
imgobj['img'+count]=docUrl+item;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
api.updateInterrogationAnswer({
|
|
||||||
answer_uuid: answer_uuid.value,
|
|
||||||
note: form.value.note,
|
|
||||||
imgsBean: imgobj
|
|
||||||
}).then(res=>{
|
|
||||||
if(res.code == 200){
|
|
||||||
uni.showToast({title: '提交成功', icon: 'none'})
|
|
||||||
uni.navigateBack()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const addInterrogationAnswer=()=>{
|
|
||||||
api.addInterrogationAnswer({
|
|
||||||
note: form.value.note,
|
|
||||||
imgsBean: imgobj
|
|
||||||
}).then(res=>{
|
|
||||||
if(res.code == 200){
|
|
||||||
uni.showToast({title: '提交成功', icon: 'none'})
|
|
||||||
uni.navigateBack()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
.then((res) => {
|
||||||
onShow(()=>{
|
console.log(res);
|
||||||
getInterrogation()
|
if (res.code === "200" && res.data) {
|
||||||
})
|
let user = uni.getStorageSync("userInfo");
|
||||||
function addImages(){
|
let arr = res.data.AnswerList.filter((item) => {
|
||||||
const remain = maxImages - form.value.images.length
|
return user.uuid == item.expert_uuid;
|
||||||
if(remain <= 0){
|
});
|
||||||
uni.showToast({title: '最多6张', icon: 'none'})
|
imgList.value = [];
|
||||||
return
|
if (arr && arr.length > 0) {
|
||||||
}
|
note.value = arr[0].note || "";
|
||||||
uni.chooseImage({
|
let imgs = arr[0].imgs ? arr[0].imgs.split(",") : [];
|
||||||
count: remain,
|
tempImageList.value = imgs.map((item, index) => {
|
||||||
sizeType: ['compressed'],
|
return {
|
||||||
sourceType: ['album','camera'],
|
name: "图片" + index + 1,
|
||||||
success: (res)=>{
|
url: docUrl + item,
|
||||||
const paths = (res.tempFilePaths || res.tempFiles?.map(f=>f.path) || [])
|
};
|
||||||
imgList.value = imgList.value.concat(paths).slice(0, maxImages)
|
});
|
||||||
}
|
tempImageList.value = imgs.map((item) => docUrl + item);
|
||||||
})
|
for (let i = 0; i < imgs.length; i++) {
|
||||||
|
uni.request({
|
||||||
|
url: docUrl + imgs[i],
|
||||||
|
method: "GET",
|
||||||
|
responseType: "arraybuffer",
|
||||||
|
success: (res) => {
|
||||||
|
const base64 = `${uni.arrayBufferToBase64(res.data)}`;
|
||||||
|
imgList.value.push(base64);
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
reject(err);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const updateInterrogationAnswer = () => {
|
||||||
|
if (note.value.trim().length < 5) {
|
||||||
|
uni.showToast({ title: "输入意见至少5个字", icon: "none" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isLock.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isLock.value = true;
|
||||||
|
let imgobj = {};
|
||||||
|
if (imgList.value.length > 0) {
|
||||||
|
let count = 0;
|
||||||
|
imgList.value.forEach((item, index) => {
|
||||||
|
imgobj["img" + (index + 1)] = item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
api
|
||||||
|
.updateInterrogationAnswer({
|
||||||
|
uuid: answer_uuid.value,
|
||||||
|
note: note.value,
|
||||||
|
imgsBean: imgobj,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
isLock.value = false;
|
||||||
|
if (res.code == 200) {
|
||||||
|
uni.showToast({ title: "提交成功", icon: "none" });
|
||||||
|
uni.$emit("updateStatus", 1);
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const test = () => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: "/pages/upload/upload",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const addInterrogationAnswer = () => {
|
||||||
|
if (note.value.trim().length < 5) {
|
||||||
|
uni.showToast({ title: "输入意见至少5个字", icon: "none" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isLock.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isLock.value = true;
|
||||||
|
let imgobj = {};
|
||||||
|
if (imgList.value.length > 0) {
|
||||||
|
imgList.value.forEach((item, index) => {
|
||||||
|
imgobj["img" + (index + 1)] = item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
api
|
||||||
|
.addInterrogationAnswer({
|
||||||
|
step1_uuid: uuid.value,
|
||||||
|
note: note.value,
|
||||||
|
imgsBean: imgobj,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
isLock.value = false;
|
||||||
|
if (res.code == 200) {
|
||||||
|
uni.$emit("updateStatus", 1);
|
||||||
|
uni.showToast({ title: "提交成功", icon: "none" });
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const selectImages = (e) => {
|
||||||
|
let tempFilePaths = e.tempFiles;
|
||||||
|
console.log(e);
|
||||||
|
tempImageList.value = [...tempImageList.value, ...tempFilePaths];
|
||||||
|
for (let i = 0; i < tempFilePaths.length; i++) {
|
||||||
|
pathToBase64(tempFilePaths[i].url)
|
||||||
|
.then((base64) => {
|
||||||
|
console.log("转base64成功");
|
||||||
|
imgList.value.push(base64.split(",")[1]);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log("转base64成功");
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.log(tempImageList.value);
|
||||||
|
console.log(imgList.value);
|
||||||
|
};
|
||||||
|
const addImages = () => {
|
||||||
|
const remain = maxImages - imgList.value.length;
|
||||||
|
if (remain <= 0) {
|
||||||
|
uni.showToast({ title: "最多6张", icon: "none" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log("执行选择图片");
|
||||||
|
console.log('isAndroid:'+isAndroid)
|
||||||
|
if (isAndroid) {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: remain,
|
||||||
|
sizeType: ["original", "compressed"],
|
||||||
|
sourceType: ["album", "camera"],
|
||||||
|
success: (res) => {
|
||||||
|
console.log("获取到照片");
|
||||||
|
console.log(res.tempFilePaths);
|
||||||
|
tempImageList.value = [...tempImageList.value, ...res.tempFilePaths];
|
||||||
|
for (let i = 0; i < res.tempFilePaths.length; i++) {
|
||||||
|
uni.saveFile({
|
||||||
|
tempFilePath: res.tempFilePaths[i],
|
||||||
|
success: (res1) => {
|
||||||
|
pathToBase64(res1.savedFilePath)
|
||||||
|
.then((base64) => {
|
||||||
|
console.log("转base64成功");
|
||||||
|
imgList.value.push(base64.split(",")[1]);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log("转base64失败");
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
uni.chooseImage({
|
||||||
|
count: remain,
|
||||||
|
sourceType: ["album", "camera"],
|
||||||
|
crop: {
|
||||||
|
width: 375,
|
||||||
|
height: 500,
|
||||||
|
resize: true,
|
||||||
|
quality:100,
|
||||||
|
},
|
||||||
|
success: (res) => {
|
||||||
|
console.log("获取到照片");
|
||||||
|
console.log(res.tempFilePaths);
|
||||||
|
tempImageList.value = [...tempImageList.value, ...res.tempFilePaths];
|
||||||
|
for (let i = 0; i < res.tempFilePaths.length; i++) {
|
||||||
|
uni.getImageInfo({
|
||||||
|
src: res.tempFilePaths[i],
|
||||||
|
success: (result) => {
|
||||||
|
console.log(result);
|
||||||
|
if (result.width > 1000) {
|
||||||
|
uni.compressImage({
|
||||||
|
quality:100,
|
||||||
|
src: res.tempFilePaths[i],
|
||||||
|
success: (result2) => {
|
||||||
|
console.log("压缩成功");
|
||||||
|
console.log(result2.tempFilePath);
|
||||||
|
pathToBase64(result2.tempFilePath)
|
||||||
|
.then((base64) => {
|
||||||
|
console.log("转base64成功");
|
||||||
|
imgList.value.push(base64.split(",")[1]);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log("转base64失败");
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.log("压缩失败:" + err.errMsg);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
pathToBase64(res.tempFilePaths[i])
|
||||||
|
.then((base64) => {
|
||||||
|
console.log("转base64成功");
|
||||||
|
imgList.value.push(base64.split(",")[1]);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log("转base64失败");
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.log("获取图片信息失败:");
|
||||||
|
console.error(err.errMsg);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
function preview(index) {
|
||||||
|
uni.previewImage({
|
||||||
|
urls: tempImageList.value,
|
||||||
|
current: index,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function preview(index){
|
function remove(index) {
|
||||||
uni.previewImage({
|
imgList.value.splice(index, 1);
|
||||||
urls:imgList.map(path=> docUrl + path),
|
tempImageList.value.splice(index, 1);
|
||||||
current: index
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
const deleteImages = (e) => {
|
||||||
|
let index = e.index;
|
||||||
|
imgList.value.splice(index, 1);
|
||||||
|
tempImageList.value.splice(index, 1);
|
||||||
|
};
|
||||||
|
|
||||||
function remove(index){
|
function submit() {
|
||||||
imgList.valuesplice(index, 1)
|
if (answer_uuid.value) {
|
||||||
}
|
updateInterrogationAnswer();
|
||||||
|
} else {
|
||||||
function submit(){
|
addInterrogationAnswer();
|
||||||
if(!form.value.note.trim()){
|
}
|
||||||
uni.showToast({title:'请输入意见', icon:'none'})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if(answer_uuid.value){
|
|
||||||
updateInterrogationAnswer()
|
|
||||||
}else{
|
|
||||||
addInterrogationAnswer()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.my-answer-page{
|
.my-answer-page {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-scroll{
|
.content-scroll {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 135rpx;
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 160rpx;
|
bottom: 160rpx;
|
||||||
padding: 24rpx 24rpx 0;
|
padding: 24rpx 24rpx 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card{
|
.card {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 16rpx;
|
border-radius: 16rpx;
|
||||||
padding: 24rpx;
|
padding: 24rpx;
|
||||||
margin-bottom: 24rpx;
|
margin-bottom: 24rpx;
|
||||||
}
|
}
|
||||||
.card-title{
|
.card-title {
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
color: #8B2316;
|
color: #8b2316;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-bottom: 16rpx;
|
margin-bottom: 16rpx;
|
||||||
}
|
}
|
||||||
.required{ color: #ff4d4f; }
|
.required {
|
||||||
|
color: #ff4d4f;
|
||||||
.textarea-wrap{
|
|
||||||
position: relative;
|
|
||||||
background: #f7f7f7;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
padding: 16rpx 88rpx 16rpx 16rpx;
|
|
||||||
}
|
|
||||||
.textarea{
|
|
||||||
min-height: 180rpx;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
.ph{ color:#999; }
|
|
||||||
.voice-btn{
|
|
||||||
position: absolute;
|
|
||||||
right: 16rpx;
|
|
||||||
bottom: 16rpx;
|
|
||||||
width: 64rpx;
|
|
||||||
height: 64rpx;
|
|
||||||
border-radius: 32rpx;
|
|
||||||
background: #b90f0f;
|
|
||||||
color: #fff;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: 28rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sub-tip{
|
.textarea-wrap {
|
||||||
font-size: 26rpx;
|
position: relative;
|
||||||
color: #999;
|
background: #f7f7f7;
|
||||||
margin-bottom: 16rpx;
|
border-radius: 12rpx;
|
||||||
|
padding: 16rpx 16rpx 16rpx 16rpx;
|
||||||
|
}
|
||||||
|
.textarea {
|
||||||
|
min-height: 180rpx;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.ph {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.voice-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: 16rpx;
|
||||||
|
bottom: 16rpx;
|
||||||
|
width: 64rpx;
|
||||||
|
height: 64rpx;
|
||||||
|
border-radius: 32rpx;
|
||||||
|
background: #b90f0f;
|
||||||
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 28rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.img-grid{
|
.sub-tip {
|
||||||
display: grid;
|
font-size: 26rpx;
|
||||||
grid-template-columns: repeat(4, 1fr);
|
color: #999;
|
||||||
gap: 16rpx;
|
margin-bottom: 16rpx;
|
||||||
}
|
|
||||||
.img-item{
|
|
||||||
position: relative;
|
|
||||||
width:150rpx;
|
|
||||||
height: 150rpx;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
background: #f0f0f0;
|
|
||||||
}
|
|
||||||
.img{ width: 100%; height: 100%; }
|
|
||||||
.add{ display:flex; align-items:center; justify-content:center; }
|
|
||||||
.plus{ font-size: 80rpx; color:#c0c0c0; line-height: 1; }
|
|
||||||
.del{
|
|
||||||
position: absolute;
|
|
||||||
top: 8rpx;
|
|
||||||
right: 8rpx;
|
|
||||||
width: 44rpx;
|
|
||||||
height: 44rpx;
|
|
||||||
border-radius: 22rpx;
|
|
||||||
background: rgba(0,0,0,.5);
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
line-height: 44rpx;
|
|
||||||
font-size: 28rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottom-fixed{
|
.img-grid {
|
||||||
position: fixed;
|
display: grid;
|
||||||
left: 0; right: 0; bottom: 0;
|
grid-template-columns: repeat(4, 1fr);
|
||||||
background: #fff;
|
gap: 16rpx;
|
||||||
padding: 24rpx;
|
|
||||||
box-shadow: 0 -2rpx 10rpx rgba(0,0,0,.06);
|
|
||||||
}
|
}
|
||||||
.submit-btn{
|
.img-item {
|
||||||
width: 100%;
|
position: relative;
|
||||||
height: 88rpx;
|
width: 150rpx;
|
||||||
line-height: 88rpx;
|
height: 150rpx;
|
||||||
text-align: center;
|
border-radius: 12rpx;
|
||||||
background: #00bcd4;
|
overflow: hidden;
|
||||||
color: #fff;
|
background: #f0f0f0;
|
||||||
font-size: 32rpx;
|
}
|
||||||
border-radius: 16rpx;
|
.img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.add {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.plus {
|
||||||
|
font-size: 80rpx;
|
||||||
|
color: #c0c0c0;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
.del {
|
||||||
|
position: absolute;
|
||||||
|
top: 8rpx;
|
||||||
|
right: 8rpx;
|
||||||
|
width: 44rpx;
|
||||||
|
height: 44rpx;
|
||||||
|
border-radius: 22rpx;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 44rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-fixed {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: #fff;
|
||||||
|
padding: 24rpx;
|
||||||
|
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
.submit-btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 88rpx;
|
||||||
|
line-height: 88rpx;
|
||||||
|
text-align: center;
|
||||||
|
background: #3cc7c0;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 32rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="my-application-page">
|
<view class="my-application-page">
|
||||||
<!-- 顶部导航栏 -->
|
<!-- 顶部导航栏 -->
|
||||||
<uni-nav-bar
|
<view class="navBox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
left-icon="left"
|
left-icon="left"
|
||||||
title="我的应用"
|
title="我的应用"
|
||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
>
|
>
|
||||||
@@ -17,6 +19,7 @@
|
|||||||
}}</text>
|
}}</text>
|
||||||
</template>
|
</template>
|
||||||
</uni-nav-bar>
|
</uni-nav-bar>
|
||||||
|
</view>
|
||||||
|
|
||||||
<scroll-view class="content" scroll-y>
|
<scroll-view class="content" scroll-y>
|
||||||
<!-- 我的应用部分 -->
|
<!-- 我的应用部分 -->
|
||||||
@@ -102,6 +105,14 @@
|
|||||||
|
|
||||||
// 获取用户图标数据
|
// 获取用户图标数据
|
||||||
const addUserIcon = () => {
|
const addUserIcon = () => {
|
||||||
|
if(myApps.value.length <3){
|
||||||
|
uni.showToast({
|
||||||
|
title: '至少添加3个应用',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 1500
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
api.addUserIcon({
|
api.addUserIcon({
|
||||||
idStr:myApps.value.map(item => item.id).join(',')
|
idStr:myApps.value.map(item => item.id).join(',')
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
@@ -190,7 +201,7 @@
|
|||||||
navTo({
|
navTo({
|
||||||
url:url
|
url:url
|
||||||
})
|
})
|
||||||
}else if(app.name=="肝病新闻"){
|
}else if(app.name=="肝胆新闻"){
|
||||||
url='/pages_app/news/news'
|
url='/pages_app/news/news'
|
||||||
navTo({
|
navTo({
|
||||||
url:url
|
url:url
|
||||||
|
|||||||
+673
-89
@@ -1,13 +1,45 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="my-code-page">
|
<view class="navbox" v-if="!jieping">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
|
left-icon="left"
|
||||||
|
title="我的二维码"
|
||||||
|
@clickLeft="goBack"
|
||||||
|
color="#8B2316"
|
||||||
|
:border="false"
|
||||||
|
backgroundColor="#eeeeee"
|
||||||
|
>
|
||||||
|
<template #right>
|
||||||
|
<view class="nav-actions">
|
||||||
|
<view class="collect-img" @click="shareToggle" >
|
||||||
|
<image
|
||||||
|
class="share-img-icon"
|
||||||
|
:src="shareIcon"
|
||||||
|
mode="aspectFill"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</uni-nav-bar>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<!-- <navBar title="我的二维码" v-if="!jieping"/> -->
|
||||||
|
<!-- 自己实现的 html2canvas 截图组件 -->
|
||||||
|
<MyHtml2canvas
|
||||||
|
ref="shotRef"
|
||||||
|
domId="render-dom"
|
||||||
|
@renderOver="onRenderOver"
|
||||||
|
/>
|
||||||
|
<view class="my-code-page renderDom" id="render-dom" :class="{'active':jieping}">
|
||||||
|
<!-- <webview src="https://dev-wx.igandan.com/expert/expertcodeimg?expert_uuid=9UFkll2Xo57km6224XE&fromtype=doctor"></webview> -->
|
||||||
<!-- 顶部导航栏 -->
|
<!-- 顶部导航栏 -->
|
||||||
<navBar title="我的二维码" />
|
|
||||||
|
|
||||||
<!-- 内容 -->
|
<!-- 内容 -->
|
||||||
<scroll-view scroll-y class="page-scroll">
|
<scroll-view scroll-y class="page-scroll" id="pageContent">
|
||||||
<!-- 顶部蓝色横幅 -->
|
<!-- 顶部蓝色横幅 -->
|
||||||
<view class="blue-banner">
|
<view class="blue-banner">
|
||||||
<up-image :src="bgImg" width="100%" mode="widthFix" ></up-image>
|
<up-image :src="bgBase64 || bgImg" width="100%" mode="widthFix" ></up-image>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 白色信息卡 -->
|
<!-- 白色信息卡 -->
|
||||||
@@ -16,10 +48,17 @@
|
|||||||
<view class="leftCircle"></view>
|
<view class="leftCircle"></view>
|
||||||
<view class="rightCircle"></view>
|
<view class="rightCircle"></view>
|
||||||
<view class="halfCircle"></view>
|
<view class="halfCircle"></view>
|
||||||
<view class="avatar-wrapper">
|
<view class="star" v-if="userInfo.isStar==1">
|
||||||
<image class="avatar" :src="docUrl+userInfo.photo" mode="aspectFill" />
|
咨询专家
|
||||||
</view>
|
</view>
|
||||||
<view class="name-viewne">{{ userInfo.realName }} {{ userInfo.positionName }}</view>
|
<view class="avatar-wrapper">
|
||||||
|
<image
|
||||||
|
class="avatar"
|
||||||
|
:src="userInfo.avatarBase64 || userInfo.localPhoto || (docUrl+userInfo.photo)"
|
||||||
|
mode="aspectFill"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
<view class="name-viewne">{{ userInfo.realName }} <text class="position-name">{{ userInfo.positionName }}</text></view>
|
||||||
<view class="org-viewne">{{ userInfo.hospitalName }}</view>
|
<view class="org-viewne">{{ userInfo.hospitalName }}</view>
|
||||||
<view class="dash-viewne"></view>
|
<view class="dash-viewne"></view>
|
||||||
<view class="slogan">
|
<view class="slogan">
|
||||||
@@ -28,10 +67,10 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="contact-qr">
|
<view class="contact-qr">
|
||||||
<view class="contact-btn">
|
<view class="contact-btn">
|
||||||
<up-image :src="viewnkImg" width="430rpx" height="131rpx" ></up-image>
|
<up-image :src="viewnkBase64 || viewnkImg" width="430rpx" height="131rpx" ></up-image>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
<image class="qr-img" :src="docUrl+userInfo.qrcode" mode="aspectFit" />
|
<image class="qr-img" :src="userInfo.localQrcode || (docUrl+userInfo.qrcode)" mode="aspectFit" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -44,8 +83,8 @@
|
|||||||
<view class="s-bottom">
|
<view class="s-bottom">
|
||||||
<view>
|
<view>
|
||||||
<view class="descrow"><text>1</text>微信扫一扫上方二维码,关注“肝胆相照一家人”公众号</view>
|
<view class="descrow"><text>1</text>微信扫一扫上方二维码,关注“肝胆相照一家人”公众号</view>
|
||||||
<view class="descrow"><text>2</text>点击“邹建东专家工作室”,选择微信登录,注册后直接发送随访申请</view>
|
<view class="descrow"><text>2</text>点击“{{ userInfo.realName }}专家工作室”,选择微信登录,注册后直接发送随访申请</view>
|
||||||
<view class="descrow"><text>3</text>若未弹出“随访申请发送成功”提示,请再次点击“邹建东专家工作室”发送随访申请</view>
|
<view class="descrow"><text>3</text>若未弹出“随访申请发送成功”提示,请再次点击“{{ userInfo.realName }}专家工作室”发送随访申请</view>
|
||||||
<view class="descrow"><text>4</text>审核通过后,点击“就医服务-随访交流”,与专家进行图文交流</view>
|
<view class="descrow"><text>4</text>审核通过后,点击“就医服务-随访交流”,与专家进行图文交流</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -58,100 +97,470 @@
|
|||||||
</scroll-view>
|
</scroll-view>
|
||||||
|
|
||||||
<!-- 底部保存按钮 -->
|
<!-- 底部保存按钮 -->
|
||||||
<view class="save-bar">
|
<view class="save-bar" v-if="!jieping">
|
||||||
<button class="save-btn" @click="onSave">保存二维码到手机</button>
|
<button class="save-btn" @click="onSave">保存到手机相册</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<!-- 分享弹窗 -->
|
||||||
|
<uni-popup ref="shareRef" type="bottom" safeArea backgroundColor="#fff">
|
||||||
|
<view class="share-popup">
|
||||||
|
<view class="share-title">分享到</view>
|
||||||
|
<view class="share-content">
|
||||||
|
<view class="share-item" @click="shareToWechat">
|
||||||
|
<view class="share-icon wechat-icon">
|
||||||
|
<image class="share-img" :src="wxImg" mode="aspectFill" />
|
||||||
|
</view>
|
||||||
|
<text class="share-text">微信</text>
|
||||||
|
</view>
|
||||||
|
<view class="share-item" @click="shareToMoments">
|
||||||
|
<view class="share-icon moments-icon">
|
||||||
|
<image class="share-img" :src="friendImg" mode="aspectFill" />
|
||||||
|
</view>
|
||||||
|
<text class="share-text">朋友圈</text>
|
||||||
|
</view>
|
||||||
|
<view class="share-item" @click="shareToWeibo">
|
||||||
|
<view class="share-icon weibo-icon">
|
||||||
|
<image class="share-img" :src="sinaImg" mode="aspectFill" />
|
||||||
|
</view>
|
||||||
|
<text class="share-text">新浪微博</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="share-cancel" @click="closeShare">
|
||||||
|
<text>取消</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup >
|
||||||
|
import { base64ToPath } from 'image-tools'
|
||||||
|
import { urlToBase64 } from '@/uni_modules/sp-html2canvas-render/utils/index.js'
|
||||||
import navBar from '@/components/navBar/navBar.vue'
|
import navBar from '@/components/navBar/navBar.vue'
|
||||||
import { onShow } from "@dcloudio/uni-app";
|
import { onShow,onBackPress,onLoad} from "@dcloudio/uni-app";
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import MyHtml2canvas from '@/components/MyHtml2canvas.vue'
|
||||||
import docUrl from '@/utils/docUrl'
|
import docUrl from '@/utils/docUrl'
|
||||||
import bgImg from "@/static/background.jpg"
|
import otherHost from '@/utils/otherHost'
|
||||||
|
import shareIcon from "@/static/icon_share.png";
|
||||||
|
import sinaImg from "@/static/share_sina.png";
|
||||||
|
import wxImg from "@/static/share_weixin.png";
|
||||||
|
import friendImg from "@/static/share_wxc.png";
|
||||||
|
import logoImg from "@/static/weiboShare.png";
|
||||||
|
import isAndroid from "@/utils/platform.js";
|
||||||
|
// 背景图使用线上地址
|
||||||
|
const bgImg = 'https://oss.igandan.com/images/expertcode_background.jpg?v=1'
|
||||||
import viewnkImg from "@/static/arr.png"
|
import viewnkImg from "@/static/arr.png"
|
||||||
|
|
||||||
const userInfo = ref({})
|
const userInfo = ref({})
|
||||||
const goBack = () => {
|
const jieping = ref(false)
|
||||||
uni.navigateBack();
|
const shotRef = ref(null)
|
||||||
};
|
const bgBase64 = ref('')
|
||||||
onShow(()=>{
|
const viewnkBase64 = ref('')
|
||||||
userInfo.value = uni.getStorageSync('userInfo')
|
const from=ref('');
|
||||||
})
|
const title=ref('');
|
||||||
const onSave = () => {
|
const summary=ref('参与爱肝行动,共创美好前程');
|
||||||
// 检查是否有二维码图片
|
const link=ref('');
|
||||||
if (!userInfo.value.qrcode) {
|
|
||||||
uni.showToast({ title: '二维码不存在', icon: 'none' });
|
onBackPress(() => {
|
||||||
return;
|
if(!from.value){
|
||||||
|
plus.runtime.quit();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
const goBack = () => {
|
||||||
|
if(!from.value){
|
||||||
|
plus.runtime.quit();
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
|
|
||||||
// 显示加载提示
|
};
|
||||||
uni.showLoading({ title: '保存中...' });
|
onLoad((options) => {
|
||||||
|
from.value = options.from;
|
||||||
// 下载二维码图片
|
uni.sendNativeEvent("portraitReport",{
|
||||||
uni.downloadFile({
|
msg:{
|
||||||
url: docUrl + userInfo.value.qrcode,
|
event_nickname: "list_page",
|
||||||
success: (res) => {
|
page_type: "我的二维码",
|
||||||
if (res.statusCode === 200) {
|
},
|
||||||
// 保存到相册
|
});
|
||||||
uni.saveImageToPhotosAlbum({
|
})
|
||||||
filePath: res.tempFilePath,
|
|
||||||
success: () => {
|
// 页面显示时拉取用户信息,并尽量把图片转成 base64,避免 html2canvas 跨域污染
|
||||||
uni.hideLoading();
|
onShow(async () => {
|
||||||
uni.showToast({
|
const info = uni.getStorageSync('userInfo') || {}
|
||||||
title: '保存成功',
|
console.log('[myCode] onShow userInfo:', info)
|
||||||
icon: 'none',
|
title.value = '不方便到医院就诊,'+info.realName+'医生在肝胆相照平台帮助您!';
|
||||||
duration: 2000
|
link.value = otherHost+'/expert/expertcodeimg?expert_uuid='+info.uuid+'&fromtype=doctor'
|
||||||
});
|
// 背景图转 base64
|
||||||
},
|
if (!bgBase64.value) {
|
||||||
fail: (err) => {
|
try {
|
||||||
uni.hideLoading();
|
console.log('[myCode] 准备将背景图转为 base64:', bgImg)
|
||||||
console.error('保存失败:', err);
|
const bg = await urlToBase64(bgImg, 'jpg')
|
||||||
|
bgBase64.value = bg
|
||||||
// 根据错误类型给出不同提示
|
console.log('[myCode] 背景图转 base64 成功,长度:', bg && bg.length)
|
||||||
if (err.errMsg.includes('auth deny') || err.errMsg.includes('authorize')) {
|
} catch (e) {
|
||||||
uni.showModal({
|
console.error('[myCode] 背景图转 base64 失败:', e)
|
||||||
title: '权限提示',
|
|
||||||
content: '需要相册权限才能保存图片,请在设置中开启权限',
|
|
||||||
showCancel: false,
|
|
||||||
confirmText: '知道了'
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: '保存失败,请重试',
|
|
||||||
icon: 'none',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
uni.hideLoading();
|
|
||||||
uni.showToast({
|
|
||||||
title: '下载失败,请检查网络',
|
|
||||||
icon: 'none',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: (err) => {
|
|
||||||
uni.hideLoading();
|
|
||||||
console.error('下载失败:', err);
|
|
||||||
uni.showToast({
|
|
||||||
title: '下载失败,请检查网络',
|
|
||||||
icon: 'none',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
// 按钮图转 base64
|
||||||
|
if (!viewnkBase64.value) {
|
||||||
|
try {
|
||||||
|
console.log('[myCode] 准备将按钮图转为 base64:', viewnkImg)
|
||||||
|
const btn = await urlToBase64(viewnkImg, 'png')
|
||||||
|
viewnkBase64.value = btn
|
||||||
|
console.log('[myCode] 按钮图转 base64 成功,长度:', btn && btn.length)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[myCode] 按钮图转 base64 失败:', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 头像:远程地址转 base64,写入 avatarBase64,优先被使用
|
||||||
|
if (info.photo && !info.avatarBase64) {
|
||||||
|
const avatarUrl = docUrl + info.photo
|
||||||
|
try {
|
||||||
|
console.log('[myCode] 准备将头像转为 base64:', avatarUrl)
|
||||||
|
const avatarBase64 = await urlToBase64(avatarUrl, 'jpg')
|
||||||
|
info.avatarBase64 = avatarBase64
|
||||||
|
console.log('[myCode] 头像转 base64 成功,长度:', avatarBase64 && avatarBase64.length)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[myCode] 头像转 base64 失败:', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 二维码:远程地址转 base64,写入 localQrcode,模板已优先使用该字段
|
||||||
|
if (info.qrcode && !info.localQrcode) {
|
||||||
|
const qrUrl = docUrl + info.qrcode
|
||||||
|
try {
|
||||||
|
console.log('[myCode] 准备将二维码转为 base64:', qrUrl)
|
||||||
|
const qrBase64 = await urlToBase64(qrUrl, 'png')
|
||||||
|
info.localQrcode = qrBase64
|
||||||
|
console.log('[myCode] 二维码转 base64 成功,长度:', qrBase64 && qrBase64.length)
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[myCode] 二维码转 base64 失败:', e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
userInfo.value = info
|
||||||
|
})
|
||||||
|
|
||||||
|
// 保存失败时统一处理
|
||||||
|
const handleSaveError = (err) => {
|
||||||
|
if (err && err.errMsg && (err.errMsg.includes('auth deny') || err.errMsg.includes('authorize'))) {
|
||||||
|
uni.showModal({
|
||||||
|
title: '权限提示',
|
||||||
|
content: '需要相册权限才能保存图片,请在系统设置中开启相册权限',
|
||||||
|
showCancel: false,
|
||||||
|
confirmText: '知道了'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: '保存失败,请重试',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击“保存到手机相册”
|
||||||
|
const onSave = () => {
|
||||||
|
console.log('[myCode] onSave 点击,准备开始截图')
|
||||||
|
|
||||||
|
// 使用自定义组件触发 html2canvas(内部通过 renderjs 在视图层执行)
|
||||||
|
jieping.value = true
|
||||||
|
|
||||||
|
// 调用自定义组件方法开始渲染
|
||||||
|
if (shotRef.value && shotRef.value.h2cRenderDom) {
|
||||||
|
shotRef.value.h2cRenderDom()
|
||||||
|
} else {
|
||||||
|
console.error('[myCode] shotRef 或 h2cRenderDom 不存在')
|
||||||
|
jieping.value = false
|
||||||
|
uni.showToast({
|
||||||
|
title: '截图组件未准备好',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 自定义组件截图完成回调(拿到 base64)
|
||||||
|
const onRenderOver = (base64) => {
|
||||||
|
console.log('[myCode] onRenderOver base64 长度:', base64 && base64.length)
|
||||||
|
if (!base64) {
|
||||||
|
jieping.value = false
|
||||||
|
uni.showToast({
|
||||||
|
title: '生成图片失败',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
base64ToPath(base64)
|
||||||
|
.then((res) => {
|
||||||
|
const path = res.path || res
|
||||||
|
console.log('[myCode] base64ToPath 转换成功,path:', path)
|
||||||
|
uni.saveImageToPhotosAlbum({
|
||||||
|
filePath: path,
|
||||||
|
success() {
|
||||||
|
uni.showToast({
|
||||||
|
title: '保存图片成功',
|
||||||
|
mask: false,
|
||||||
|
duration: 1500
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fail(err) {
|
||||||
|
console.error('[myCode] 保存到相册失败:', err)
|
||||||
|
handleSaveError(err)
|
||||||
|
},
|
||||||
|
complete() {
|
||||||
|
jieping.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('[myCode] base64ToPath 失败:', err)
|
||||||
|
handleSaveError(err)
|
||||||
|
jieping.value = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const shareRef = ref();
|
||||||
|
// 分享APP
|
||||||
|
const shareToggle = () => {
|
||||||
|
shareRef.value.open();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 关闭分享弹窗
|
||||||
|
const closeShare = () => {
|
||||||
|
shareRef.value.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分享到微信
|
||||||
|
const shareToWechat = () => {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
// 使用系统分享
|
||||||
|
uni.downloadFile({
|
||||||
|
url:'https://doc.igandan.com/app/html/img/2016/20160714132557.png',
|
||||||
|
success: function (res) {
|
||||||
|
uni.compressImage({
|
||||||
|
src: res.tempFilePath,
|
||||||
|
quality: 60,
|
||||||
|
success: function (res2) {
|
||||||
|
uni.share({
|
||||||
|
provider: "weixin",
|
||||||
|
scene: "WXSceneSession",
|
||||||
|
type: 0,
|
||||||
|
title: title.value,
|
||||||
|
summary: summary.value,
|
||||||
|
href: link.value,
|
||||||
|
imageUrl: res2.tempFilePath,
|
||||||
|
success: function (res) {
|
||||||
|
console.log("success:" + JSON.stringify(res));
|
||||||
|
},
|
||||||
|
fail: function (err) {
|
||||||
|
console.log("fail:" + JSON.stringify(err));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// uni.share({
|
||||||
|
// provider: "weixin",
|
||||||
|
// scene: "WXSceneSession",
|
||||||
|
// type: 0,
|
||||||
|
// title: videoInfo.value.name,
|
||||||
|
// summary: videoInfo.value.note,
|
||||||
|
// href: shareLink.value,
|
||||||
|
// imageUrl: docUrl + videoInfo.value.imgpath,
|
||||||
|
// success: function (res) {
|
||||||
|
// //console.log("success:" + JSON.stringify(res));
|
||||||
|
// },
|
||||||
|
// fail: function (err) {
|
||||||
|
// //console.log("fail:" + JSON.stringify(err));
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef H5
|
||||||
|
// H5环境下的分享
|
||||||
|
if (navigator.share) {
|
||||||
|
navigator
|
||||||
|
.share({
|
||||||
|
title: "肝胆相照APP",
|
||||||
|
text: "专业的医疗健康平台,快来下载体验吧!",
|
||||||
|
url: shareLink.value,
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
uni.showToast({
|
||||||
|
title: "分享成功",
|
||||||
|
icon: "success",
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
uni.showToast({
|
||||||
|
title: "分享失败",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 复制到剪贴板
|
||||||
|
uni.setClipboardData({
|
||||||
|
data:
|
||||||
|
"肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接:" +
|
||||||
|
shareLink.value,
|
||||||
|
success: () => {
|
||||||
|
uni.showToast({
|
||||||
|
title: "已复制到剪贴板",
|
||||||
|
icon: "success",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
// 微信小程序分享
|
||||||
|
uni.showShareMenu({
|
||||||
|
withShareTicket: true,
|
||||||
|
menus: ["shareAppMessage", "shareTimeline"],
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
closeShare();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分享到朋友圈
|
||||||
|
const shareToMoments = () => {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
uni.downloadFile({
|
||||||
|
url: 'https://doc.igandan.com/app/html/img/2016/20160714132557.png',
|
||||||
|
success: function (res) {
|
||||||
|
uni.compressImage({
|
||||||
|
src: res.tempFilePath,
|
||||||
|
quality: 60,
|
||||||
|
success: function (res2) {
|
||||||
|
uni.share({
|
||||||
|
provider: "weixin",
|
||||||
|
scene: "WXSceneTimeline",
|
||||||
|
type: 0,
|
||||||
|
title: title.value,
|
||||||
|
summary: summary.value,
|
||||||
|
href: link.value,
|
||||||
|
imageUrl: res2.tempFilePath,
|
||||||
|
success: function (res) {
|
||||||
|
//console.log("success:" + JSON.stringify(res));
|
||||||
|
},
|
||||||
|
fail: function (err) {
|
||||||
|
//console.log("fail:" + JSON.stringify(err));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef H5
|
||||||
|
// 复制到剪贴板
|
||||||
|
uni.setClipboardData({
|
||||||
|
data: "肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接:https://www.igandan.com",
|
||||||
|
success: () => {
|
||||||
|
uni.showToast({
|
||||||
|
title: "已复制到剪贴板,可分享到朋友圈",
|
||||||
|
icon: "success",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
uni.showShareMenu({
|
||||||
|
withShareTicket: true,
|
||||||
|
menus: ["shareAppMessage", "shareTimeline"],
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
closeShare();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分享到新浪微博
|
||||||
|
const shareToWeibo = () => {
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
uni.share({
|
||||||
|
provider: "sinaweibo",
|
||||||
|
type: 0,
|
||||||
|
title: title.value,
|
||||||
|
summary: summary.value,
|
||||||
|
href: link.value,
|
||||||
|
imageUrl: logoImg,
|
||||||
|
success: function (res) {
|
||||||
|
//console.log("分享成功");
|
||||||
|
},
|
||||||
|
fail: function (err) {
|
||||||
|
//console.log("fail:" + JSON.stringify(err));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// plus.share.sendWithSystem({
|
||||||
|
// type: 'text',
|
||||||
|
// content: '肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接:https://www.igandan.com'
|
||||||
|
// }, () => {
|
||||||
|
// uni.showToast({
|
||||||
|
// title: '分享成功',
|
||||||
|
// icon: 'success'
|
||||||
|
// })
|
||||||
|
// }, (err) => {
|
||||||
|
// console.log('分享失败:', err)
|
||||||
|
// uni.showToast({
|
||||||
|
// title: '分享失败',
|
||||||
|
// icon: 'none'
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef H5
|
||||||
|
// 复制到剪贴板
|
||||||
|
uni.setClipboardData({
|
||||||
|
data: "肝胆相照APP - 专业的医疗健康平台,快来下载体验吧!\n下载链接:https://www.igandan.com",
|
||||||
|
success: () => {
|
||||||
|
uni.showToast({
|
||||||
|
title: "已复制到剪贴板,可分享到微博",
|
||||||
|
icon: "success",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
closeShare();
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.share-img {
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
}
|
||||||
|
.share-img-icon {
|
||||||
|
width: 40rpx;
|
||||||
|
height:40rpx;
|
||||||
|
}
|
||||||
|
.nav-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
}
|
||||||
.my-code-page {
|
.my-code-page {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-color: #0d7dfd;
|
background-color: #0d7dfd;
|
||||||
|
|
||||||
|
.active{
|
||||||
|
transform: scale(0.8);
|
||||||
|
margin-top: -calc(var(--status-bar-height) + 44px);
|
||||||
|
transition: all 0.3s ease-in-out;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.squrebox{
|
.squrebox{
|
||||||
margin:0 30rpx;
|
margin:0 30rpx;
|
||||||
|
|
||||||
@@ -226,7 +635,8 @@ const onSave = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.page-scroll {
|
.page-scroll {
|
||||||
height: calc(100vh - 100rpx);
|
margin-top: calc(var(--status-bar-height) + 44px);
|
||||||
|
// height: calc(100vh - var(--status-bar-height) - 44px);
|
||||||
padding-bottom: 140rpx;
|
padding-bottom: 140rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,7 +661,7 @@ const onSave = () => {
|
|||||||
|
|
||||||
.qr-card {
|
.qr-card {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: -120rpx 30rpx 30rpx;
|
margin: -80rpx 30rpx 30rpx;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
border-radius: 20rpx;
|
border-radius: 20rpx;
|
||||||
padding: 140rpx 30rpx 30rpx;
|
padding: 140rpx 30rpx 30rpx;
|
||||||
@@ -275,6 +685,22 @@ const onSave = () => {
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: #0d7dfd;
|
background-color: #0d7dfd;
|
||||||
}
|
}
|
||||||
|
.star{
|
||||||
|
position: absolute;
|
||||||
|
top: 48rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
padding:0 16rpx;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
background-color:#ff9f1a;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index:10;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
.halfCircle{
|
.halfCircle{
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -312,13 +738,17 @@ const onSave = () => {
|
|||||||
|
|
||||||
.name-viewne {
|
.name-viewne {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 34rpx;
|
font-size: 36rpx;
|
||||||
color: #1a76d2;
|
color: #1a76d2;
|
||||||
|
font-weight: bold;
|
||||||
margin-top: 10rpx;
|
margin-top: 10rpx;
|
||||||
|
.position-name{
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.org-viewne {
|
.org-viewne {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 28rpx;
|
font-size: 36rpx;
|
||||||
color: #4a90e2;
|
color: #4a90e2;
|
||||||
margin-top: 16rpx;
|
margin-top: 16rpx;
|
||||||
}
|
}
|
||||||
@@ -400,4 +830,158 @@ const onSave = () => {
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 分享弹窗样式 */
|
||||||
|
.share-popup {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 20rpx 20rpx 0 0;
|
||||||
|
padding: 40rpx 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-title {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 40rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
padding: 0 40rpx 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-icon {
|
||||||
|
width: 100rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wechat-icon {
|
||||||
|
background-color: #07c160;
|
||||||
|
}
|
||||||
|
|
||||||
|
.moments-icon {
|
||||||
|
background-color: #07c160;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weibo-icon {
|
||||||
|
background-color: #e6162d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qq-icon {
|
||||||
|
background-color: #12b7f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-icon-text {
|
||||||
|
font-size: 50rpx;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-cancel {
|
||||||
|
height: 100rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-top: 1rpx solid #f0f0f0;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-cancel:active {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除确认弹窗
|
||||||
|
.delete-modal-mask {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
z-index: 1000;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-modal-content {
|
||||||
|
width: 600rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
padding: 60rpx 40rpx 40rpx;
|
||||||
|
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-modal-title {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-modal-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: 50rpx;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-modal-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-modal-btn {
|
||||||
|
flex: 1;
|
||||||
|
height: 80rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
font-size: 32rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-btn {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
color: #333;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
background-color: #8b2316;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
background-color: #6b1a0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
fixed
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
height="180rpx"
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
>
|
>
|
||||||
@@ -265,9 +265,9 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.journal-list {
|
.journal-list {
|
||||||
height: calc(100vh - 140rpx);
|
height: calc(100vh - 180rpx);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 140rpx;
|
top: 180rpx;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-bottom: 100rpx; /* 为底部操作栏留出空间 */
|
padding-bottom: 100rpx; /* 为底部操作栏留出空间 */
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
fixed
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
height="180rpx"
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
>
|
>
|
||||||
@@ -166,9 +166,9 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.document-list {
|
.document-list {
|
||||||
height: calc(100vh - 140rpx);
|
height: calc(100vh - 180rpx);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 140rpx;
|
top: 180rpx;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
fixed
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
height="180rpx"
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
>
|
>
|
||||||
@@ -172,7 +172,7 @@ const onLoadMore = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.history-list {
|
.history-list {
|
||||||
height: calc(100vh - 140rpx);
|
height: calc(100vh - 180rpx);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top:140rpx;
|
top:140rpx;
|
||||||
bottom:0;
|
bottom:0;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
@clickLeft="goBack()"
|
@clickLeft="goBack()"
|
||||||
fixed
|
fixed
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
height="180rpx"
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
fixed
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
height="180rpx"
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
>
|
>
|
||||||
@@ -177,9 +177,9 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.news-list {
|
.news-list {
|
||||||
height: calc(100vh - 140rpx);
|
height: calc(100vh - 180rpx);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 140rpx;
|
top: 180rpx;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
fixed
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
height="180rpx"
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
>
|
>
|
||||||
@@ -172,7 +172,7 @@ const onLoadMore = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.history-list {
|
.history-list {
|
||||||
height: calc(100vh - 140rpx);
|
height: calc(100vh - 180rpx);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top:140rpx;
|
top:140rpx;
|
||||||
bottom:0;
|
bottom:0;
|
||||||
|
|||||||
@@ -0,0 +1,218 @@
|
|||||||
|
<template>
|
||||||
|
<view class="detail-page">
|
||||||
|
<navBar title="订单详情" />
|
||||||
|
|
||||||
|
<view class="order-card">
|
||||||
|
<view class="order-top">
|
||||||
|
<text class="download-no">下载课件号: {{ detail.downloadNo || "--" }}</text>
|
||||||
|
<text class="pay-status">{{ detail.statusText || "--" }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="section-divider"></view>
|
||||||
|
|
||||||
|
<view class="course-title">{{ detail.title || "--" }}</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<view class="info-list">
|
||||||
|
<view class="info-row">
|
||||||
|
<text class="info-label">课件作者:</text>
|
||||||
|
<text class="info-value">{{ detail.author || "--" }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-row">
|
||||||
|
<text class="info-label">金额:</text>
|
||||||
|
<text class="info-value amount">{{ detail.amountText || "--" }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-row">
|
||||||
|
<text class="info-label">创建时间:</text>
|
||||||
|
<text class="info-value">{{ detail.createTime || "--" }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-row">
|
||||||
|
<text class="info-label">支付方式:</text>
|
||||||
|
<text class="info-value">{{ detail.payType}}</text>
|
||||||
|
</view>
|
||||||
|
<view class="info-row">
|
||||||
|
<text class="info-label">支付时间:</text>
|
||||||
|
<text class="info-value">{{ detail.payTime || "--" }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
|
import api from "@/api/api.js";
|
||||||
|
|
||||||
|
const coursewareId = ref("");
|
||||||
|
const detail = ref({
|
||||||
|
downloadNo: "",
|
||||||
|
statusText: "",
|
||||||
|
title: "",
|
||||||
|
author: "",
|
||||||
|
amountText: "",
|
||||||
|
createTime: "",
|
||||||
|
payType: "",
|
||||||
|
payTime: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const formatDateTime = (value) => {
|
||||||
|
if (!value) return "";
|
||||||
|
if (typeof value === "string" && value.includes("-")) return value;
|
||||||
|
const timeNum = Number(value);
|
||||||
|
if (!timeNum) return "";
|
||||||
|
const ms = timeNum < 10000000000 ? timeNum * 1000 : timeNum;
|
||||||
|
const d = new Date(ms);
|
||||||
|
const y = d.getFullYear();
|
||||||
|
const m = String(d.getMonth() + 1).padStart(2, "0");
|
||||||
|
const day = String(d.getDate()).padStart(2, "0");
|
||||||
|
const h = String(d.getHours()).padStart(2, "0");
|
||||||
|
const min = String(d.getMinutes()).padStart(2, "0");
|
||||||
|
const s = String(d.getSeconds()).padStart(2, "0");
|
||||||
|
return `${y}-${m}-${day} ${h}:${min}:${s}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatAmount = (value) => {
|
||||||
|
if (value === undefined || value === null || value === "") return "";
|
||||||
|
const num = Number(value);
|
||||||
|
if (Number.isNaN(num)) return "";
|
||||||
|
const amount = num / 100;
|
||||||
|
return `${amount.toFixed(2)}元`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatStatus = (raw) => {
|
||||||
|
if (raw === undefined || raw === null) return "";
|
||||||
|
const text = String(raw).toLowerCase();
|
||||||
|
if (text === "paid" || text === "success" || text === "1" || text === "2") return "已支付";
|
||||||
|
if (text === "unpaid" || text === "0" || text === "created") return "未支付";
|
||||||
|
return String(raw);
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatPayType = (raw) => {
|
||||||
|
if(raw=='balance'){
|
||||||
|
return '余额支付';
|
||||||
|
}else if(raw=='FREE'){
|
||||||
|
return '免费'
|
||||||
|
}else if(raw=='USEWELFARENUM'){
|
||||||
|
return '免费次数';
|
||||||
|
}else if(raw=='wx'){
|
||||||
|
return '微信支付';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchCoursewareDetail = async () => {
|
||||||
|
if (!coursewareId.value) return;
|
||||||
|
try {
|
||||||
|
const res = await api.getGanDanFileOrder({
|
||||||
|
order_id: coursewareId.value,
|
||||||
|
});
|
||||||
|
if (res.code !== 200 || !res.data) return;
|
||||||
|
|
||||||
|
const data = res.data;
|
||||||
|
detail.value = {
|
||||||
|
downloadNo: data.order_id || data.download_no || data.gandanfile_order_id || data.id || "",
|
||||||
|
statusText: formatStatus(data.order_status || data.status || data.pay_status || ""),
|
||||||
|
title: data.title || data.name || data.file_name || "",
|
||||||
|
author: data.provider_name || data.author || data.nickname || "",
|
||||||
|
amountText: formatAmount(data.pay_amount || data.total_fee || data.amount || data.price || 0),
|
||||||
|
createTime: formatDateTime(data.create_date || data.create_time || data.order_time || ""),
|
||||||
|
payType: formatPayType(data.pay_channel),
|
||||||
|
payTime: formatDateTime(data.pay_date || data.pay_time || ""),
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: "获取详情失败",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
coursewareId.value = options.id;
|
||||||
|
fetchCoursewareDetail();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.detail-page {
|
||||||
|
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-card {
|
||||||
|
background: #fff;
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right:0;
|
||||||
|
z-index: 10;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-top {
|
||||||
|
min-height: 88rpx;
|
||||||
|
padding: 0 30rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-no {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pay-status {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #8b2316;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-divider {
|
||||||
|
height: 16rpx;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-title {
|
||||||
|
padding: 20rpx 30rpx;
|
||||||
|
color: #8b2316;
|
||||||
|
font-size: 32rpx;
|
||||||
|
line-height: 1.5;
|
||||||
|
word-break: break-all;
|
||||||
|
border-bottom: 2rpx solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-list {
|
||||||
|
padding: 24rpx 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-row {
|
||||||
|
min-height: 56rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-row:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-value {
|
||||||
|
max-width: 68%;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #666;
|
||||||
|
text-align: right;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
|
.amount {
|
||||||
|
color:red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<!-- <navBar title="我的课件" /> -->
|
||||||
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
|
left-icon="left"
|
||||||
|
title="我的课件"
|
||||||
|
@clickLeft="goBack"
|
||||||
|
color="#8B2316"
|
||||||
|
:border="false"
|
||||||
|
backgroundColor="#eeeeee"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
<view class="my-courseware-page">
|
<view class="my-courseware-page">
|
||||||
<!-- 顶部导航栏 -->
|
<!-- 顶部导航栏 -->
|
||||||
<uni-nav-bar
|
|
||||||
left-icon="left"
|
|
||||||
title="我的课件"
|
|
||||||
@cviewckLeft="goBack"
|
|
||||||
fixed
|
|
||||||
color="#8B2316"
|
|
||||||
height="140rpx"
|
|
||||||
:border="false"
|
|
||||||
backgroundColor="#eeeeee"
|
|
||||||
>
|
|
||||||
|
|
||||||
</uni-nav-bar>
|
|
||||||
|
|
||||||
<!-- 标签页导航 -->
|
<!-- 标签页导航 -->
|
||||||
<view class="tab-nav">
|
<view class="tab-nav">
|
||||||
@@ -37,11 +37,11 @@
|
|||||||
<view class="summary-bar">
|
<view class="summary-bar">
|
||||||
<view class="summary-item">
|
<view class="summary-item">
|
||||||
<up-image :src="downLoadImg" width="36rpx" height="36rpx" ></up-image>
|
<up-image :src="downLoadImg" width="36rpx" height="36rpx" ></up-image>
|
||||||
<text class="summary-text">{{ activeTab === 'download' ? '下载账户' : '分享账户' }}: {{ downloadCount }}</text>
|
<text class="summary-text">{{ totalAmount}}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="summary-item">
|
<view class="summary-item">
|
||||||
<up-image :src="moneyImg" width="36rpx" height="36rpx" ></up-image>
|
<up-image :src="moneyImg" width="36rpx" height="36rpx" ></up-image>
|
||||||
<text class="summary-text">{{ activeTab === 'download' ? '文件数量' : '分享文件' }}: {{ totalAmount }}</text>
|
<text class="summary-text">{{ downloadCount }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -49,12 +49,15 @@
|
|||||||
<scroll-view
|
<scroll-view
|
||||||
scroll-y
|
scroll-y
|
||||||
class="courseware-list"
|
class="courseware-list"
|
||||||
|
:scroll-top="listScrollTop"
|
||||||
|
:scroll-into-view="scrollIntoViewId"
|
||||||
refresher-enabled
|
refresher-enabled
|
||||||
@refresherrefresh="onRefresh"
|
@refresherrefresh="onRefresh"
|
||||||
:refresher-triggered="refreshing"
|
:refresher-triggered="refreshing"
|
||||||
@scrolltolower="onLoadMore"
|
@scrolltolower="onLoadMore"
|
||||||
:lower-threshold="100"
|
:lower-threshold="100"
|
||||||
>
|
>
|
||||||
|
<view id="courseware-top"></view>
|
||||||
<!-- 空状态 -->
|
<!-- 空状态 -->
|
||||||
<view v-if="coursewareList.length === 0 && !loading" class="empty-state">
|
<view v-if="coursewareList.length === 0 && !loading" class="empty-state">
|
||||||
<text>{{ activeTab === 'download' ? '暂无下载数据' : '暂无分享数据' }}</text>
|
<text>{{ activeTab === 'download' ? '暂无下载数据' : '暂无分享数据' }}</text>
|
||||||
@@ -62,21 +65,22 @@
|
|||||||
|
|
||||||
<view class="courseware-item" v-for="(item, index) in coursewareList" :key="index" @click="onItemClick(item)">
|
<view class="courseware-item" v-for="(item, index) in coursewareList" :key="index" @click="onItemClick(item)">
|
||||||
<view class="item-content">
|
<view class="item-content">
|
||||||
|
<view class="courseware-provider" v-if="activeTab === 'share'">
|
||||||
|
<text class="label">下载医生</text>
|
||||||
|
<text class="value">:{{ item.providername }}</text>
|
||||||
|
</view>
|
||||||
<view class="courseware-name">
|
<view class="courseware-name">
|
||||||
<text class="label">课件名称:</text>
|
<text class="label">课件名称</text>
|
||||||
<text class="value">{{ item.name }}</text>
|
<text class="value">:{{ item.name }}</text>
|
||||||
</view>
|
|
||||||
<view class="courseware-provider" v-if="item.providername">
|
|
||||||
<text class="label">{{ activeTab === 'download' ? '提供者' : '下载者' }}:</text>
|
|
||||||
<text class="value">{{ item.providername }}</text>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="courseware-time">
|
<view class="courseware-time">
|
||||||
<text class="label">时间:</text>
|
<text class="label">时间</text>
|
||||||
<text class="value">{{ item.time }}</text>
|
<text class="value">:{{ item.time }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="courseware-status">
|
<view class="courseware-status" v-if="activeTab === 'download'">
|
||||||
<text class="label">状态:</text>
|
<text class="label">状态</text>
|
||||||
<text class="value status-paid">{{ item.status }}</text>
|
<text class="value status-paid">:{{item.status}}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -95,31 +99,76 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted, nextTick } from 'vue';
|
||||||
import api from '@/api/api';
|
import api from '@/api/api';
|
||||||
|
import navTo from '@/utils/navTo.js';
|
||||||
|
import { onLoad,onBackPress } from '@dcloudio/uni-app';
|
||||||
import downLoadImg from "@/static/course_download.png"
|
import downLoadImg from "@/static/course_download.png"
|
||||||
import moneyImg from "@/static/course_yuan.png"
|
import moneyImg from "@/static/course_yuan.png"
|
||||||
const activeTab = ref('download');
|
const activeTab = ref('download');
|
||||||
|
const listScrollTop = ref(0);
|
||||||
|
const scrollIntoViewId = ref('');
|
||||||
const refreshing = ref(false);
|
const refreshing = ref(false);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const noMore = ref(false);
|
const noMore = ref(false);
|
||||||
const page = ref(1);
|
const page = ref(1);
|
||||||
const pageSize = ref(10);
|
const pageSize = ref(10);
|
||||||
const downloadCount = ref(4);
|
const downloadCount = ref(0);
|
||||||
const totalAmount = ref('20.00');
|
const totalAmount = ref(0);
|
||||||
|
|
||||||
const coursewareList = ref([]);
|
const coursewareList = ref([]);
|
||||||
|
const from = ref('');
|
||||||
|
onBackPress(() => {
|
||||||
|
if(!from.value){
|
||||||
|
plus.runtime.quit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onLoad((options) => {
|
||||||
|
if(options.from){
|
||||||
|
from.value = options.from;
|
||||||
|
}
|
||||||
|
uni.sendNativeEvent("portraitReport",{
|
||||||
|
msg:{
|
||||||
|
event_nickname: "list_page",
|
||||||
|
page_type: "我的课件",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
onRefresh();
|
onRefresh();
|
||||||
});
|
});
|
||||||
|
const getStatusText = (status) => {
|
||||||
|
console.log(status);
|
||||||
|
if(status === 'paid'){
|
||||||
|
return '已支付';
|
||||||
|
}else if(status === 'unpaid'){
|
||||||
|
return '未支付';
|
||||||
|
}else{
|
||||||
|
return '已分享';
|
||||||
|
}
|
||||||
|
};
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
uni.navigateBack();
|
if(!from.value){
|
||||||
|
plus.runtime.quit();
|
||||||
|
}else{
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
if(options.from){
|
||||||
|
//from.value = options.from;
|
||||||
|
switchTab('share')
|
||||||
|
}
|
||||||
|
})
|
||||||
const switchTab = (tab) => {
|
const switchTab = (tab) => {
|
||||||
activeTab.value = tab;
|
activeTab.value = tab;
|
||||||
|
listScrollTop.value = 0;
|
||||||
|
scrollIntoViewId.value = '';
|
||||||
|
nextTick(() => {
|
||||||
|
scrollIntoViewId.value = 'courseware-top';
|
||||||
|
});
|
||||||
// 切换标签时重置数据
|
// 切换标签时重置数据
|
||||||
page.value = 1;
|
page.value = 1;
|
||||||
noMore.value = false;
|
noMore.value = false;
|
||||||
@@ -132,37 +181,10 @@ const onItemClick = (item) => {
|
|||||||
console.log('点击课件:', item);
|
console.log('点击课件:', item);
|
||||||
|
|
||||||
if (activeTab.value === 'download') {
|
if (activeTab.value === 'download') {
|
||||||
// 下载标签页的处理逻辑
|
navTo({
|
||||||
if (item.download_path) {
|
url: `/pages_app/myCourseware/coursewareDetail?id=${item.order_id}`
|
||||||
uni.downloadFile({
|
})
|
||||||
url: item.download_path,
|
}
|
||||||
success: (res) => {
|
|
||||||
if (res.statusCode === 200) {
|
|
||||||
uni.openDocument({
|
|
||||||
filePath: res.tempFilePath,
|
|
||||||
success: () => {
|
|
||||||
console.log('打开文档成功');
|
|
||||||
},
|
|
||||||
fail: (err) => {
|
|
||||||
console.error('打开文档失败:', err);
|
|
||||||
uni.showToast({ title: '无法打开此文件', icon: 'none' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: (err) => {
|
|
||||||
console.error('下载失败:', err);
|
|
||||||
uni.showToast({ title: '下载失败', icon: 'none' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
uni.showToast({ title: `点击了下载课件: ${item.name}`, icon: 'none' });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 分享标签页的处理逻辑
|
|
||||||
uni.showToast({ title: `点击了分享课件: ${item.name}`, icon: 'none' });
|
|
||||||
// 这里可以添加分享相关的操作,比如查看分享详情、重新分享等
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRefresh = () => {
|
const onRefresh = () => {
|
||||||
@@ -175,7 +197,7 @@ const onRefresh = () => {
|
|||||||
if (res.code === 200 && res.data) {
|
if (res.code === 200 && res.data) {
|
||||||
const data = res.data.list;
|
const data = res.data.list;
|
||||||
// 更新摘要信息
|
// 更新摘要信息
|
||||||
downloadCount.value = res.data.downloadTotalAccount || 0;
|
downloadCount.value = (res.data.downloadTotalAccount/100).toFixed(2) || 0;
|
||||||
totalAmount.value = res.data.downloadFileCount || 0;
|
totalAmount.value = res.data.downloadFileCount || 0;
|
||||||
|
|
||||||
// 处理课件列表数据
|
// 处理课件列表数据
|
||||||
@@ -186,7 +208,7 @@ const onRefresh = () => {
|
|||||||
uuid: item.uuid,
|
uuid: item.uuid,
|
||||||
order_id: item.order_id,
|
order_id: item.order_id,
|
||||||
type: item.type,
|
type: item.type,
|
||||||
providername: item.providername
|
providername: item.downloadername
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// 判断是否还有更多数据
|
// 判断是否还有更多数据
|
||||||
@@ -203,7 +225,7 @@ const onRefresh = () => {
|
|||||||
if (res.code === 200 && res.data) {
|
if (res.code === 200 && res.data) {
|
||||||
const data = res.data.list;
|
const data = res.data.list;
|
||||||
// 更新摘要信息 - 分享数据使用不同的字段
|
// 更新摘要信息 - 分享数据使用不同的字段
|
||||||
downloadCount.value = res.data.shareTotalAccount || 0;
|
downloadCount.value = (res.data.shareTotalAccount/100).toFixed(2) || 0;
|
||||||
totalAmount.value = res.data.shareloadFileCount || 0;
|
totalAmount.value = res.data.shareloadFileCount || 0;
|
||||||
|
|
||||||
// 处理分享列表数据
|
// 处理分享列表数据
|
||||||
@@ -305,7 +327,7 @@ const onLoadMore = () => {
|
|||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
border-bottom: 2rpx solid #f0f0f0;
|
border-bottom: 2rpx solid #f0f0f0;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 140rpx;
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
@@ -332,20 +354,21 @@ const onLoadMore = () => {
|
|||||||
|
|
||||||
.summary-bar {
|
.summary-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background: #8B2316;
|
background: #8B2316;
|
||||||
padding: 20rpx 30rpx;
|
padding: 20rpx 30rpx;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 260rpx; // 标签页导航下方
|
top: calc(var(--status-bar-height) + 44px + 124rpx); // 标签页导航下方
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
|
||||||
.summary-item {
|
.summary-item {
|
||||||
|
flex:1;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
.summary-text {
|
.summary-text {
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
@@ -355,9 +378,9 @@ const onLoadMore = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.courseware-list {
|
.courseware-list {
|
||||||
height: calc(100vh - 140rpx - 116rpx - 80rpx);
|
// height: calc(100vh - 180rpx - 116rpx - 80rpx);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 336rpx; // 调整顶部位置,为固定的摘要栏腾出空间
|
top: calc(var(--status-bar-height) + 44px + 124rpx + 80rpx); // 调整顶部位置,为固定的摘要栏腾出空间
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@@ -383,6 +406,15 @@ const onLoadMore = () => {
|
|||||||
width: 120rpx;
|
width: 120rpx;
|
||||||
color: #8B2316;
|
color: #8B2316;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: justify;
|
||||||
|
text-align-last: justify;
|
||||||
|
text-justify: inter-ideograph;
|
||||||
|
}
|
||||||
|
.label::after {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
@clickLeft="goBack()"
|
@clickLeft="goBack()"
|
||||||
fixed
|
fixed
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
height="180rpx"
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
>
|
>
|
||||||
|
|||||||
+263
-72
@@ -2,33 +2,38 @@
|
|||||||
|
|
||||||
<view class="flower-page">
|
<view class="flower-page">
|
||||||
<!-- 顶部统计栏(与截图一致:两项) -->
|
<!-- 顶部统计栏(与截图一致:两项) -->
|
||||||
<uni-nav-bar
|
<view class="navbox">
|
||||||
|
<view class="status_bar"></view>
|
||||||
|
<uni-nav-bar
|
||||||
left-icon="left"
|
left-icon="left"
|
||||||
title="我的鲜花"
|
title="我的鲜花"
|
||||||
@clickLeft="goBack"
|
@clickLeft="goBack"
|
||||||
fixed
|
|
||||||
color="#8B2316"
|
color="#8B2316"
|
||||||
height="140rpx"
|
|
||||||
:border="false"
|
:border="false"
|
||||||
backgroundColor="#eeeeee"
|
backgroundColor="#eeeeee"
|
||||||
/>
|
/>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view class="stats-bar">
|
<view class="fixed-top-block">
|
||||||
<view class="stat">
|
<view class="stats-bar">
|
||||||
<up-image :src="flowerImg" width="36rpx" height="36rpx" ></up-image>
|
<view class="stat">
|
||||||
<text class="num">{{ stat.totalCount }}</text>
|
<up-image :src="flowerImg" width="36rpx" height="36rpx" ></up-image>
|
||||||
|
<text class="num">{{ stat.totalCount }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="stat">
|
||||||
|
<up-image :src="moneyImg" width="36rpx" height="36rpx" ></up-image>
|
||||||
|
<text class="num">{{ stat.totalAmount.toFixed(2) }}</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="stat">
|
|
||||||
<up-image :src="moneyImg" width="36rpx" height="36rpx" ></up-image>
|
|
||||||
<text class="num">{{ stat.totalAmount.toFixed(2) }}</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 表头条(红底白字) -->
|
<!-- 表头条(红底白字) -->
|
||||||
<view class="table-header">
|
<view class="table-header">
|
||||||
<text class="col name">姓名</text>
|
<text class="col name">姓名</text>
|
||||||
<text class="col time">时间</text>
|
<text class="col time">时间</text>
|
||||||
<text class="col qty">数量</text>
|
<text class="col qty">数量</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 表体/列表或空状态 -->
|
<!-- 表体/列表或空状态 -->
|
||||||
@@ -43,37 +48,62 @@
|
|||||||
lower-threshold="100"
|
lower-threshold="100"
|
||||||
:scroll-top="scrollTop"
|
:scroll-top="scrollTop"
|
||||||
>
|
>
|
||||||
<view v-if="records.length === 0" class="empty-wrap">
|
<view class="list-content">
|
||||||
<up-image :src="emptyImg" width="176rpx" height="204rpx" ></up-image>
|
<view v-if="records.length === 0" class="empty-wrap">
|
||||||
<text class="empty-text">您暂未收到鲜花</text>
|
<up-image :src="emptyImg" width="176rpx" height="204rpx" ></up-image>
|
||||||
</view>
|
<text class="empty-text">您暂未收到鲜花</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view v-else class="row" v-for="(item, idx) in records" :key="idx">
|
<view v-else class="row" v-for="(item, idx) in records" :key="idx">
|
||||||
<text class="cell name">{{ item.name }}</text>
|
<text class="cell name">{{ item.name }}</text>
|
||||||
<text class="cell time">{{ item.time }}</text>
|
<text class="cell time">{{ item.time }}</text>
|
||||||
<text class="cell qty" :class="{ plus: item.amount > 0, minus: item.amount < 0 }">{{ item.amount }}</text>
|
<text class="cell qty" :class="{ plus: item.amount > 0, minus: item.amount < 0 }">{{ item.amount }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="loading" class="loading">
|
<view v-if="loading" class="loading">
|
||||||
<text>加载中...</text>
|
<text>加载中...</text>
|
||||||
</view>
|
</view>
|
||||||
<view v-if="noMore && records.length > 0" class="no-more">
|
<view v-if="noMore && records.length > 0" class="no-more">
|
||||||
<text>没有更多数据了</text>
|
<text>没有更多数据了</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="debug-actions">
|
<!-- <view class="debug-actions">
|
||||||
<!-- <button @click="testLoadMore" size="mini" type="primary">测试加载更多</button>
|
<button @click="testLoadMore" size="mini" type="primary">测试加载更多</button>
|
||||||
<text class="debug-info">当前页: {{ page }}, 加载中: {{ loading }}, 无更多: {{ noMore }}</text> -->
|
<text class="debug-info">当前页: {{ page }}, 加载中: {{ loading }}, 无更多: {{ noMore }}</text>
|
||||||
|
</view> -->
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted, nextTick } from 'vue';
|
||||||
import flowerImg from "@/static/flowers.png"
|
import flowerImg from "@/static/flowers.png"
|
||||||
import moneyImg from "@/static/mind_totle_money.png"
|
import moneyImg from "@/static/mind_totle_money.png"
|
||||||
import emptyImg from "@/static/icon_empty.png"
|
import emptyImg from "@/static/icon_empty.png"
|
||||||
import api from '@/api/api.js';
|
import api from '@/api/api.js';
|
||||||
|
import { onBackPress,onLoad } from '@dcloudio/uni-app';
|
||||||
|
const from=ref('');
|
||||||
|
const user_uuid=ref('');
|
||||||
|
onLoad((options) => {
|
||||||
|
if(options.from){
|
||||||
|
from.value = options.from;
|
||||||
|
}
|
||||||
|
let userInfo= uni.getStorageSync('userInfo')
|
||||||
|
user_uuid.value = userInfo.uuid;
|
||||||
|
loadFirstTwoPages();
|
||||||
|
uni.sendNativeEvent("portraitReport",{
|
||||||
|
msg:{
|
||||||
|
event_nickname: "list_page",
|
||||||
|
page_type: "我的鲜花",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
onBackPress(() => {
|
||||||
|
if(!from.value){
|
||||||
|
plus.runtime.quit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
// 与截图一致的顶部两项统计:总鲜花数与累计金额
|
// 与截图一致的顶部两项统计:总鲜花数与累计金额
|
||||||
const stat = ref({ totalCount: 0, totalAmount: 0.0 });
|
const stat = ref({ totalCount: 0, totalAmount: 0.0 });
|
||||||
|
|
||||||
@@ -87,19 +117,44 @@ const noMore = ref(false);
|
|||||||
const page = ref(1);
|
const page = ref(1);
|
||||||
const pageSize = ref(10);
|
const pageSize = ref(10);
|
||||||
const scrollTop = ref(0);
|
const scrollTop = ref(0);
|
||||||
|
const autoLoading = ref(false);
|
||||||
|
|
||||||
|
const formatDateToYDM = (value) => {
|
||||||
|
if (!value) return '-';
|
||||||
|
const raw = String(value).trim();
|
||||||
|
const directMatch = raw.match(/^(\d{4})[-/.](\d{1,2})[-/.](\d{1,2})/);
|
||||||
|
if (directMatch) {
|
||||||
|
const [, year, month, day] = directMatch;
|
||||||
|
return `${year}-${day.padStart(2, '0')}-${month.padStart(2, '0')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsedDate = new Date(raw);
|
||||||
|
if (Number.isNaN(parsedDate.getTime())) return '-';
|
||||||
|
|
||||||
|
const year = parsedDate.getFullYear();
|
||||||
|
const month = String(parsedDate.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(parsedDate.getDate()).padStart(2, '0');
|
||||||
|
return `${year}-${day}-${month}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
uni.navigateBack({
|
if(!from.value){
|
||||||
fail() {
|
plus.runtime.quit();
|
||||||
uni.redirectTo({ url: '/pages/index/index' });
|
}else{
|
||||||
}
|
uni.navigateBack();
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFlowerList = () => {
|
const getFlowerList = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
console.log('[myFlower] getFlowerList:start', {
|
||||||
|
page: page.value,
|
||||||
|
loading: loading.value,
|
||||||
|
refreshing: refreshing.value,
|
||||||
|
noMore: noMore.value
|
||||||
|
});
|
||||||
// 只在第一页时设置loading状态,避免与onLoadMore冲突
|
// 只在第一页时设置loading状态,避免与onLoadMore冲突
|
||||||
if (page.value === 1) {
|
if (page.value === 1) {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
@@ -107,20 +162,30 @@ const getFlowerList = () => {
|
|||||||
|
|
||||||
console.log('正在获取第', page.value, '页数据...');
|
console.log('正在获取第', page.value, '页数据...');
|
||||||
|
|
||||||
api.getFlowerList({page: page.value}).then(res => {
|
api.getFlowerList({
|
||||||
|
page: page.value,
|
||||||
|
user_uuid: user_uuid.value,
|
||||||
|
}).then(res => {
|
||||||
console.log('接口返回数据:', res);
|
console.log('接口返回数据:', res);
|
||||||
if (res.code === 200 && res.data) {
|
if (res.code === 200 && res.data) {
|
||||||
const { flower_data, total_amount, total_num } = res.data;
|
const { flower_data, total_amount, total_num } = res.data;
|
||||||
|
console.log('[myFlower] getFlowerList:response', {
|
||||||
|
reqPage: page.value,
|
||||||
|
pageNum: flower_data?.pageNum,
|
||||||
|
pages: flower_data?.pages,
|
||||||
|
isLastPage: flower_data?.isLastPage,
|
||||||
|
listLength: flower_data?.list?.length || 0
|
||||||
|
});
|
||||||
|
|
||||||
// 更新统计数据
|
// 更新统计数据
|
||||||
stat.value.totalCount = total_num || 0;
|
stat.value.totalCount = total_num || 0;
|
||||||
stat.value.totalAmount = total_amount || 0;
|
stat.value.totalAmount = total_amount || 0;
|
||||||
|
|
||||||
// 处理列表数据
|
// 处理列表数据
|
||||||
if (flower_data && flower_data.list) {
|
if (flower_data && Array.isArray(flower_data.list)) {
|
||||||
const newRecords = flower_data.list.map(item => ({
|
const newRecords = flower_data.list.map(item => ({
|
||||||
name: item.patient_name || '未知',
|
name: item.patient_name || '账号已注销',
|
||||||
time: item.create_date || '',
|
time: formatDateToYDM(item.create_date),
|
||||||
amount: item.num || 0,
|
amount: item.num || 0,
|
||||||
// 保留原始数据以备后用
|
// 保留原始数据以备后用
|
||||||
original: item
|
original: item
|
||||||
@@ -135,12 +200,28 @@ const getFlowerList = () => {
|
|||||||
console.log('第', page.value, '页数据,追加到列表,新增', newRecords.length, '条');
|
console.log('第', page.value, '页数据,追加到列表,新增', newRecords.length, '条');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否还有更多数据
|
// 判断是否还有更多数据,兼容不同接口字段
|
||||||
noMore.value = flower_data.isLastPage;
|
if (typeof flower_data.isLastPage === 'boolean') {
|
||||||
console.log('是否最后一页:', flower_data.isLastPage, ',总页数:', flower_data.pages);
|
noMore.value = flower_data.isLastPage;
|
||||||
|
} else if (Number(flower_data.pages) > 0) {
|
||||||
|
noMore.value = page.value >= Number(flower_data.pages);
|
||||||
|
} else {
|
||||||
|
// 未返回分页字段时,仅在本页无数据时判定到底
|
||||||
|
noMore.value = newRecords.length === 0;
|
||||||
|
}
|
||||||
|
console.log('是否最后一页:', noMore.value, ',总页数:', flower_data.pages);
|
||||||
}
|
}
|
||||||
|
console.log('[myFlower] getFlowerList:end', {
|
||||||
|
page: page.value,
|
||||||
|
records: records.value.length,
|
||||||
|
noMore: noMore.value
|
||||||
|
});
|
||||||
resolve(res);
|
resolve(res);
|
||||||
} else {
|
} else {
|
||||||
|
console.log('[myFlower] getFlowerList:invalid', {
|
||||||
|
code: res?.code,
|
||||||
|
msg: res?.msg
|
||||||
|
});
|
||||||
reject(new Error('接口返回错误'));
|
reject(new Error('接口返回错误'));
|
||||||
}
|
}
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
@@ -156,18 +237,11 @@ const getFlowerList = () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
onMounted(() => {
|
|
||||||
getFlowerList();
|
|
||||||
});
|
|
||||||
|
|
||||||
const onRefresh = async () => {
|
const onRefresh = async () => {
|
||||||
if (refreshing.value) return;
|
if (refreshing.value || loading.value) return;
|
||||||
refreshing.value = true;
|
refreshing.value = true;
|
||||||
try {
|
try {
|
||||||
page.value = 1;
|
await loadFirstTwoPages();
|
||||||
noMore.value = false;
|
|
||||||
records.value = []; // 清空数据
|
|
||||||
getFlowerList(); // 重新获取第一页数据
|
|
||||||
uni.showToast({ title: '刷新成功', icon: 'none' });
|
uni.showToast({ title: '刷新成功', icon: 'none' });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('刷新失败:', error);
|
console.error('刷新失败:', error);
|
||||||
@@ -177,39 +251,136 @@ const onRefresh = async () => {
|
|||||||
|
|
||||||
const onLoadMore = async () => {
|
const onLoadMore = async () => {
|
||||||
console.log('触发上拉加载更多事件');
|
console.log('触发上拉加载更多事件');
|
||||||
|
console.log('[myFlower] onLoadMore:enter', {
|
||||||
|
page: page.value,
|
||||||
|
loading: loading.value,
|
||||||
|
refreshing: refreshing.value,
|
||||||
|
noMore: noMore.value
|
||||||
|
});
|
||||||
|
|
||||||
// 检查各种状态
|
// 检查各种状态
|
||||||
if (loading.value) {
|
if (loading.value || refreshing.value) {
|
||||||
console.log('正在加载中,忽略重复请求');
|
console.log('正在加载中,忽略重复请求');
|
||||||
|
console.log('[myFlower] onLoadMore:blockByState');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noMore.value) {
|
if (noMore.value) {
|
||||||
console.log('已经没有更多数据了');
|
console.log('已经没有更多数据了');
|
||||||
|
console.log('[myFlower] onLoadMore:blockByNoMore');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('开始加载下一页,当前页码:', page.value);
|
console.log('开始加载下一页,当前页码:', page.value);
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
const currentPage = page.value;
|
||||||
try {
|
try {
|
||||||
page.value += 1;
|
page.value = currentPage + 1;
|
||||||
|
console.log('[myFlower] onLoadMore:request', {
|
||||||
|
fromPage: currentPage,
|
||||||
|
toPage: page.value
|
||||||
|
});
|
||||||
await getFlowerList(); // 等待数据加载完成
|
await getFlowerList(); // 等待数据加载完成
|
||||||
console.log('加载完成,当前页码:', page.value);
|
console.log('加载完成,当前页码:', page.value);
|
||||||
|
console.log('[myFlower] onLoadMore:done', {
|
||||||
|
page: page.value,
|
||||||
|
records: records.value.length,
|
||||||
|
noMore: noMore.value
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载更多失败:', error);
|
console.error('加载更多失败:', error);
|
||||||
page.value -= 1; // 恢复页码
|
page.value = currentPage; // 恢复页码
|
||||||
|
console.log('[myFlower] onLoadMore:rollback', { page: page.value });
|
||||||
uni.showToast({ title: '加载失败', icon: 'error' });
|
uni.showToast({ title: '加载失败', icon: 'error' });
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getListLayoutInfo = () => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const query = uni.createSelectorQuery();
|
||||||
|
query.select('.table-body').boundingClientRect();
|
||||||
|
query.select('.list-content').boundingClientRect();
|
||||||
|
query.exec((res = []) => {
|
||||||
|
const bodyHeight = Number(res?.[0]?.height || 0);
|
||||||
|
const contentHeight = Number(res?.[1]?.height || 0);
|
||||||
|
resolve({ bodyHeight, contentHeight });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const ensureListCanScroll = async () => {
|
||||||
|
if (autoLoading.value || loading.value || refreshing.value || noMore.value) return;
|
||||||
|
autoLoading.value = true;
|
||||||
|
try {
|
||||||
|
while (!noMore.value) {
|
||||||
|
await nextTick();
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||||
|
const { bodyHeight, contentHeight } = await getListLayoutInfo();
|
||||||
|
if (!bodyHeight || !contentHeight) break;
|
||||||
|
if (contentHeight > bodyHeight) break;
|
||||||
|
await onLoadMore();
|
||||||
|
if (loading.value) break;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
autoLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadFirstTwoPages = async () => {
|
||||||
|
console.log('[myFlower] loadFirstTwoPages:start');
|
||||||
|
page.value = 1;
|
||||||
|
noMore.value = false;
|
||||||
|
records.value = [];
|
||||||
|
console.log('[myFlower] loadFirstTwoPages:reset', {
|
||||||
|
page: page.value,
|
||||||
|
records: records.value.length,
|
||||||
|
noMore: noMore.value
|
||||||
|
});
|
||||||
|
await getFlowerList();
|
||||||
|
// 第1页 Promise resolve 早于 finally 复位 loading,这里手动兜底复位
|
||||||
|
loading.value = false;
|
||||||
|
console.log('[myFlower] loadFirstTwoPages:afterPage1', {
|
||||||
|
page: page.value,
|
||||||
|
records: records.value.length,
|
||||||
|
noMore: noMore.value
|
||||||
|
});
|
||||||
|
if (!noMore.value) {
|
||||||
|
console.log('[myFlower] loadFirstTwoPages:triggerPage2');
|
||||||
|
const firstPage = page.value;
|
||||||
|
try {
|
||||||
|
page.value = firstPage + 1;
|
||||||
|
console.log('[myFlower] loadFirstTwoPages:requestPage2', {
|
||||||
|
fromPage: firstPage,
|
||||||
|
toPage: page.value,
|
||||||
|
refreshing: refreshing.value
|
||||||
|
});
|
||||||
|
await getFlowerList();
|
||||||
|
loading.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
page.value = firstPage;
|
||||||
|
console.log('[myFlower] loadFirstTwoPages:page2FailedRollback', { page: page.value });
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log('[myFlower] loadFirstTwoPages:skipPage2(noMore=true)');
|
||||||
|
}
|
||||||
|
console.log('[myFlower] loadFirstTwoPages:end', {
|
||||||
|
page: page.value,
|
||||||
|
records: records.value.length,
|
||||||
|
noMore: noMore.value
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// 测试加载更多功能
|
// 测试加载更多功能
|
||||||
const testLoadMore = () => {
|
const testLoadMore = () => {
|
||||||
console.log('手动测试加载更多');
|
console.log('手动测试加载更多');
|
||||||
onLoadMore();
|
onLoadMore();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -221,13 +392,27 @@ $card: #ffffff;
|
|||||||
|
|
||||||
.flower-page {
|
.flower-page {
|
||||||
background: $bg;
|
background: $bg;
|
||||||
|
--nav-offset: calc(var(--status-bar-height) + 44px);
|
||||||
|
--stats-height: 86rpx;
|
||||||
|
--header-height: 74rpx;
|
||||||
|
/* 导航栏下方固定区域总高度:统计栏 + 表头 */
|
||||||
|
--fixed-block-height: calc(var(--stats-height) + var(--header-height));
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-top-block {
|
||||||
|
position: fixed;
|
||||||
|
top: var(--nav-offset);
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-bar {
|
.stats-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 24rpx 30rpx;
|
height: var(--stats-height);
|
||||||
|
padding: 0 30rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-bottom: 2rpx solid #eee;
|
border-bottom: 2rpx solid #eee;
|
||||||
|
|
||||||
@@ -244,20 +429,25 @@ $card: #ffffff;
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 22rpx 30rpx;
|
align-items: center;
|
||||||
|
height: var(--header-height);
|
||||||
|
padding: 0 30rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
font-size: 30rpx;
|
font-size: 30rpx;
|
||||||
position: sticky;
|
|
||||||
top: 140rpx; /* nav 高度 */
|
|
||||||
z-index: 5;
|
|
||||||
|
|
||||||
.col { width: 33%; }
|
.col { width: 33%; }
|
||||||
.name { text-align: left; }
|
.name { text-align: left; }
|
||||||
.time { text-align: center; }
|
.time { text-align: center; }
|
||||||
.qty { text-align: right; }
|
.qty { text-align: center; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-body {
|
.table-body {
|
||||||
height: calc(100vh - 140rpx - 88rpx - 70rpx);
|
position: fixed;
|
||||||
|
top: calc(var(--nav-offset) + var(--fixed-block-height));
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
/* 充满剩余高度,避免滚动穿透 */
|
/* 充满剩余高度,避免滚动穿透 */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,16 +456,17 @@ $card: #ffffff;
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 26rpx 30rpx;
|
padding: 26rpx 30rpx;
|
||||||
border-bottom: 2rpx solid #f2f2f2;
|
background: #fff;
|
||||||
|
border-bottom: 2rpx solid #ccc;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #333;
|
color: #333;
|
||||||
|
|
||||||
.cell { width: 33%; }
|
.cell { width: 33%; }
|
||||||
.name { text-align: left; }
|
.name { text-align: left; }
|
||||||
.time { text-align: center; color: #666; }
|
.time { text-align: center; color: #666; }
|
||||||
.qty { text-align: right; }
|
.qty { text-align: center; }
|
||||||
.qty.plus { color: #2dbd85; }
|
.qty.plus { color: #333; }
|
||||||
.qty.minus { color: #e34d4d; }
|
.qty.minus { color: #333; }
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty-wrap { padding-top: 200rpx; display: flex; flex-direction: column; align-items: center; color: #bdbdbd; }
|
.empty-wrap { padding-top: 200rpx; display: flex; flex-direction: column; align-items: center; color: #bdbdbd; }
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
<template>
|
||||||
|
<view class="page">
|
||||||
|
<view class="header">
|
||||||
|
<text class="title">scroll-view 上拉加载 Demo</text>
|
||||||
|
<text class="sub">下拉刷新 + 触底加载更多</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<scroll-view
|
||||||
|
class="list-scroll"
|
||||||
|
scroll-y
|
||||||
|
lower-threshold="80"
|
||||||
|
refresher-enabled
|
||||||
|
:refresher-triggered="refreshing"
|
||||||
|
@refresherrefresh="onRefresh"
|
||||||
|
@scrolltolower="onLoadMore"
|
||||||
|
>
|
||||||
|
<view v-for="item in list" :key="item.id" class="list-item">
|
||||||
|
<text class="item-title">{{ item.title }}</text>
|
||||||
|
<text class="item-time">{{ item.time }}</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="loading" class="tip">加载中...</view>
|
||||||
|
<view v-else-if="noMore && list.length > 0" class="tip">没有更多数据了</view>
|
||||||
|
<view v-else-if="list.length === 0" class="tip">暂无数据</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
|
|
||||||
|
const page = ref(1);
|
||||||
|
const pageSize = ref(10);
|
||||||
|
const list = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
const refreshing = ref(false);
|
||||||
|
const noMore = ref(false);
|
||||||
|
|
||||||
|
const totalMockCount = 37;
|
||||||
|
const fullData = Array.from({ length: totalMockCount }, (_, i) => {
|
||||||
|
const index = i + 1;
|
||||||
|
return {
|
||||||
|
id: index,
|
||||||
|
title: `第 ${index} 条数据`,
|
||||||
|
time: `2026-03-${String((index % 28) + 1).padStart(2, '0')}`
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const getPageData = (pageNum, size) => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const start = (pageNum - 1) * size;
|
||||||
|
const end = start + size;
|
||||||
|
resolve(fullData.slice(start, end));
|
||||||
|
}, 350);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchList = async (isRefresh = false) => {
|
||||||
|
if (loading.value) return;
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
if (isRefresh) {
|
||||||
|
page.value = 1;
|
||||||
|
noMore.value = false;
|
||||||
|
}
|
||||||
|
const rows = await getPageData(page.value, pageSize.value);
|
||||||
|
if (isRefresh) {
|
||||||
|
list.value = rows;
|
||||||
|
} else {
|
||||||
|
list.value = [...list.value, ...rows];
|
||||||
|
}
|
||||||
|
noMore.value = rows.length < pageSize.value;
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
refreshing.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onRefresh = async () => {
|
||||||
|
if (refreshing.value) return;
|
||||||
|
refreshing.value = true;
|
||||||
|
await fetchList(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onLoadMore = async () => {
|
||||||
|
if (loading.value || refreshing.value || noMore.value) return;
|
||||||
|
page.value += 1;
|
||||||
|
await fetchList(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
fetchList(true);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.page {
|
||||||
|
height: 100vh;
|
||||||
|
background: #f7f8fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
padding: 30rpx;
|
||||||
|
background: #ffffff;
|
||||||
|
border-bottom: 1rpx solid #ededed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: block;
|
||||||
|
font-size: 34rpx;
|
||||||
|
color: #222;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub {
|
||||||
|
display: block;
|
||||||
|
margin-top: 8rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-scroll {
|
||||||
|
height: calc(100vh - 130rpx);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-item {
|
||||||
|
margin: 20rpx 24rpx 0;
|
||||||
|
padding: 24rpx;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-title {
|
||||||
|
display: block;
|
||||||
|
font-size: 30rpx;
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-time {
|
||||||
|
display: block;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip {
|
||||||
|
padding: 28rpx 0 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #9aa0a6;
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,24 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<navBar :title="'新的患者'" />
|
||||||
<view class="new-patient-page">
|
<view class="new-patient-page">
|
||||||
|
|
||||||
|
|
||||||
<uni-nav-bar
|
|
||||||
left-icon="left"
|
|
||||||
title="我的患者"
|
|
||||||
@clickLeft="goBack"
|
|
||||||
fixed
|
|
||||||
color="#8B2316"
|
|
||||||
height="140rpx"
|
|
||||||
:border="false"
|
|
||||||
backgroundColor="#eeeeee"
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 提醒区域 -->
|
<!-- 提醒区域 -->
|
||||||
<view class="reminder-section">
|
<view class="contentbox">
|
||||||
|
<view class="reminder-section">
|
||||||
<view class="reminder-icon">
|
<view class="reminder-icon">
|
||||||
<uni-icons type="notification" size="16" color="#ff9500"></uni-icons>
|
<up-image :src="tipImg" width="35rpx" height="42rpx"></up-image>
|
||||||
</view>
|
</view>
|
||||||
<text class="reminder-text">提醒: 为了避免不必要的纠纷,请您务必选择线下就诊过的患者</text>
|
<text class="reminder-text">提醒: 为了避免不必要的纠纷,请您务必选择线下就诊过的患者</text>
|
||||||
</view>
|
</view>
|
||||||
@@ -29,15 +16,15 @@
|
|||||||
<view class="pending-request" v-for="(item, index) in applyList" :key="index">
|
<view class="pending-request" v-for="(item, index) in applyList" :key="index">
|
||||||
<view class="request-item">
|
<view class="request-item">
|
||||||
<view class="avatar">
|
<view class="avatar">
|
||||||
<up-image :src="docUrl+item.photo" radius="10rpx" width="80rpx" height="80rpx" ></up-image>
|
<up-image :src="docUrl+item.photo" radius="10rpx" width="120rpx" height="120rpx" ></up-image>
|
||||||
</view>
|
</view>
|
||||||
<view class="request-content">
|
<view class="request-content">
|
||||||
<view class="request-time">{{ item.createDate }}</view>
|
<view class="request-time">{{ item.createDate }}</view>
|
||||||
<view class="request-text">{{ item.content }}</view>
|
<view class="request-text">{{ item.content }}</view>
|
||||||
|
|
||||||
<view class="action-buttons">
|
<view class="action-buttons">
|
||||||
<button class="reject-btn" @click="applyListOperate(item.uuid,3)">拒绝</button>
|
<button class="reject-btn" @click="applyListOperate(item.uuid,3,item.content,item.patientUuid)">拒绝</button>
|
||||||
<button class="agree-btn" @click="applyListOperate(item.uuid,2)">同意</button>
|
<button class="agree-btn" @click="applyListOperate(item.uuid,2,item.content,item.patientUuid)">同意</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -48,14 +35,14 @@
|
|||||||
<view class="history-section" v-if="historyList.length > 0">
|
<view class="history-section" v-if="historyList.length > 0">
|
||||||
<view class="section-title">申请记录(近一月)</view>
|
<view class="section-title">申请记录(近一月)</view>
|
||||||
<view class="history-list">
|
<view class="history-list">
|
||||||
<view class="history-item" v-for="(item, index) in historyList" :key="index">
|
<view class="history-item" v-for="(item, index) in historyList" :key="index" @click="goPatientDetail(item.patient_uuid,item.status)">
|
||||||
<view class="avatar">
|
<view class="avatar">
|
||||||
<up-image v-if="docUrl+item.patient_photo" :src="docUrl + item.patient_photo" radius="10rpx" width="80rpx" height="80rpx"></up-image>
|
<up-image v-if="docUrl+item.patient_photo" :src="docUrl + item.patient_photo" radius="10rpx" width="120rpx" height="120rpx"></up-image>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
<view class="history-content">
|
<view class="history-content">
|
||||||
<view class="history-time">{{ formatDate(item.createDate) }}</view>
|
<view class="history-time">{{ formatDate2(item.create_date) }}</view>
|
||||||
<view class="nickname">{{ item.nickname || item.patient_name }}</view>
|
<view class="nickname">昵称:{{ item.patient_name || item.nickname }}</view>
|
||||||
<view class="history-text">{{ item.content}}</view>
|
<view class="history-text">{{ item.content}}</view>
|
||||||
<view class="status-info">
|
<view class="status-info">
|
||||||
<up-image :src="goImg" width="30rpx" height="30rpx" v-if="item.status==2"></up-image>
|
<up-image :src="goImg" width="30rpx" height="30rpx" v-if="item.status==2"></up-image>
|
||||||
@@ -65,7 +52,10 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<empty v-if="applyList.length == 0 && historyList.length == 0" :emptyDesc="'暂无新随访申请患者'" />
|
||||||
|
|
||||||
|
</view>
|
||||||
<!-- 底部按钮 -->
|
<!-- 底部按钮 -->
|
||||||
<view class="bottom-button">
|
<view class="bottom-button">
|
||||||
<button class="add-patient-btn" @click="addPatient">加患者</button>
|
<button class="add-patient-btn" @click="addPatient">加患者</button>
|
||||||
@@ -75,11 +65,27 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { onLoad,onShow} from '@dcloudio/uni-app';
|
import { onLoad,onShow,onBackPress} from '@dcloudio/uni-app';
|
||||||
import goImg from "@/static/go_big.png"
|
import goImg from "@/static/go_big.png"
|
||||||
import api from '@/api/api.js'
|
import api from '@/api/api.js'
|
||||||
import docUrl from "@/utils/docUrl"
|
import docUrl from "@/utils/docUrl"
|
||||||
|
import dayjs from 'dayjs'
|
||||||
import navTo from "@/utils/navTo.js"
|
import navTo from "@/utils/navTo.js"
|
||||||
|
import empty from "@/components/empty/empty.vue"
|
||||||
|
import navBar from "@/components/navBar/navBar.vue"
|
||||||
|
import tipImg from "@/static/sendgroup_tishi_big.png"
|
||||||
|
const from=ref('');
|
||||||
|
onLoad((options) => {
|
||||||
|
if(options.from){
|
||||||
|
from.value = options.from;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onBackPress(() => {
|
||||||
|
if(!from.value){
|
||||||
|
plus.runtime.quit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
// 响应式数据
|
// 响应式数据
|
||||||
const pendingRequest = ref({
|
const pendingRequest = ref({
|
||||||
name: '陈新华',
|
name: '陈新华',
|
||||||
@@ -91,7 +97,11 @@ const historyList = ref([]);
|
|||||||
|
|
||||||
// 方法
|
// 方法
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
uni.navigateBack();
|
if(!from.value){
|
||||||
|
plus.runtime.quit();
|
||||||
|
}else{
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const rejectRequest = () => {
|
const rejectRequest = () => {
|
||||||
@@ -162,20 +172,27 @@ const getApplyList = async () => { // 申请列表
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const applyListOperate = async (uuid,status) => {
|
const applyListOperate = async (uuid,status,content,patientUuid) => {
|
||||||
let data = {
|
let data = {
|
||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
status: status
|
status: status
|
||||||
}
|
}
|
||||||
const res = await api.applyListOperate(data);
|
const res = await api.applyListOperate(data);
|
||||||
if(res.code === 200){
|
if(res.code === 200){
|
||||||
|
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: '操作成功',
|
title: '操作成功',
|
||||||
icon: 'none',
|
icon: 'none',
|
||||||
duration: 1500
|
duration: 1500
|
||||||
});
|
});
|
||||||
|
let nickname = content.split(',')[0].replace('我是', '');
|
||||||
getApplyList();
|
getApplyList();
|
||||||
getRelationRecordLately();
|
getRelationRecordLately();
|
||||||
|
if(status == 2){
|
||||||
|
navTo({
|
||||||
|
url: `/pages_app/patientRemark/patientRemark?uuid=${patientUuid}&&nickname=${nickname}`
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
@@ -184,6 +201,15 @@ const getApplyList = async () => { // 申请列表
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const goPatientDetail = (uuid,status) => {
|
||||||
|
|
||||||
|
if(status == 2){
|
||||||
|
navTo({
|
||||||
|
url: `/pages_app/patientDetail/patientDetail?uuid=${uuid}&from=myPatient`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 辅助方法
|
// 辅助方法
|
||||||
// 格式化日期
|
// 格式化日期
|
||||||
const formatDate = (dateString) => {
|
const formatDate = (dateString) => {
|
||||||
@@ -196,6 +222,9 @@ const formatDate = (dateString) => {
|
|||||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||||
};
|
};
|
||||||
|
const formatDate2 = (dateString) => {
|
||||||
|
return dayjs(dateString).format('YYYY-MM-DD HH:mm:ss');
|
||||||
|
}
|
||||||
|
|
||||||
// 获取状态文本
|
// 获取状态文本
|
||||||
const getStatusText = (status) => {
|
const getStatusText = (status) => {
|
||||||
@@ -208,7 +237,7 @@ const getStatusText = (status) => {
|
|||||||
|
|
||||||
const addPatient = () => {
|
const addPatient = () => {
|
||||||
navTo({
|
navTo({
|
||||||
url:'/pages_app/myCode/myCode'
|
url:'/pages_app/myCode/myCode?from=myPatient'
|
||||||
});
|
});
|
||||||
// 这里可以跳转到添加患者页面
|
// 这里可以跳转到添加患者页面
|
||||||
};
|
};
|
||||||
@@ -216,7 +245,7 @@ const addPatient = () => {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.new-patient-page {
|
.new-patient-page {
|
||||||
min-height: 100vh;
|
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,34 +340,47 @@ const addPatient = () => {
|
|||||||
margin-right: 60rpx; // 为了保持标题居中
|
margin-right: 60rpx; // 为了保持标题居中
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.contentbox{
|
||||||
|
top: calc(var(--status-bar-height) + 44px);
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 100rpx;
|
||||||
|
overflow-y: scroll;
|
||||||
|
z-index: 1;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
.reminder-section {
|
.reminder-section {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items:center;
|
||||||
padding: 30rpx;
|
padding: 30rpx;
|
||||||
|
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
margin-bottom: 20rpx;
|
|
||||||
|
|
||||||
.reminder-icon {
|
.reminder-icon {
|
||||||
|
width: 35rpx;
|
||||||
|
height: 42rpx;
|
||||||
margin-right: 20rpx;
|
margin-right: 20rpx;
|
||||||
margin-top: 4rpx;
|
margin-top: 4rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reminder-text {
|
.reminder-text {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
font-size: 28rpx;
|
font-size: 32rpx;
|
||||||
color: #333;
|
color: #999;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.follow-up-section {
|
.follow-up-section {
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
margin-bottom: 20rpx;
|
|
||||||
|
|
||||||
.section-title {
|
.section-title {
|
||||||
padding: 30rpx 30rpx 20rpx;
|
padding: 30rpx 30rpx 30rpx;
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
|
background-color: #f0f0f0;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
color: #333;
|
color: #333;
|
||||||
border-bottom: 1rpx solid #f0f0f0;
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
@@ -349,11 +391,12 @@ const addPatient = () => {
|
|||||||
|
|
||||||
.request-item {
|
.request-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 20rpx;
|
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
width: 80rpx;
|
width: 120rpx;
|
||||||
height: 80rpx;
|
height: 120rpx;
|
||||||
|
margin-top: 30rpx;
|
||||||
background-color: #ffb6c1;
|
background-color: #ffb6c1;
|
||||||
border-radius: 12rpx;
|
border-radius: 12rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -361,8 +404,8 @@ const addPatient = () => {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
.avatar-icon {
|
.avatar-icon {
|
||||||
width: 40rpx;
|
width: 120rpx;
|
||||||
height: 40rpx;
|
height: 120rpx;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
@@ -370,7 +413,7 @@ const addPatient = () => {
|
|||||||
|
|
||||||
.request-content {
|
.request-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
margin-left: 20rpx;
|
||||||
.request-text {
|
.request-text {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #333;
|
color: #333;
|
||||||
@@ -432,18 +475,19 @@ const addPatient = () => {
|
|||||||
margin-bottom: 120rpx; // 为底部按钮留出空间
|
margin-bottom: 120rpx; // 为底部按钮留出空间
|
||||||
|
|
||||||
.section-title {
|
.section-title {
|
||||||
padding: 30rpx 30rpx 20rpx;
|
padding: 30rpx 30rpx 30rpx;
|
||||||
font-size: 32rpx;
|
font-size: 32rpx;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
background-color: #f0f0f0;
|
||||||
color: #333;
|
color: #333;
|
||||||
border-bottom: 1rpx solid #f0f0f0;
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.history-list {
|
.history-list {
|
||||||
margin-bottom: 100rpx;
|
margin-bottom: 30rpx;
|
||||||
.history-item {
|
.history-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 20rpx;
|
|
||||||
padding: 30rpx;
|
padding: 30rpx;
|
||||||
border-bottom: 1rpx solid #f0f0f0;
|
border-bottom: 1rpx solid #f0f0f0;
|
||||||
|
|
||||||
@@ -452,8 +496,9 @@ const addPatient = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.avatar {
|
.avatar {
|
||||||
width: 80rpx;
|
width: 120rpx;
|
||||||
height: 80rpx;
|
height: 120rpx;
|
||||||
|
margin-top: 30rpx;
|
||||||
background-color: #ffb6c1;
|
background-color: #ffb6c1;
|
||||||
border-radius: 12rpx;
|
border-radius: 12rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -470,18 +515,24 @@ const addPatient = () => {
|
|||||||
|
|
||||||
.history-content {
|
.history-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
min-width: 0;
|
||||||
.nickname {
|
.nickname {
|
||||||
font-size: 28rpx;
|
font-size: 30rpx;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
color: #8B2316;
|
color: #8B2316;
|
||||||
margin-bottom: 10rpx;
|
margin-bottom: 10rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.history-text {
|
.history-text {
|
||||||
font-size: 28rpx;
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 30rpx;
|
||||||
color: #333;
|
color: #333;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
margin-bottom: 20rpx;
|
margin-bottom: 20rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1351
-995
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user