11.13早上提交
727
App.vue
@ -1,613 +1,152 @@
|
||||
<script >
|
||||
import RootStore from "@xkit-yx/im-store-v2";
|
||||
/** 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"
|
||||
import my_api from '@/api/my_api.js'
|
||||
import GlobalDialog from "@/components/GlobalDialog.vue"
|
||||
// #ifdef APP-PLUS
|
||||
/** 推送插件 */
|
||||
const nimPushPlugin = uni.requireNativePlugin("NIMUniPlugin-PluginModule");
|
||||
console.log("nimPushPlugin1111");
|
||||
console.log(nimPushPlugin);
|
||||
/** 音视频通话插件 */
|
||||
// const nimCallKit = (uni.$UIKitCallKit =
|
||||
// uni.requireNativePlugin("netease-CallKit"));
|
||||
// #endif
|
||||
const app = getApp()
|
||||
let startByNotificationId = "";
|
||||
|
||||
|
||||
export default {
|
||||
globalData: {
|
||||
plAd: true
|
||||
},
|
||||
onLaunch() {
|
||||
|
||||
// #ifdef APP-PLUS
|
||||
/** 关闭启动画面,锁定竖屏 */
|
||||
try {
|
||||
plus.navigator.closeSplashscreen();
|
||||
plus.screen.lockOrientation("portrait-primary");
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
// 点击通知栏推送监听
|
||||
|
||||
nimPushPlugin.addOpenNotificationListener((res) => {
|
||||
console.log("推送监听");
|
||||
console.log("res",res);
|
||||
if (typeof res === 'object') {
|
||||
|
||||
console.log("=====addOpenNotificationListener success:", JSON.stringify(res))
|
||||
uni.redirectTo({
|
||||
url: `/pages_app/patientMsg/patientMsg?from=push`,
|
||||
success: () => {
|
||||
app.globalData.plAd=false;
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log("跳转失败", err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log("=====addOpenNotificationListener unexpected:", res)
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
|
||||
// uni-app客户端获取push客户端标记,代码可以实现在App.vue中
|
||||
// uni.getPushClientId({
|
||||
// success: (res) => {
|
||||
// let push_clientid = res.cid
|
||||
// uni.setStorageSync("push_clientid", push_clientid)
|
||||
// console.log('客户端推送标识cid:',push_clientid)
|
||||
|
||||
// const systemInfo = uni.getSystemInfoSync();
|
||||
// console.log("systemInfo:", systemInfo)
|
||||
|
||||
|
||||
// let userInfo= uni.getStorageSync('userInfo')
|
||||
// console.log("userinfo:", userInfo)
|
||||
// if(!userInfo){
|
||||
// return
|
||||
// }
|
||||
// if(userInfo.uuid){
|
||||
// let client_type = ""
|
||||
// if (systemInfo.platform === 'android') {
|
||||
// client_type = "A"
|
||||
// } else if (systemInfo.platform === 'ios') {
|
||||
// client_type = "I"
|
||||
// }
|
||||
// console.log("client_type:", client_type)
|
||||
// if(client_type){
|
||||
// my_api.addUniappCid({
|
||||
// user_uuid: userInfo.uuid,
|
||||
// client_type:client_type,
|
||||
// cid: push_clientid
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// fail(err) {
|
||||
// console.error("unipush: ", err)
|
||||
// }
|
||||
// })
|
||||
|
||||
|
||||
// uni.onPushMessage((res)=>{
|
||||
// console.log("收到推送消息:", res)
|
||||
|
||||
// let app_isback = uni.getStorageSync("app_isback")
|
||||
// console.log("app_isback:", app_isback)
|
||||
// uni.showModal({
|
||||
// title: res.data.title,
|
||||
// content: res.type,
|
||||
// showCancel: false
|
||||
// });
|
||||
|
||||
// if(res.type === 'click' ){
|
||||
|
||||
// }else{
|
||||
// if(app_isback){
|
||||
// uni.createPushMessage({
|
||||
// title: res.data.title,
|
||||
// content: res.data.content,
|
||||
// payload: res.data.payload,
|
||||
// delay: 1,
|
||||
// success: (res) => {
|
||||
// console.log("创建推送消息成功", res)
|
||||
// }
|
||||
// })
|
||||
// }else{
|
||||
// console.log('[App] emit global-dialog:show', res)
|
||||
// uni.$emit('global-dialog:show', {
|
||||
// title: res.data.title || '消息通知',
|
||||
// content: res.data.content || '',
|
||||
// confirmText: '我知道了',
|
||||
// position: 'top',
|
||||
// offsetTop: '160rpx'
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
|
||||
/** 设置语言 (此处为了方便demo切换语言,将其存到本地,实际需根据业务情况设置)*/
|
||||
setLanguage(
|
||||
uni.getStorageSync("switchToEnglishFlag") == "en" ? "en" : "zh"
|
||||
);
|
||||
/** 已经登录了 不用走初始化逻辑*/
|
||||
if (
|
||||
uni?.$UIKitStore?.connectStore?.connectStatus ===
|
||||
V2NIMConst.V2NIMConnectStatus.V2NIM_CONNECT_STATUS_CONNECTED
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
let storage_token='';
|
||||
let storage_accid='';
|
||||
if (process.env.UNI_PLATFORM == "h5") {
|
||||
if (window.location.href.indexOf('dev') > -1) {
|
||||
storage_accid=uni.getStorageSync('AUTH_YX_ACCID_App');
|
||||
storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App');
|
||||
} else {
|
||||
storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App');
|
||||
storage_token=uni.getStorageSync('DEV_AUTH_YX_TOKEN_App');
|
||||
}
|
||||
} else if(process.env.UNI_PLATFORM == "mp-weixin") {
|
||||
const {
|
||||
envVersion
|
||||
} = uni.getAccountInfoSync().miniProgram;
|
||||
if (envVersion == "release") {
|
||||
storage_accid=uni.getStorageSync('AUTH_YX_ACCID_App');
|
||||
storage_token=uni.setStorageSync('AUTH_YX_TOKEN_App');
|
||||
} else {
|
||||
storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App');
|
||||
storage_token=uni.getStorageSync('DEV_AUTH_YX_TOKEN_App');
|
||||
}
|
||||
}else{
|
||||
storage_accid=uni.getStorageSync('DEV_AUTH_YX_ACCID_App');
|
||||
storage_token=uni.getStorageSync('DEV_AUTH_YX_TOKEN_App');
|
||||
globalData: {
|
||||
plAd: true,
|
||||
dotNumber:{
|
||||
|
||||
}
|
||||
const account =storage_accid;
|
||||
const token = storage_token;
|
||||
if(!account || !token){
|
||||
uni.redirectTo({
|
||||
url: '/pages_app/login/login'
|
||||
});
|
||||
return;
|
||||
}
|
||||
console.log("account",account);
|
||||
console.log("token",token);
|
||||
console.log("account",typeof account);
|
||||
console.log("token",typeof token);
|
||||
const imOptions = {
|
||||
appkey: "885dea390870814acf3ba8558c717572", // 请填写你的appkey
|
||||
account: String(account),//"9ufkll2xo57km6224xe", // 请填写你的account
|
||||
token:String( token)//"4918605da57e573cff93209df56f351d", // 请填写你的token
|
||||
},
|
||||
onLaunch(options) {
|
||||
|
||||
console.log('打印options');
|
||||
console.log(options);
|
||||
if(options && options.referrerInfo.extraData && options.referrerInfo.extraData.token){
|
||||
uni.setStorageSync("DEV_AUTH_TOKEN_App", options.referrerInfo.extraData.token);
|
||||
uni.setStorageSync("userInfo", options.referrerInfo.extraData.userInfo);
|
||||
};
|
||||
console.log("onLaunch");
|
||||
if (imOptions) {
|
||||
console.log("初始化im");
|
||||
this.initNim(imOptions);
|
||||
} else {
|
||||
/** 未登录 跳转登录页 */
|
||||
// customRedirectTo({
|
||||
// url: isWxApp ? "/pages/index/index" : "/pages/Login/index",
|
||||
// });
|
||||
if(options && options.referrerInfo.extraData && options.referrerInfo.extraData.targetPath){
|
||||
uni.navigateTo({
|
||||
url: options.referrerInfo.extraData.targetPath
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
console.log("app传递登录信息onLaunch-------------------");
|
||||
try {
|
||||
// #ifdef APP
|
||||
// uni.onNativeEventReceive((event, data) => {
|
||||
|
||||
|
||||
// console.log("app传递登录信息-------------------");
|
||||
// console.log("event数据");
|
||||
// console.log(event);
|
||||
// console.log("data数据");
|
||||
// console.log(data);
|
||||
// if (event.indexOf("loginInfo") > -1) {
|
||||
// uni.setStorageSync("DEV_AUTH_TOKEN_App", data.token);
|
||||
// uni.setStorageSync("userInfo", data.userInfo);
|
||||
// console.log("获取token数据");
|
||||
// console.log(uni.getStorageSync("DEV_AUTH_TOKEN_App"));
|
||||
// }
|
||||
// });
|
||||
// #endif
|
||||
} catch (error) {
|
||||
console.log("app传递登录信息error-------------------");
|
||||
console.log(error);
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
// #ifdef APP-PLUS
|
||||
console.log("onShow");
|
||||
uni?.$UIKitNIM?.V2NIMSettingService?.setAppBackground(false);
|
||||
uni.setStorageSync("app_isback", false)
|
||||
// 点击通知栏推送监听
|
||||
// nimPushPlugin.addOpenNotificationListener((res) => {
|
||||
// console.log("推送监听");
|
||||
// console.log("res",res);
|
||||
// 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() {
|
||||
console.log("onHide");
|
||||
uni.setStorageSync("app_isback", true)
|
||||
// #ifdef APP-PLUS
|
||||
uni?.$UIKitNIM?.V2NIMSettingService?.setAppBackground(true);
|
||||
// #endif
|
||||
|
||||
// 重置推送 startByNotificationId
|
||||
startByNotificationId = "";
|
||||
},
|
||||
components:{
|
||||
GlobalDialog
|
||||
},
|
||||
methods: {
|
||||
initNim(opts) {
|
||||
console.log("initNim1111111111");
|
||||
/** 保存登录信息 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,
|
||||
needReconnect: true,
|
||||
debugLevel: "debug",
|
||||
apiVersion: "v2",
|
||||
enableV2CloudConversation: enableV2CloudConversation,
|
||||
},
|
||||
{
|
||||
V2NIMLoginServiceConfig: {
|
||||
/**
|
||||
* 微信小程序需要使用单独的lbsUrls和linkUrl
|
||||
*/
|
||||
lbsUrls: isWxApp
|
||||
? ["https://lbs.netease.im/lbs/wxwebconf.jsp"]
|
||||
: ["https://lbs.netease.im/lbs/webconf.jsp"],
|
||||
linkUrl: isWxApp ? "wlnimsc0.netease.im" : "weblink.netease.im",
|
||||
/**
|
||||
* 使用固定设备ID,
|
||||
*/
|
||||
isFixedDeviceId: true,
|
||||
},
|
||||
}
|
||||
));
|
||||
|
||||
/** 初始化 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
|
||||
);
|
||||
const PACKAGE_NAME = 'cn.shangyu.gdxzExpert';
|
||||
let sessionId=conversationType == 1
|
||||
? uni.$UIKitStore.userStore.myUserInfo.accountId
|
||||
: targetId;
|
||||
// 设置离线强推,厂商相关推送在此处配置
|
||||
// 具体参考文档 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=${PACKAGE_NAME}/com.netease.nimlib.uniapp.push.NotificationClickActivity;launchFlags=0x04000000;i.sessionType=${conversationType};S.sessionId=${sessionId};end`,
|
||||
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=${PACKAGE_NAME}/com.netease.nimlib.uniapp.push.NotificationClickActivity;launchFlags=0x04000000;i.sessionType=${conversationType};S.sessionId=${sessionId};end`
|
||||
},
|
||||
androidConfig: {
|
||||
category: "IM", //可选项,标识消息类型,用于标识高优先级透传场景,详见官方文档 AndroidConfig.category
|
||||
},
|
||||
},
|
||||
honorField: {
|
||||
notification: {
|
||||
// AndroidNotification
|
||||
clickAction: {
|
||||
//必填,消息点击行为
|
||||
type: 1, //必填,消息点击行为类型,取值如下:1:打开应用自定义页面 2:点击后打开特定URL 3:点击后打开应用
|
||||
//自定义页面中intent的实现,请参见指定intent参数。当type为1时,字段intent和action至少二选一。
|
||||
intent: `intent://com.honor.push/deeplink?#Intent;scheme=pushscheme;launchFlags=0x04000000;i.sessionType=${conversationType};S.sessionId=${sessionId};end`,
|
||||
},
|
||||
importance: "NORMAL", //可选项,Android通知消息分类,决定用户设备消息通知行为,取值如下:LOW:资讯营销类消息 NORMAL:服务与通讯类消息
|
||||
},
|
||||
},
|
||||
vivoField: {
|
||||
skipType: "4", //必填,点击跳转类型 1:打开APP首页 2:打开链接 3:自定义 4:打开app内指定页面,默认为1
|
||||
skipContent: `intent:#Intent;action=com.netease.nimlib.uniapp.push.NotificationClickActivity;component=${PACKAGE_NAME}/com.netease.nimlib.uniapp.push.NotificationClickActivity;launchFlags=0x04000000;i.sessionType=${conversationType};S.sessionId=${sessionId};end`,
|
||||
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: "com.netease.nimlib.uniapp.push.NotificationClickActivity",
|
||||
action_parameters: JSON.stringify({
|
||||
sessionType: conversationType,
|
||||
sessionId: sessionId,
|
||||
}),
|
||||
},
|
||||
fcmFieldV1: {
|
||||
message: {
|
||||
android: {
|
||||
priority: "",
|
||||
data: {
|
||||
sessionType: conversationType,
|
||||
sessionId: sessionId,
|
||||
},
|
||||
notification: {
|
||||
click_action: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// IOS apns
|
||||
sessionId:sessionId,
|
||||
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: "",
|
||||
// },
|
||||
|
||||
miPush: {
|
||||
appId: "2882303761517470793",
|
||||
appKey: "5431747048793",
|
||||
certificateName: "Expert_Mi_Push",
|
||||
},
|
||||
hwPush: {
|
||||
appId: "10526652",
|
||||
certificateName: "Expert_Hw_push_f",
|
||||
},
|
||||
|
||||
oppoPush: {
|
||||
appId: "3364888",
|
||||
appKey: "75D5Vqsg63wok0S0w4SKog0w8",
|
||||
certificateName: "Expert_Op_Push",
|
||||
secret: "416a4f5eF822ddcB73B627Cc310636D7",
|
||||
|
||||
},
|
||||
vivoPush: {
|
||||
appId: "100034326",
|
||||
appKey: "e789634c1f76c8f184b1def1101ce824",
|
||||
certificateName: "Expert_Vi_Push",
|
||||
secret: "416a4f5eF822ddcB73B627Cc310636D7",
|
||||
},
|
||||
fcmPush: {
|
||||
certificateName: "FCM_PUSH_CERT",
|
||||
},
|
||||
mzPush: {
|
||||
appId: "111",
|
||||
appKey: "111",
|
||||
certificateName: "MEIZU_PUSH_CERT",
|
||||
},
|
||||
apns: {
|
||||
certificateName: "专家端Pro",
|
||||
},
|
||||
});
|
||||
try {
|
||||
|
||||
|
||||
// #ifdef APP
|
||||
|
||||
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
|
||||
|
||||
|
||||
/** 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 = "";
|
||||
}
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.log("登录失败", err);
|
||||
});
|
||||
},
|
||||
logout() {
|
||||
uni.removeStorageSync(STORAGE_KEY);
|
||||
try {
|
||||
// nimCallKit.logout({}, (ret) => {
|
||||
// if (ret.code != 200) {
|
||||
// console.log("音视频通话插件退出失败");
|
||||
// } else {
|
||||
// console.log("音视频通话插件退出成功");
|
||||
// }
|
||||
// });
|
||||
} catch (error) {
|
||||
console.log("音视频通话插件退出失败", error);
|
||||
}
|
||||
// 退出登录
|
||||
uni.$UIKitNIM.V2NIMLoginService.logout().then((res) => {
|
||||
console.log("退出登录", res);
|
||||
uni.$UIKitStore.destroy();
|
||||
uni.clearStorageSync();
|
||||
// 跳转到登录页面
|
||||
uni.reLaunch({
|
||||
url: '/pages_app/login/login'
|
||||
});
|
||||
|
||||
});
|
||||
},
|
||||
} catch (error) {}
|
||||
},
|
||||
onHide() {},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<GlobalDialog />
|
||||
<GlobalDialog />
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
/*每个页面公共css */
|
||||
@import '@/uni_modules/uni-scss/index.scss';
|
||||
/* #ifndef APP-NVUE */
|
||||
@import '@/static/customicons.css';
|
||||
// 设置整个项目的背景色
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.uni-navbar__header-btns-right{
|
||||
min-width: 120rpx;
|
||||
width:auto!important;
|
||||
}
|
||||
/* #endif */
|
||||
.uni-nav-bar-text{
|
||||
font-weight: bold;
|
||||
font-size: 34rpx!important;
|
||||
}
|
||||
.example-info {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
padding: 10px;
|
||||
}
|
||||
.twoline{
|
||||
display: -webkit-box;
|
||||
-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; }
|
||||
// .nav-right{
|
||||
// margin-top: -20px;
|
||||
// }
|
||||
/*每个页面公共css */
|
||||
@import "@/uni_modules/uni-scss/index.scss";
|
||||
/* #ifndef APP-NVUE */
|
||||
@import "@/static/customicons.css";
|
||||
// 设置整个项目的背景色
|
||||
page {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.uni-navbar__header-btns-right {
|
||||
min-width: 120rpx;
|
||||
width: auto !important;
|
||||
}
|
||||
/* #endif */
|
||||
.uni-nav-bar-text {
|
||||
font-weight: bold;
|
||||
font-size: 36rpx !important;
|
||||
}
|
||||
.example-info {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
padding: 10px;
|
||||
}
|
||||
.twoline {
|
||||
display: -webkit-box;
|
||||
-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;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
{
|
||||
"prompt" : "template"
|
||||
"prompt" : "none"
|
||||
}
|
||||
|
||||
40
api/api.js
@ -1,4 +1,5 @@
|
||||
import {request} from '@/utils/request.js'
|
||||
|
||||
const api = {
|
||||
|
||||
expertWxLogin(jscode){
|
||||
@ -607,7 +608,46 @@ const api = {
|
||||
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);
|
||||
},
|
||||
}
|
||||
|
||||
export default api
|
||||
@ -112,7 +112,7 @@ const maskStyle = computed(() => position.value === 'top' ? { paddingTop: offset
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
display: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
// 非模态:容器不截获事件
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
<template>
|
||||
<!-- 顶部导航栏 -->
|
||||
<uni-nav-bar
|
||||
<view class="navbox">
|
||||
<view class="status_bar"></view>
|
||||
<uni-nav-bar
|
||||
:left-icon="showLeft?'left':''"
|
||||
:title="title"
|
||||
@clickLeft="goBack"
|
||||
fixed
|
||||
color="#8B2316"
|
||||
height="180rpx"
|
||||
:border="false"
|
||||
backgroundColor="#eeeeee"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@ -20,6 +21,10 @@
|
||||
type:Boolean,
|
||||
default:true
|
||||
},
|
||||
noticeBack:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
title:{
|
||||
type:String,
|
||||
default:''
|
||||
@ -33,10 +38,21 @@
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<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>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
v-for="(item, index) in tabList"
|
||||
:key="index"
|
||||
@click="switchTab(index, item)"
|
||||
:class="{ active: currentTab === index }"
|
||||
:class="{ active: 2 === index }"
|
||||
>
|
||||
<!-- 图标容器 -->
|
||||
<view class="icon-container">
|
||||
@ -121,32 +121,56 @@
|
||||
if (currentTab.value === index) return;
|
||||
|
||||
// 更新当前tab
|
||||
currentTab.value = index;
|
||||
|
||||
// 清除红点
|
||||
if (item.showRedDot) {
|
||||
item.showRedDot = false;
|
||||
//currentTab.value = index;
|
||||
let msg="home"
|
||||
if(index == 0){
|
||||
msg="home"
|
||||
}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({
|
||||
url: item.pagePath,
|
||||
fail: () => {
|
||||
// 如果页面不存在,使用navigateTo
|
||||
uni.navigateTo({
|
||||
url: item.pagePath,
|
||||
fail: () => {
|
||||
// uni.redirectTo({
|
||||
// url: item.pagePath,
|
||||
// fail: () => {
|
||||
// // 如果页面不存在,使用navigateTo
|
||||
// uni.navigateTo({
|
||||
// url: item.pagePath,
|
||||
// fail: () => {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
|
||||
// 触发父组件事件
|
||||
emit('tabChange', {
|
||||
index,
|
||||
item
|
||||
});
|
||||
// emit('tabChange', {
|
||||
// index,
|
||||
// item
|
||||
// });
|
||||
|
||||
};
|
||||
|
||||
// 设置徽章数量
|
||||
|
||||
64
components/topTip/topTip.vue
Normal file
@ -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>
|
||||
273
js_sdk/wa-permission/permission.js
Normal file
@ -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}
|
||||
4
main.js
@ -1,5 +1,9 @@
|
||||
|
||||
// ES6模块化引入
|
||||
//import VConsole from 'vconsole'
|
||||
import App from './App'
|
||||
import uviewPlus, { setConfig } from 'uview-plus'
|
||||
//const vConsole = new VConsole();
|
||||
// #ifndef VUE3
|
||||
import Vue from 'vue'
|
||||
import './uni.promisify.adaptor'
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
"transformPx" : false,
|
||||
"app-plus" : {
|
||||
/* 5+App特有相关 */
|
||||
"runmode" : "liberate",
|
||||
"usingComponents" : true,
|
||||
"nvueCompiler" : "uni-app",
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
@ -16,23 +17,27 @@
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
"useragent": {
|
||||
"value": "gdxz",
|
||||
"concatenate": true
|
||||
},
|
||||
"compatible" : {
|
||||
"ignoreVersion" : true
|
||||
},
|
||||
"useragent" : {
|
||||
"value" : "gdxz",
|
||||
"concatenate" : true
|
||||
},
|
||||
"modules" : {
|
||||
"OAuth" : {},
|
||||
"Payment" : {},
|
||||
"Share" : {},
|
||||
"Webview-x5" : {},
|
||||
"UIWebview" : {},
|
||||
"Push" : {},
|
||||
"VideoPlayer" : {}
|
||||
"VideoPlayer" : {},
|
||||
"OAuth" : {},
|
||||
"Barcode" : {},
|
||||
"Camera" : {}
|
||||
},
|
||||
/* 模块配置 */
|
||||
"distribute" : {
|
||||
/* 应用发布信息 */
|
||||
"android" : {
|
||||
"hasTaskAffinity" : true,
|
||||
/* android打包配置 */
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
@ -63,8 +68,13 @@
|
||||
"oauth" : {
|
||||
"weixin" : {
|
||||
"appid" : "wxbf3658f5e674667c",
|
||||
"appsecret" : "c4505a04a9910c65efea8e11ffc93f92",
|
||||
"UniversalLinks" : "https://doc.igandan.com/gdxzExpert/"
|
||||
},
|
||||
"univerify" : {},
|
||||
"sina" : {
|
||||
"appkey" : "2071931330",
|
||||
"redirect_uri" : "http://sns.whalecloud.com/sina2/callback",
|
||||
"UniversalLinks" : ""
|
||||
}
|
||||
},
|
||||
"payment" : {
|
||||
@ -79,6 +89,11 @@
|
||||
"weixin" : {
|
||||
"appid" : "wxbf3658f5e674667c",
|
||||
"UniversalLinks" : "https://doc.igandan.com/gdxzExpert/"
|
||||
},
|
||||
"sina" : {
|
||||
"appkey" : "2071931330",
|
||||
"redirect_uri" : "http://sns.whalecloud.com/sina2/callback",
|
||||
"UniversalLinks" : "https://doc.igandan.com/gdxzExpert/"
|
||||
}
|
||||
},
|
||||
"speech" : {},
|
||||
@ -86,7 +101,7 @@
|
||||
},
|
||||
"splashscreen" : {
|
||||
"androidStyle" : "common",
|
||||
"useOriginalMsgbox" : true,
|
||||
"useOriginalMsgbox" : false,
|
||||
"iosStyle" : "common"
|
||||
},
|
||||
"icons" : {
|
||||
|
||||
@ -18,6 +18,8 @@
|
||||
"mobx": "^6.6.1",
|
||||
"nim-web-sdk-ng": "^10.9.50",
|
||||
"pinyin": "^4.0.0",
|
||||
"uview-plus": "^3.4.73"
|
||||
"uniapp-video-player": "^1.3.0",
|
||||
"uview-plus": "^3.4.73",
|
||||
"vconsole": "^3.15.1"
|
||||
}
|
||||
}
|
||||
|
||||
2383
pages.json
@ -167,9 +167,8 @@ $padding-small: 10px;
|
||||
|
||||
.page {
|
||||
background-color: $gray-bg;
|
||||
min-height: calc(100vh - 180rpx);
|
||||
|
||||
padding-bottom: 120rpx;
|
||||
min-height: calc(100vh - var(--status-bar-height) - 44px);
|
||||
margin-top:calc(var(--status-bar-height) + 44px);
|
||||
}
|
||||
|
||||
// 课程列表
|
||||
|
||||
2539
pages/live/live.vue
31
pages/loading/loading.vue
Normal file
@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<navBar :showLeft="false" :title="'加载中...'"></navBar>
|
||||
<view class="loading-page"></view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted } from 'vue';
|
||||
import { onLoad,onUnload,onHide,onShow } from '@dcloudio/uni-app';
|
||||
import navBar from '@/components/navBar/navBar.vue';
|
||||
onShow(() => {
|
||||
uni.showLoading({
|
||||
title: '加载中...',
|
||||
mask: true
|
||||
});
|
||||
});
|
||||
|
||||
onUnload(() => {
|
||||
uni.hideLoading();
|
||||
});
|
||||
onHide(() => {
|
||||
uni.hideLoading();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.loading-page{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
}
|
||||
</style>
|
||||
196
pages/my/my.vue
@ -6,14 +6,18 @@
|
||||
<!-- 用户信息卡片 -->
|
||||
<view class="user-card"
|
||||
:style="{'background-image': `url(${myInfoBackGround || '/static/big_background_my.png'})`, 'background-size':'cover','background-repeat':'no-repeat'}">
|
||||
<view class="user-info" @click="goToPage('myInfo')">
|
||||
<image class="avatar" :src="avatar" mode="aspectFill"></image>
|
||||
<view class="user-info">
|
||||
<image class="avatar" :src="avatar" mode="aspectFill" @click="goToPage('myInfo')"></image>
|
||||
<view class="user-info-content">
|
||||
<text class="username">{{username}}</text>
|
||||
<scroll-view class="honor_box" scroll-x="true" show-scrollbar="false">
|
||||
<view class="honor_wrap">
|
||||
<view class="honor_item" v-for="item in honor_list" :key="item.id">
|
||||
<image class="honor_image" src="/static/wdsc.png" mode="aspectFill"></image>
|
||||
<view class="honor_item" v-if="ranking > 0">
|
||||
<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>
|
||||
</view>
|
||||
</view>
|
||||
@ -100,9 +104,9 @@
|
||||
<!-- 账户明细 -->
|
||||
<view class="section">
|
||||
<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">
|
||||
<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>
|
||||
<text>我的账户</text>
|
||||
</view>
|
||||
@ -114,11 +118,11 @@
|
||||
<up-image :src="wdflImg" width="48rpx" height="48rpx"></up-image>
|
||||
<text>我的福利</text>
|
||||
</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>
|
||||
<text>我的鲜花</text>
|
||||
</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>
|
||||
<text>课件明细</text>
|
||||
</view>
|
||||
@ -148,8 +152,8 @@
|
||||
<text>通知已{{notice_on?'开':'关'}}</text>
|
||||
</view>
|
||||
<view class="operation-item" @click="showVersion">
|
||||
<up-image :src="versionImg" width="48rpx" height="48rpx"></up-image>
|
||||
<text>V{{version}}</text>
|
||||
<up-image :src="hasNewVersion?versionImgOn:versionImg" width="48rpx" height="48rpx"></up-image>
|
||||
<text>{{hasNewVersion?'有新版本':'V'+version}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -174,7 +178,7 @@
|
||||
|
||||
<!-- 常用银行卡 -->
|
||||
<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">
|
||||
<up-image :src="cyyhk" width="48rpx" height="48rpx"></up-image>
|
||||
</view>
|
||||
@ -193,10 +197,12 @@
|
||||
<view class="settings-icon">
|
||||
<up-image :src="settingImg" width="48rpx" height="48rpx"></up-image>
|
||||
</view>
|
||||
<view class="settings-content">
|
||||
<view class="settings-content flex-row" >
|
||||
<text class="settings-title">设置与帮助</text>
|
||||
<text v-if="hasNewVersion && isIos" class="new-version">有新版本</text>
|
||||
</view>
|
||||
<view class="settings-arrow">
|
||||
|
||||
<uni-icons type="forward" size="16" color="#ccc"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
@ -233,6 +239,29 @@
|
||||
</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>
|
||||
@ -248,6 +277,11 @@
|
||||
import {
|
||||
onShow
|
||||
} 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 hzshImg from "@/static/hzsh.png"
|
||||
import hzfzImg from "@/static/hzfz.png"
|
||||
@ -269,8 +303,9 @@
|
||||
import ghsjhImg from "@/static/ghsjh.png"
|
||||
import tzykImg from "@/static/xxtx.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 fpgl from "@/static/fpgl.png"
|
||||
import cyyhk from "@/static/cyhhk.png"
|
||||
@ -279,6 +314,7 @@
|
||||
import my_api from '@/api/my_api.js'
|
||||
import navTo from "@/utils/navTo"
|
||||
import linkUrl from "@/utils/docUrl"
|
||||
|
||||
// 响应式数据
|
||||
const isLargeFont = ref(false);
|
||||
const hasSign = ref(false)
|
||||
@ -298,8 +334,25 @@
|
||||
const totalPoints = ref(0)
|
||||
const sign_in = ref(0)
|
||||
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
|
||||
@ -376,6 +429,7 @@
|
||||
totalPoints.value = data.total_points || 0
|
||||
sign_in.value = data.sign_in || 0
|
||||
honor_list.value = data.honor_list || []
|
||||
ranking.value = data.ranking || 0
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取我的信息失败', e)
|
||||
@ -629,7 +683,16 @@ const switchPushPermissions = () => {
|
||||
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) => {
|
||||
let url = '';
|
||||
switch (key) {
|
||||
@ -661,13 +724,23 @@ const switchPushPermissions = () => {
|
||||
isBoundWechat.value = res.data
|
||||
}
|
||||
}
|
||||
const isBoundWechat = ref(false)
|
||||
const isBoundWechat = ref(false);
|
||||
const isIos = ref(false);
|
||||
onShow(() => {
|
||||
console.log('我的页面显示');
|
||||
getUserInfoFromStorage() // 先从storage获取用户信息
|
||||
fetchMyInfo() // 然后从API获取最新数据
|
||||
getIsBoundWechat()
|
||||
isNoticeOn()
|
||||
isNoticeOn();
|
||||
checkVersion();
|
||||
getIsAccount();
|
||||
let systemInfo = uni.getSystemInfoSync();
|
||||
console.log(systemInfo)
|
||||
if(systemInfo.osName == 'ios'){
|
||||
isIos.value = true;
|
||||
}else{
|
||||
isIos.value = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -691,11 +764,91 @@ const switchPushPermissions = () => {
|
||||
|
||||
.page {
|
||||
background-color: $gray-bg;
|
||||
height: calc(100vh - 180rpx);
|
||||
margin-top:calc(var(--status-bar-height) + 44px);
|
||||
height: calc(100vh - var(--status-bar-height) - 44px);
|
||||
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;
|
||||
@ -825,6 +978,11 @@ const switchPushPermissions = () => {
|
||||
.honor_text {
|
||||
font-size: 24rpx;
|
||||
color: $white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.bar_rank{
|
||||
padding:0 6rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,12 +10,13 @@
|
||||
<view class="tab-item" :class="{ active: activeTab === 0 }" @click="switchTab(0)">
|
||||
患教文库
|
||||
</view>
|
||||
<view class="bar"></view>
|
||||
<view class="tab-item" :class="{ active: activeTab === 1 }" @click="switchTab(1)">
|
||||
患教视频
|
||||
</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>
|
||||
|
||||
<!-- 筛选栏 -->
|
||||
@ -51,7 +52,7 @@
|
||||
:class="{ active: tag.selected }"
|
||||
@click="toggleTag(index)"
|
||||
>
|
||||
{{ tag.DES }}
|
||||
{{ tag.NAME }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -74,20 +75,20 @@
|
||||
:lower-threshold="100"
|
||||
>
|
||||
<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-title">{{ article.title }}</view>
|
||||
<view class="article-meta">
|
||||
<view class="date-tag" v-if="article.isToday">今日</view>
|
||||
<view class="date" v-else>{{ article.date }}</view>
|
||||
<view class="stats">
|
||||
<view class="stat-item">
|
||||
<view class="stat-item readnum">
|
||||
<uni-icons type="eye" size="12" color="#999"></uni-icons>
|
||||
<text>{{ article.views }}</text>
|
||||
<text>{{ formatNumber(article.views) }}</text>
|
||||
</view>
|
||||
<view class="stat-item">
|
||||
<uni-icons type="hand-up" size="13" color="#999"></uni-icons>
|
||||
<text>{{ article.likes }}</text>
|
||||
<text>{{ formatNumber(article.likes) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -130,6 +131,7 @@
|
||||
import docUrl from '@/utils/docUrl.js';
|
||||
import navTo from '@/utils/navTo.js';
|
||||
import navBar from "@/components/navBar/navBar.vue"
|
||||
import formatNumber from '@/utils/formatNumber.js';
|
||||
const type=ref(1)
|
||||
|
||||
// 分页相关状态
|
||||
@ -147,6 +149,7 @@
|
||||
// 重置分页状态
|
||||
currentPage.value = 1;
|
||||
hasMore.value = true;
|
||||
articleList.value = [];
|
||||
polularScienceArticleListByKeywordsNew(true);
|
||||
};
|
||||
const loadGuideTags = async () => {
|
||||
@ -240,9 +243,18 @@
|
||||
|
||||
// 格式化日期
|
||||
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 day = String(date.getDate()).padStart(2, '0');
|
||||
return `${month}-${day}`;
|
||||
|
||||
// 如果年份是今年,只显示月日,否则显示年月日
|
||||
if (year === currentYear) {
|
||||
return `${month}-${day}`;
|
||||
} else {
|
||||
return `${year}-${month}-${day}`;
|
||||
}
|
||||
};
|
||||
// 筛选标签数据
|
||||
const filterTags = ref([]);
|
||||
@ -270,7 +282,7 @@
|
||||
// 跳转到详情页
|
||||
if (article.path) {
|
||||
uni.navigateTo({
|
||||
url: `/pages_app/webview/webview?url=${encodeURIComponent(docUrl+article.path)}&title=${article.title}`
|
||||
url: `/pages_app/webview/webview?url=${encodeURIComponent(docUrl+article.path)}&title=患教详情`
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -319,7 +331,19 @@
|
||||
};
|
||||
|
||||
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 = () => {
|
||||
@ -336,7 +360,7 @@
|
||||
|
||||
// 执行筛选逻辑
|
||||
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);
|
||||
keywords.value = selectedTags.join(',');
|
||||
} else {
|
||||
@ -346,7 +370,7 @@
|
||||
// 重置分页状态
|
||||
currentPage.value = 1;
|
||||
hasMore.value = true;
|
||||
|
||||
articleList.value = [];
|
||||
showFilter.value = false;
|
||||
polularScienceArticleListByKeywordsNew(true);
|
||||
};
|
||||
@ -369,10 +393,10 @@ $gray-dark: #666;
|
||||
$text-color: #333;
|
||||
|
||||
// 尺寸变量
|
||||
$border-radius: 8px;
|
||||
$border-radius-small: 6px;
|
||||
$padding: 15px;
|
||||
$padding-small: 10px;
|
||||
$border-radius: 16rpx;
|
||||
$border-radius-small: 12rpx;
|
||||
$padding: 30rpx;
|
||||
$padding-small: 20rpx;
|
||||
|
||||
.page {
|
||||
background-color: $gray-bg;
|
||||
@ -385,19 +409,25 @@ $padding-small: 10px;
|
||||
.top{
|
||||
width:100%;
|
||||
position: fixed;
|
||||
top:180rpx;
|
||||
top:calc(var(--status-bar-height) + 44px);
|
||||
}
|
||||
// 选项卡
|
||||
.tabs {
|
||||
background-color: $white;
|
||||
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 {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: $padding 0;
|
||||
font-size: 16px;
|
||||
font-size: 32rpx;
|
||||
color: $gray-dark;
|
||||
position: relative;
|
||||
|
||||
@ -411,8 +441,8 @@ $padding-small: 10px;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 30px;
|
||||
height: 2px;
|
||||
width: 60rpx;
|
||||
height: 4rpx;
|
||||
|
||||
}
|
||||
}
|
||||
@ -425,25 +455,25 @@ $padding-small: 10px;
|
||||
padding: $padding-small $padding;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid $gray-light;
|
||||
border-bottom: 2rpx solid $gray-light;
|
||||
|
||||
.search-box {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
gap: 10rpx;
|
||||
|
||||
.search-text {
|
||||
font-size: 14px;
|
||||
font-size: 28rpx;
|
||||
color: $gray-medium;
|
||||
}
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 1px;
|
||||
height: 16px;
|
||||
background-color: $gray-medium;
|
||||
width: 2rpx;
|
||||
height: 32rpx;
|
||||
background-color: $gray-light;
|
||||
margin: 0 $padding;
|
||||
}
|
||||
|
||||
@ -452,8 +482,8 @@ $padding-small: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 3px;
|
||||
font-size: 14px;
|
||||
gap: 6rpx;
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
@ -466,8 +496,8 @@ $padding-small: 10px;
|
||||
// 文章列表
|
||||
.article-list {
|
||||
position: fixed;
|
||||
height:calc(100vh - 450rpx);
|
||||
top: 342rpx;
|
||||
height:calc(100vh - var(--status-bar-height) - 44px - 188rpx);
|
||||
top: calc(var(--status-bar-height) + 44px + 188rpx);
|
||||
|
||||
padding-bottom: 130rpx;
|
||||
.article-item {
|
||||
@ -476,11 +506,11 @@ $padding-small: 10px;
|
||||
border-radius: $border-radius;
|
||||
padding: $padding;
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
gap: 24rpx;
|
||||
|
||||
.article-image {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
width: 260rpx;
|
||||
height: 160rpx;
|
||||
border-radius: $border-radius-small;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@ -492,7 +522,7 @@ $padding-small: 10px;
|
||||
justify-content: space-between;
|
||||
|
||||
.article-title {
|
||||
font-size: 16px;
|
||||
font-size: 32rpx;
|
||||
color: $text-color;
|
||||
line-height: 1.4;
|
||||
margin-bottom: $padding-small;
|
||||
@ -506,31 +536,36 @@ $padding-small: 10px;
|
||||
|
||||
.article-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.date-tag {
|
||||
background-color: $primary-color;
|
||||
color: $white;
|
||||
font-size: 12px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
font-size: 24rpx;
|
||||
padding: 4rpx 12rpx;
|
||||
border-radius: 6rpx;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 12px;
|
||||
width: 125rpx;
|
||||
font-size: 24rpx;
|
||||
color: $gray-medium;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.stats {
|
||||
display: flex;
|
||||
gap: $padding;
|
||||
|
||||
margin-left: 50rpx;
|
||||
.readnum{
|
||||
width:100rpx;
|
||||
}
|
||||
.stat-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
font-size: 12px;
|
||||
gap: 10rpx;
|
||||
|
||||
font-size: 24rpx;
|
||||
color: $gray-medium;
|
||||
}
|
||||
}
|
||||
@ -591,8 +626,8 @@ $padding-small: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
font-size: 12px;
|
||||
gap: 4rpx;
|
||||
font-size: 24rpx;
|
||||
color: $gray-medium;
|
||||
|
||||
&.active {
|
||||
@ -600,7 +635,7 @@ $padding-small: 10px;
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: 10px;
|
||||
font-size: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -619,7 +654,7 @@ $padding-small: 10px;
|
||||
z-index: 9999;
|
||||
|
||||
.filter-content {
|
||||
margin-top:329rpx;
|
||||
margin-top:calc(var(--status-bar-height) + 44px + 188rpx);;
|
||||
|
||||
background-color: $white;
|
||||
// border-radius: 20rpx 20rpx 0 0;
|
||||
@ -638,9 +673,14 @@ $padding-small: 10px;
|
||||
.tag-item {
|
||||
background-color: #f8f8f8;
|
||||
color: $gray-dark;
|
||||
padding: 8rpx 24rpx;
|
||||
padding: 8rpx 0rpx;
|
||||
width:150rpx;
|
||||
text-align:center;
|
||||
border-radius: 30rpx;
|
||||
font-size: 26rpx;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
border: 2rpx solid #efefef;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
|
||||
@ -218,7 +218,7 @@
|
||||
uni.setStorageSync('userInfo', res.data);
|
||||
}
|
||||
const app = getApp()
|
||||
app.initNim({appkey: "885dea390870814acf3ba8558c717572", account:result.data.YX_accid, token: result.data.YX_token })
|
||||
//app.initNim({appkey: "885dea390870814acf3ba8558c717572", account:result.data.YX_accid, token: result.data.YX_token })
|
||||
// 跳转到首页
|
||||
uni.redirectTo({
|
||||
url: '/pages/index/index'
|
||||
|
||||
582
pages_app/meetHistroy/meetHistroy.vue
Normal file
@ -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>
|
||||
493
pages_app/meetHistroySearch/meetHistroySearch.vue
Normal file
@ -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_yugao&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>
|
||||
@ -1,13 +1,15 @@
|
||||
<template>
|
||||
<view class="my-application-page">
|
||||
<!-- 顶部导航栏 -->
|
||||
<uni-nav-bar
|
||||
<view class="navBox">
|
||||
<view class="status_bar"></view>
|
||||
<uni-nav-bar
|
||||
left-icon="left"
|
||||
title="我的应用"
|
||||
@clickLeft="goBack"
|
||||
fixed
|
||||
|
||||
color="#8B2316"
|
||||
height="180rpx"
|
||||
|
||||
:border="false"
|
||||
backgroundColor="#eeeeee"
|
||||
>
|
||||
@ -17,6 +19,7 @@
|
||||
}}</text>
|
||||
</template>
|
||||
</uni-nav-bar>
|
||||
</view>
|
||||
|
||||
<scroll-view class="content" scroll-y>
|
||||
<!-- 我的应用部分 -->
|
||||
@ -102,6 +105,14 @@
|
||||
|
||||
// 获取用户图标数据
|
||||
const addUserIcon = () => {
|
||||
if(myApps.value.length <3){
|
||||
uni.showToast({
|
||||
title: '至少添加3个应用',
|
||||
icon: 'none',
|
||||
duration: 1500
|
||||
});
|
||||
return false;
|
||||
}
|
||||
api.addUserIcon({
|
||||
idStr:myApps.value.map(item => item.id).join(',')
|
||||
}).then(res => {
|
||||
@ -190,7 +201,7 @@
|
||||
navTo({
|
||||
url:url
|
||||
})
|
||||
}else if(app.name=="肝病新闻"){
|
||||
}else if(app.name=="肝胆新闻"){
|
||||
url='/pages_app/news/news'
|
||||
navTo({
|
||||
url:url
|
||||
|
||||
@ -1,15 +1,6 @@
|
||||
<template>
|
||||
<uni-nav-bar
|
||||
left-icon="left"
|
||||
title="肝胆新闻"
|
||||
@clickLeft="goBack"
|
||||
fixed
|
||||
color="#8B2316"
|
||||
height="180rpx"
|
||||
:border="false"
|
||||
backgroundColor="#eeeeee"
|
||||
></uni-nav-bar>
|
||||
|
||||
<navBar title="肝胆新闻" />
|
||||
<view class="news-page">
|
||||
<!-- Fixed Banner Swiper -->
|
||||
<view class="banner-container">
|
||||
@ -143,7 +134,8 @@
|
||||
import { onShow } from "@dcloudio/uni-app";
|
||||
import api from '@/api/api.js';
|
||||
import docUrl from "@/utils/docUrl.js";
|
||||
import navTo from '../../utils/navTo';
|
||||
import navTo from '../../utils/navTo';
|
||||
import navBar from '@/components/navBar/navBar.vue';
|
||||
|
||||
onMounted(() => {
|
||||
loadNewsBanner();
|
||||
@ -270,7 +262,7 @@ import navTo from '../../utils/navTo';
|
||||
/* Fixed Banner Container */
|
||||
.banner-container {
|
||||
position: fixed;
|
||||
top: 180rpx; /* uni-nav-bar height */
|
||||
top:calc(var(--status-bar-height) + 44px);
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 50;
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
<template>
|
||||
<uni-nav-bar left-icon="left"
|
||||
@clickLeft="goBack" title="患教视频" fixed color="#8B2316" height="180rpx" :border="false" backgroundColor="#eeeeee"></uni-nav-bar>
|
||||
<navBar title="患教视频" />
|
||||
<view class="video-page">
|
||||
<!-- Header -->
|
||||
|
||||
|
||||
|
||||
<!-- Fixed Filter Tabs -->
|
||||
<view class="filter-tabs-container">
|
||||
<view class="filter-tabs">
|
||||
@ -67,7 +66,7 @@
|
||||
<text class="author">{{video.public_name}}</text>
|
||||
<view class="stats">
|
||||
<uni-icons type="eye" size="14" color="#999"></uni-icons>
|
||||
<text class="view-count">{{video.readnum}}</text>
|
||||
<text class="view-count">{{formatNumber(video.readnum)}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -153,6 +152,8 @@
|
||||
import docUrl from '@/utils/docUrl';
|
||||
import navTo from '@/utils/navTo';
|
||||
import empty from '@/components/empty/empty.vue';
|
||||
import formatNumber from '@/utils/formatNumber.js';
|
||||
import navBar from '@/components/navBar/navBar.vue';
|
||||
const isAllActive=ref(false)
|
||||
// 响应式数据
|
||||
const videoList = ref([]);
|
||||
@ -515,9 +516,9 @@
|
||||
.scroll-view {
|
||||
position: fixed;
|
||||
bottom: 0rpx;
|
||||
height: calc(100vh - 180rpx); /* 固定高度,减去导航栏高度 */
|
||||
height: calc(100vh - var(--status-bar-height) - 44px); /* 固定高度,减去导航栏高度 */
|
||||
background-color: #f5f5f5;
|
||||
top: 172rpx; /* 为导航栏留出空间 */
|
||||
top: calc(var(--status-bar-height) + 65px); /* 为导航栏留出空间 */
|
||||
}
|
||||
|
||||
|
||||
@ -569,7 +570,7 @@
|
||||
/* Fixed Filter Tabs Container */
|
||||
.filter-tabs-container {
|
||||
position: fixed;
|
||||
top: 180rpx; /* uni-nav-bar height */
|
||||
top: calc(var(--status-bar-height) + 44px); /* uni-nav-bar height */
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 40;
|
||||
|
||||
@ -1,16 +1,7 @@
|
||||
<template>
|
||||
<view class="person-page">
|
||||
<!-- 顶部导航栏 -->
|
||||
<uni-nav-bar
|
||||
left-icon="left"
|
||||
title="个人资料"
|
||||
@clickLeft="goBack"
|
||||
fixed
|
||||
color="#8B2316"
|
||||
height="180rpx"
|
||||
:border="false"
|
||||
backgroundColor="#eeeeee"
|
||||
></uni-nav-bar>
|
||||
<navBar title="个人资料" />
|
||||
|
||||
<scroll-view class="content" scroll-y>
|
||||
<!-- 基本资料分组 -->
|
||||
@ -267,6 +258,7 @@
|
||||
import areaList from '@/utils/areaList.js';
|
||||
import docUrl from '@/utils/docUrl';
|
||||
import navTo from '@/utils/navTo';
|
||||
import navBar from '@/components/navBar/navBar.vue';
|
||||
import QfImageCropper from '@/components/qf-image-cropper/qf-image-cropper.vue';
|
||||
const form = ref({
|
||||
// 基本资料字段
|
||||
@ -777,7 +769,7 @@ const confirmSpecialties = () => {
|
||||
}
|
||||
.content {
|
||||
position: fixed;
|
||||
top: 180rpx;
|
||||
top: calc(var(--status-bar-height) + 44px);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
||||
@ -90,7 +90,7 @@
|
||||
:class="{ active: tag.selected }"
|
||||
@click="toggleTag(index)"
|
||||
>
|
||||
{{ tag.DES}}
|
||||
{{ tag.NAME}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -391,9 +391,9 @@
|
||||
console.log('选中的筛选标签:', selectedTags);
|
||||
for (var i = 0; i < selectedTags.length; i++) {
|
||||
if(keywords.value){
|
||||
keywords.value+=","+selectedTags[i].DES
|
||||
keywords.value+=","+selectedTags[i].NAME
|
||||
}else{
|
||||
keywords.value=selectedTags[i].DES
|
||||
keywords.value=selectedTags[i].NAME
|
||||
}
|
||||
}
|
||||
isFilterActive.value =true;
|
||||
|
||||
@ -217,7 +217,7 @@ const goBack = () => {
|
||||
|
||||
.download-bar {
|
||||
position: fixed;
|
||||
top: calc(var(--status-bar-height) + 44px);
|
||||
top:220rpx;
|
||||
z-index: 89;
|
||||
width: 100%;
|
||||
background-color: #6f6f6f; // 接近截图灰条
|
||||
|
||||
@ -255,7 +255,7 @@
|
||||
icon: 'none'
|
||||
});
|
||||
const app = getApp()
|
||||
app.initNim({appkey: "885dea390870814acf3ba8558c717572", account:result.YX_accid, token: result.YX_token })
|
||||
//app.initNim({appkey: "885dea390870814acf3ba8558c717572", account:result.YX_accid, token: result.YX_token })
|
||||
console.log(3)
|
||||
uni.redirectTo({
|
||||
url:'/pages/index/index'
|
||||
@ -330,7 +330,7 @@
|
||||
uni.setStorageSync('userInfo', res.data);
|
||||
}
|
||||
const app = getApp()
|
||||
app.initNim({ account:result.data.YX_accid, token: result.data.YX_token })
|
||||
//app.initNim({ account:result.data.YX_accid, token: result.data.YX_token })
|
||||
// 跳转到首页
|
||||
uni.redirectTo({
|
||||
url: '/pages/index/index'
|
||||
|
||||
635
pages_app/replayList/replayList.vue
Normal file
@ -0,0 +1,635 @@
|
||||
<template>
|
||||
<view class="navbox">
|
||||
<view class="status_bar"></view>
|
||||
<uni-nav-bar left-icon="left"
|
||||
@clickLeft="goBack" :title="name" color="#8B2316" :border="false" backgroundColor="#eeeeee">
|
||||
<template #right>
|
||||
|
||||
<view class="nav-right" @click="goSelect">
|
||||
精选
|
||||
</view>
|
||||
</template>
|
||||
</uni-nav-bar>
|
||||
</view>
|
||||
<view class="video-page">
|
||||
<!-- Header -->
|
||||
|
||||
<!-- Main Content -->
|
||||
<scroll-view
|
||||
class="scroll-view"
|
||||
scroll-y="true"
|
||||
refresher-enabled="true"
|
||||
:refresher-triggered="refreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
@scrolltolower="onLoadMore"
|
||||
lower-threshold="100"
|
||||
>
|
||||
|
||||
<!-- Video List -->
|
||||
<view class="video-list">
|
||||
<view
|
||||
class="video-item"
|
||||
v-for="(video, index) in videoList"
|
||||
:key="video.id || video.uuid"
|
||||
@click="playVideo(video)"
|
||||
>
|
||||
<view class="video-thumbnail">
|
||||
<image :src="docUrl + video.imgpath" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="video-info">
|
||||
<view class="video-title">{{video.title || video.name}}</view>
|
||||
<view class="video-meta">
|
||||
<text class="author">{{video.public_name}}</text>
|
||||
<view class="stats">
|
||||
<uni-icons type="eye" size="14" color="#999"></uni-icons>
|
||||
<text class="view-count">{{video.readnum}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Loading More -->
|
||||
<uni-load-more
|
||||
v-if="videoList.length > 0"
|
||||
:status="loadMoreStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
contentrefresh: '正在加载...',
|
||||
contentnomore: '没有更多数据了'
|
||||
}"
|
||||
></uni-load-more>
|
||||
|
||||
<!-- Empty State -->
|
||||
<view class="empty-state" v-if="videoList.length === 0 && !loading">
|
||||
<empty></empty>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, computed,reactive } from 'vue';
|
||||
import { onShow,onLoad } from "@dcloudio/uni-app";
|
||||
import api from '@/api/api.js';
|
||||
import allImg from "@/static/video_all.png"
|
||||
import allOnImg from "@/static/video_select.png"
|
||||
import selectImg from "@/static/all_video.png"
|
||||
import selectOnImg from "@/static/select_video.png"
|
||||
import filter from "@/static/cb_screen_no.png"
|
||||
import filterOn from "@/static/cb_screen_yes.png"
|
||||
import upImg from "@/static/cb_up.png"
|
||||
import downImg from "@/static/cb_down.png"
|
||||
import docUrl from '@/utils/docUrl';
|
||||
import navTo from '@/utils/navTo';
|
||||
import empty from '@/components/empty/empty.vue';
|
||||
const isAllActive=ref(false)
|
||||
// 响应式数据
|
||||
const videoList = ref([]);
|
||||
const activeTab = ref(1); // 默认选中"最新"
|
||||
const loading = ref(false);
|
||||
const refreshing = ref(false);
|
||||
const loadMoreStatus = ref('more'); // more, loading, noMore
|
||||
const currentPage = ref(1);
|
||||
const pageSize = ref(10);
|
||||
const hasMoreData = ref(true);
|
||||
const filteredContent=ref([])
|
||||
const sort =ref(2);
|
||||
const keywords=ref('');
|
||||
const typeUuid=ref('');
|
||||
const typeName=ref('乙肝')
|
||||
const isFilterActive=ref(false)
|
||||
const showFilter = ref(false);
|
||||
const yearList=ref([]);
|
||||
const selectYearContent=reactive({});
|
||||
const name=ref('');
|
||||
// 筛选弹窗相关数据
|
||||
const filterTags = ref([]);
|
||||
onLoad((options)=>{
|
||||
if(options.name){
|
||||
name.value=decodeURIComponent(options.name);
|
||||
}
|
||||
getVideoType();
|
||||
})
|
||||
|
||||
|
||||
const goSelect=()=>{
|
||||
navTo({
|
||||
url: `/pages_app/replayText/replayText?name=${name.value}`
|
||||
});
|
||||
};
|
||||
const getVideoType=async () => {
|
||||
const response = await api.getTypeUuidByName({
|
||||
name: name.value,
|
||||
});
|
||||
if(response.code === 200 && response.data){
|
||||
typeUuid.value = response.data;
|
||||
loadVideoData();
|
||||
}
|
||||
}
|
||||
// 加载轮播数据
|
||||
|
||||
|
||||
// 加载视频数据
|
||||
const loadVideoData = async (isRefresh = false) => {
|
||||
if (loading.value && !isRefresh) return;
|
||||
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
const response = await api.videoByTypeNew({
|
||||
page: currentPage.value,
|
||||
pageSize: pageSize.value,
|
||||
typeUuid:typeUuid.value,
|
||||
});
|
||||
|
||||
console.log('视频列表API原始响应:', response);
|
||||
|
||||
// 检查响应结构
|
||||
let videoData = {};
|
||||
if (response && response.data) {
|
||||
if (response.data.code === 200) {
|
||||
videoData = response.data.data || {};
|
||||
} else if (response.code === 200) {
|
||||
videoData = response.data || {};
|
||||
}
|
||||
} else if (response && response.code === 200) {
|
||||
videoData = response.data || {};
|
||||
}
|
||||
|
||||
console.log('解析后的视频数据:', videoData);
|
||||
|
||||
if (videoData && videoData.list) {
|
||||
const { list, totalPage,pageNumber } = videoData;
|
||||
console.log('视频列表数据:', list);
|
||||
|
||||
if (isRefresh) {
|
||||
videoList.value = list || [];
|
||||
currentPage.value = 1;
|
||||
} else {
|
||||
videoList.value = [...videoList.value, ...(list || [])];
|
||||
}
|
||||
|
||||
hasMoreData.value = totalPage>pageNumber;
|
||||
loadMoreStatus.value = hasMoreData.value ? 'more' : 'noMore';
|
||||
} else {
|
||||
throw new Error(response?.message || '获取数据失败');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('加载视频失败:', error);
|
||||
|
||||
} finally {
|
||||
loading.value = false;
|
||||
refreshing.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 下拉刷新
|
||||
const onRefresh = () => {
|
||||
refreshing.value = true;
|
||||
currentPage.value = 1;
|
||||
hasMoreData.value = true;
|
||||
loadVideoData(true);
|
||||
};
|
||||
|
||||
// 上拉加载更多
|
||||
const onLoadMore = () => {
|
||||
if (!hasMoreData.value || loading.value) return;
|
||||
|
||||
loadMoreStatus.value = 'loading';
|
||||
currentPage.value++;
|
||||
loadVideoData();
|
||||
};
|
||||
|
||||
|
||||
|
||||
// 播放视频
|
||||
const playVideo = (video) => {
|
||||
console.log(video);
|
||||
const videoId = video.id || video.uuid;
|
||||
navTo({
|
||||
url: `/pages_app/videoDetail/videoDetail?id=${videoId}`
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 返回
|
||||
const goBack = () => {
|
||||
uni.navigateBack({
|
||||
fail() {
|
||||
uni.redirectTo({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$primary-color: #ff6b6b;
|
||||
$theme-color: #8B2316;
|
||||
$white: #fff;
|
||||
$gray-bg: #f5f5f5;
|
||||
$gray-light: #eee;
|
||||
$gray-medium: #999;
|
||||
$gray-dark: #666;
|
||||
$text-color: #333;
|
||||
|
||||
// 尺寸变量
|
||||
$border-radius: 8px;
|
||||
$border-radius-small: 6px;
|
||||
$padding: 15px;
|
||||
$padding-small: 10px;
|
||||
.nav-right {
|
||||
// margin-top:50rpx;
|
||||
font-size: 32rpx;
|
||||
color: #8b2316;
|
||||
font-weight: 500;
|
||||
}
|
||||
.video-page {
|
||||
background-color: #f5f5f5;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Header Styles */
|
||||
.header {
|
||||
background-color: #fff;
|
||||
height: 88rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 30rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
|
||||
position: relative;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.header-left, .header-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #8B4513;
|
||||
}
|
||||
|
||||
/* Scroll View */
|
||||
.scroll-view {
|
||||
position: fixed;
|
||||
bottom: 0rpx;
|
||||
height:calc(100vh - var(--status-bar-height) - 44px);
|
||||
background-color: #f5f5f5;
|
||||
top: calc(var(--status-bar-height) + 44px); /* 为导航栏留出空间 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Filter Tabs */
|
||||
.filter-tabs {
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx 30rpx;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 60rpx;
|
||||
padding: 10rpx 0;
|
||||
}
|
||||
|
||||
.tab-item:last-child{
|
||||
margin-right: 0;
|
||||
}
|
||||
.right{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-text {
|
||||
color: #E74C3C;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tab-text {
|
||||
margin: 0 8rpx;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
.tab-item:first-child .tab-text{
|
||||
max-width:295rpx;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.tab-item .tab-text.active {
|
||||
color: #8B2316;
|
||||
|
||||
}
|
||||
|
||||
/* Fixed Filter Tabs Container */
|
||||
.filter-tabs-container {
|
||||
position: fixed;
|
||||
top: 180rpx; /* uni-nav-bar height */
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 40;
|
||||
background-color: #fff;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.doctor-avatar {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.doctor-avatar image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Video List */
|
||||
.video-list {
|
||||
padding: 0 20rpx;
|
||||
margin-top: 20rpx; /* 为固定的Filter Tabs留出空间 */
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr); /* 每行两个 */
|
||||
gap: 16rpx; /* 卡片间距 */
|
||||
}
|
||||
|
||||
.video-item {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 0;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.1);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.video-thumbnail {
|
||||
position: relative;
|
||||
height: 200rpx;
|
||||
}
|
||||
|
||||
.video-thumbnail image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.video-duration {
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.video-duration text {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.video-info {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.video-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
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;
|
||||
height: 2.8em; /* 固定2行高度:1.4 * 2 = 2.8em */
|
||||
}
|
||||
|
||||
.video-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.author {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.stats {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.view-count {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
/* Empty State */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
}
|
||||
|
||||
.empty-state image {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
margin-bottom: 30rpx;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.empty-state text {
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.newbox{
|
||||
margin-top: -12rpx;
|
||||
}
|
||||
|
||||
/* 全部视频弹窗样式 */
|
||||
.all-video-popup {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
height:calc(100vh - 272rpx);
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.popup-header {
|
||||
padding: 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.popup-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.popup-body {
|
||||
height:100%;
|
||||
|
||||
}
|
||||
|
||||
.category-item {
|
||||
padding: 30rpx;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
background-color: #fff;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.category-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.category-item.active {
|
||||
background-color: #f8f8f8;
|
||||
color: #8B2316;
|
||||
}
|
||||
|
||||
.category-item:active {
|
||||
background-color: #e8f4fd;
|
||||
}
|
||||
|
||||
.empty-content {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 200rpx;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
// 筛选弹窗样式
|
||||
.filter-popup {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
// background-color: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
z-index: 9999;
|
||||
|
||||
.filter-content {
|
||||
margin-top:272rpx;
|
||||
overflow-y:scroll;
|
||||
background-color: $white;
|
||||
// border-radius: 20rpx 20rpx 0 0;
|
||||
padding: 20rpx 30rpx 60rpx;
|
||||
width: 100%;
|
||||
height: calc(100vh - 272rpx);
|
||||
|
||||
.filter-tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20rpx;
|
||||
margin-bottom: 60rpx;
|
||||
max-height: 65vh;
|
||||
overflow-y: auto;
|
||||
|
||||
.tag-item {
|
||||
background-color: #f8f8f8;
|
||||
color: $gray-dark;
|
||||
padding: 8rpx 0; /* 去掉左右padding,仅保留上下 */
|
||||
border-radius: 30rpx;
|
||||
font-size: 26rpx;
|
||||
border: 2rpx solid #efefef;
|
||||
transition: all 0.3s ease;
|
||||
width: 152rpx; /* 固定宽度 */
|
||||
text-align: center; /* 文本居中 */
|
||||
white-space: nowrap; /* 单行显示 */
|
||||
overflow: hidden; /* 隐藏溢出 */
|
||||
text-overflow: ellipsis; /* 超出显示省略号 */
|
||||
|
||||
&.active {
|
||||
background-color: #fff;
|
||||
color: $theme-color;
|
||||
border-color: $theme-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filter-buttons {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
position: fixed;
|
||||
bottom: 30rpx;
|
||||
left: 30rpx;
|
||||
right: 30rpx;
|
||||
background-color: #fff; /* 背景色为白色 */
|
||||
|
||||
.btn-reset,
|
||||
.btn-confirm {
|
||||
flex: 1;
|
||||
height: 70rpx;
|
||||
border-radius: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.btn-reset {
|
||||
background-color: $white;
|
||||
color: $theme-color;
|
||||
border: 2rpx solid $theme-color;
|
||||
}
|
||||
|
||||
.btn-confirm {
|
||||
border: 2rpx solid $theme-color;
|
||||
background-color: $theme-color;
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
272
pages_app/replayText/replayText.vue
Normal file
@ -0,0 +1,272 @@
|
||||
<template>
|
||||
<view class="meeting-page">
|
||||
<!-- 导航栏 -->
|
||||
<navBar :title="name" />
|
||||
|
||||
<!-- 主内容区域 -->
|
||||
<scroll-view
|
||||
class="content-scroll"
|
||||
scroll-y="true"
|
||||
refresher-enabled="true"
|
||||
:refresher-triggered="refreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
@scrolltolower="onLoadMore"
|
||||
lower-threshold="100"
|
||||
>
|
||||
<view class="meeting-list">
|
||||
<view
|
||||
class="meeting-item"
|
||||
v-for="(meeting, index) in meetingList"
|
||||
:key="meeting.id"
|
||||
@click="playVideo(meeting)"
|
||||
>
|
||||
<view class="meeting-content">
|
||||
{{ meeting.name }}
|
||||
</view>
|
||||
<view class="meeting-arrow">
|
||||
<uni-icons type="right" size="16" color="#999"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多状态 -->
|
||||
<uni-load-more
|
||||
v-if="meetingList.length > 0"
|
||||
:status="loadMoreStatus"
|
||||
:content-text="{
|
||||
contentdown: '上拉加载更多',
|
||||
contentrefresh: '正在加载...',
|
||||
contentnomore: '没有更多数据了'
|
||||
}"
|
||||
></uni-load-more>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-state" v-if="meetingList.length === 0 && !loading">
|
||||
<view class="empty-content">
|
||||
<text class="empty-text">暂无数据</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { onShow,onLoad } from "@dcloudio/uni-app";
|
||||
import navBar from '@/components/navBar/navBar.vue';
|
||||
import api from '@/api/api.js';
|
||||
import navTo from '@/utils/navTo';
|
||||
// 会议列表数据
|
||||
const typeUuid=ref('');
|
||||
const typeName=ref('');
|
||||
const currentPage=ref(1);
|
||||
const pageSize=ref(10);
|
||||
const hasMoreData=ref(true);
|
||||
const loadMoreStatus=ref('more');
|
||||
const loading=ref(false);
|
||||
const refreshing=ref(false);
|
||||
const meetingList=ref([]);
|
||||
|
||||
// 页面加载
|
||||
onMounted(() => {
|
||||
// 初始化数据
|
||||
});
|
||||
const name=ref('');
|
||||
onLoad((options)=>{
|
||||
if(options.name){
|
||||
name.value=decodeURIComponent(options.name);
|
||||
}
|
||||
getVideoType();
|
||||
});
|
||||
|
||||
const getVideoType=async () => {
|
||||
const response = await api.getTypeUuidByName({
|
||||
name: name.value,
|
||||
});
|
||||
if(response.code === 200 && response.data){
|
||||
typeUuid.value = response.data;
|
||||
loadVideoData();
|
||||
}
|
||||
}
|
||||
// 返回上一页
|
||||
const goBack = () => {
|
||||
uni.navigateBack({
|
||||
fail() {
|
||||
uni.redirectTo({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
const loadVideoData = async (isRefresh = false) => {
|
||||
if (loading.value && !isRefresh) return;
|
||||
|
||||
loading.value = true;
|
||||
|
||||
try {
|
||||
const response = await api.videoByTypeNew({
|
||||
page: currentPage.value,
|
||||
pageSize: pageSize.value,
|
||||
typeUuid:typeUuid.value,
|
||||
});
|
||||
console.log('视频列表API原始响应:', response);
|
||||
// 检查响应结构
|
||||
let videoData = {};
|
||||
if (response && response.data) {
|
||||
if (response.data.code === 200) {
|
||||
videoData = response.data.data || {};
|
||||
} else if (response.code === 200) {
|
||||
videoData = response.data || {};
|
||||
}
|
||||
} else if (response && response.code === 200) {
|
||||
videoData = response.data || {};
|
||||
}
|
||||
|
||||
console.log('解析后的视频数据:', videoData);
|
||||
|
||||
if (videoData && videoData.list) {
|
||||
const { list, totalPage,pageNumber } = videoData;
|
||||
console.log('视频列表数据:', list);
|
||||
|
||||
if (isRefresh) {
|
||||
meetingList.value = list || [];
|
||||
currentPage.value = 1;
|
||||
} else {
|
||||
meetingList.value = [...meetingList.value, ...(list || [])];
|
||||
}
|
||||
|
||||
hasMoreData.value = totalPage>pageNumber;
|
||||
loadMoreStatus.value = hasMoreData.value ? 'more' : 'noMore';
|
||||
} else {
|
||||
throw new Error(response?.message || '获取数据失败');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('加载视频失败:', error);
|
||||
|
||||
} finally {
|
||||
loading.value = false;
|
||||
refreshing.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 下拉刷新
|
||||
const onRefresh = () => {
|
||||
refreshing.value = true;
|
||||
currentPage.value = 1;
|
||||
hasMoreData.value = true;
|
||||
loadVideoData(true);
|
||||
};
|
||||
|
||||
// 上拉加载更多
|
||||
const onLoadMore = () => {
|
||||
if (!hasMoreData.value || loading.value) return;
|
||||
|
||||
loadMoreStatus.value = 'loading';
|
||||
currentPage.value++;
|
||||
loadVideoData();
|
||||
};
|
||||
|
||||
// 跳转到会议详情
|
||||
// 播放视频
|
||||
const playVideo = (video) => {
|
||||
const videoId = video.id || video.uuid;
|
||||
|
||||
navTo({
|
||||
url: `/pages_app/videoDetail/videoDetail?id=${videoId}`
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
$theme-color: #8B2316;
|
||||
$text-color: #333;
|
||||
$text-gray: #999;
|
||||
$bg-color: #f5f5f5;
|
||||
$white: #fff;
|
||||
|
||||
.meeting-page {
|
||||
background-color: $bg-color;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 内容滚动区域 */
|
||||
.content-scroll {
|
||||
flex: 1;
|
||||
height: calc(100vh - var(--status-bar-height) - 44px);
|
||||
background-color: $white;
|
||||
margin-top: calc(var(--status-bar-height) + 44px);
|
||||
}
|
||||
|
||||
/* 会议列表 */
|
||||
.meeting-list {
|
||||
background-color: $white;
|
||||
}
|
||||
|
||||
/* 会议项 */
|
||||
.meeting-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 30rpx 30rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
background-color: $white;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.meeting-item:active {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
/* 会议内容 */
|
||||
.meeting-content {
|
||||
flex: 1;
|
||||
margin-right: 20rpx;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 30rpx;
|
||||
color: $text-color;
|
||||
}
|
||||
|
||||
.meeting-title {
|
||||
font-size: 30rpx;
|
||||
color: $text-color;
|
||||
line-height: 1.4;
|
||||
|
||||
}
|
||||
|
||||
/* 箭头图标 */
|
||||
.meeting-arrow {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
/* 空状态样式 */
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 100rpx 0;
|
||||
}
|
||||
|
||||
.empty-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
</style>
|
||||
350
pages_app/scanLogin/scanLogin.vue
Normal file
@ -0,0 +1,350 @@
|
||||
<template>
|
||||
<view class="scan-login-container">
|
||||
<navBar title="扫码登录" />
|
||||
|
||||
<!-- 主要内容区域 -->
|
||||
<view class="main-content">
|
||||
<!-- 连接图标区域 -->
|
||||
<view class="connection-area">
|
||||
<up-image :src="loginImg" width="420rpx" height="187rpx"></up-image>
|
||||
</view>
|
||||
|
||||
<!-- 提示文字 -->
|
||||
<view class="tips-text">
|
||||
<text class="main-tip">确认电脑登录</text>
|
||||
<text class="sub-tip">为确保账号安全,请确认是您本人操作</text>
|
||||
</view>
|
||||
|
||||
<!-- 按钮区域 -->
|
||||
<view class="button-area">
|
||||
<button class="confirm-btn" @click="toggleLogin(true)">确认登录</button>
|
||||
<button class="cancel-btn" @click="toggleLogin(false)">取消登录</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { onShow, onLoad } from "@dcloudio/uni-app";
|
||||
import navBar from '@/components/navBar/navBar.vue';
|
||||
import api from '@/api/api.js';
|
||||
import loginImg from '@/static/pcquer.png';
|
||||
import navTo from '@/utils/navTo';
|
||||
import { encryptAesEcb } from '@/utils/aesEcb.js';
|
||||
import OTHER_HOST from '@/utils/otherHost.js';
|
||||
|
||||
// 响应式数据
|
||||
const loading = ref(false);
|
||||
const code = ref('');
|
||||
// 页面加载
|
||||
onLoad((options) => {
|
||||
console.log('扫码登录页面加载完成', options);
|
||||
if (options.code) {
|
||||
code.value = options.code;
|
||||
}
|
||||
});
|
||||
const toggleLogin = (status) => {
|
||||
let userInfo=uni.getStorageSync('userInfo');
|
||||
let str='';
|
||||
if(status){
|
||||
str='watchliveTo}'+code.value+'}'+userInfo.uuid+','+userInfo.realName+','+userInfo.photo;
|
||||
}else{
|
||||
str='watchliveCancel}'+code.value+'}'+userInfo.uuid+','+userInfo.realName+','+userInfo.photo;
|
||||
}
|
||||
let message=encryptAesEcb(str,'deoep09_klodLdAo');
|
||||
uni.request({
|
||||
url: OTHER_HOST+'/watchlive/sendWebsocketMsg',
|
||||
method: 'POST',
|
||||
data: {
|
||||
message: message,
|
||||
},
|
||||
header: {
|
||||
'Content-Type':'application/x-www-form-urlencoded'//自定义请求头信息
|
||||
},
|
||||
success: (res) => {
|
||||
console.log(res);
|
||||
if(res.data.code==1){
|
||||
uni.navigateBack();
|
||||
if(status){
|
||||
uni.showToast({
|
||||
title: '操作成功',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}else{
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
// 确认登录
|
||||
const confirmLogin = async () => {
|
||||
if (loading.value) return;
|
||||
|
||||
try {
|
||||
loading.value = true;
|
||||
|
||||
// 调用确认登录API
|
||||
const result = await api.confirmScanLogin({
|
||||
qrCode: loginData.qrCode,
|
||||
sessionId: loginData.sessionId
|
||||
});
|
||||
|
||||
if (result.code === 200) {
|
||||
uni.showToast({
|
||||
title: '登录成功',
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
// 登录成功后跳转
|
||||
setTimeout(() => {
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
}, 1500);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: result.message || '登录失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('确认登录失败:', error);
|
||||
uni.showToast({
|
||||
title: '网络错误,请重试',
|
||||
icon: 'none'
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 取消登录
|
||||
const cancelLogin = () => {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定要取消登录吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.navigateBack({
|
||||
fail() {
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.scan-login-container {
|
||||
min-height: 100vh;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
padding: 80rpx 60rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 连接图标区域 */
|
||||
.connection-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 80rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 手机图标 */
|
||||
.phone-icon {
|
||||
width: 120rpx;
|
||||
height: 200rpx;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 20rpx;
|
||||
position: relative;
|
||||
border: 2rpx solid #e0e0e0;
|
||||
}
|
||||
|
||||
.phone-screen {
|
||||
width: 100rpx;
|
||||
height: 140rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 10rpx;
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
left: 10rpx;
|
||||
}
|
||||
|
||||
.phone-home-button {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
background-color: #d0d0d0;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
bottom: 20rpx;
|
||||
left: 50rpx;
|
||||
}
|
||||
|
||||
/* 连接信号 */
|
||||
.connection-signals {
|
||||
margin: 0 40rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.signal-line {
|
||||
width: 4rpx;
|
||||
background-color: #d0d0d0;
|
||||
margin: 4rpx 0;
|
||||
border-radius: 2rpx;
|
||||
}
|
||||
|
||||
.signal-1 {
|
||||
height: 20rpx;
|
||||
}
|
||||
|
||||
.signal-2 {
|
||||
height: 30rpx;
|
||||
}
|
||||
|
||||
.signal-3 {
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
/* PC图标 */
|
||||
.pc-icon {
|
||||
width: 140rpx;
|
||||
height: 100rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pc-screen {
|
||||
width: 140rpx;
|
||||
height: 80rpx;
|
||||
background-color: #f5f5f5;
|
||||
border: 2rpx solid #e0e0e0;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pc-text {
|
||||
font-size: 24rpx;
|
||||
color: #666666;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.pc-stand {
|
||||
width: 60rpx;
|
||||
height: 20rpx;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 0 0 8rpx 8rpx;
|
||||
position: absolute;
|
||||
bottom: -20rpx;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
/* 提示文字 */
|
||||
.tips-text {
|
||||
text-align: center;
|
||||
margin-bottom: 100rpx;
|
||||
}
|
||||
|
||||
.main-tip {
|
||||
display: block;
|
||||
font-size: 32rpx;
|
||||
color: #333333;
|
||||
font-weight: 500;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.sub-tip {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* 按钮区域 */
|
||||
.button-area {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 30rpx;
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
background-color: #8B2316;
|
||||
color: #ffffff;
|
||||
border: none;
|
||||
border-radius: 12rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.confirm-btn:active {
|
||||
background-color: #6B1A0F;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.cancel-btn {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
background-color: #ffffff;
|
||||
color: #666666;
|
||||
border: 2rpx solid #e0e0e0;
|
||||
border-radius: 12rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.cancel-btn:active {
|
||||
background-color: #f5f5f5;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
/* 加载状态 */
|
||||
.confirm-btn[disabled] {
|
||||
background-color: #cccccc;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
/* 响应式适配 */
|
||||
@media screen and (max-width: 750rpx) {
|
||||
.main-content {
|
||||
padding: 60rpx 40rpx;
|
||||
}
|
||||
|
||||
.connection-area {
|
||||
margin-bottom: 60rpx;
|
||||
}
|
||||
|
||||
.tips-text {
|
||||
margin-bottom: 80rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -222,7 +222,7 @@
|
||||
background-color: #eeeeee;
|
||||
|
||||
display: flex;
|
||||
height:140rpx;
|
||||
height:180rpx;
|
||||
align-items: center;
|
||||
padding:0 30rpx;
|
||||
gap: 20rpx;
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<uni-nav-bar left-icon="left"
|
||||
@clickLeft="goBack" title="肝胆视频" fixed color="#8B2316" height="180rpx" :border="false" backgroundColor="#eeeeee"></uni-nav-bar>
|
||||
<navBar title="肝胆视频" />
|
||||
<view class="video-page">
|
||||
<!-- Header -->
|
||||
|
||||
@ -64,6 +63,7 @@
|
||||
<up-image :src="sort==2?upImg:downImg" width="20rpx" height="26rpx" ></up-image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="bar"></view>
|
||||
<view
|
||||
class="tab-item"
|
||||
@click="showFilterPopup"
|
||||
@ -105,7 +105,7 @@
|
||||
<text class="author">{{video.public_name}}</text>
|
||||
<view class="stats">
|
||||
<uni-icons type="eye" size="14" color="#999"></uni-icons>
|
||||
<text class="view-count">{{video.readnum}}</text>
|
||||
<text class="view-count">{{formatNumber(video.readnum)}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -147,7 +147,7 @@
|
||||
:class="{ active: tag.selected }"
|
||||
@click="toggleTag(index)"
|
||||
>
|
||||
{{ tag.DES }}
|
||||
{{ tag.NAME }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -219,6 +219,8 @@
|
||||
import videoImg from "@/static/patient_video.png"
|
||||
import docUrl from '@/utils/docUrl';
|
||||
import navTo from '@/utils/navTo';
|
||||
import formatNumber from '@/utils/formatNumber.js';
|
||||
import navBar from '@/components/navBar/navBar.vue';
|
||||
const isAllActive=ref(false)
|
||||
// 响应式数据
|
||||
const videoList = ref([]);
|
||||
@ -302,7 +304,7 @@
|
||||
} catch (error) {
|
||||
console.error('加载轮播数据失败:', error);
|
||||
// 使用模拟数据作为备用
|
||||
bannerList.value = getMockBannerData();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@ -333,7 +335,8 @@
|
||||
console.log('类型API原始响应:', response);
|
||||
if(response.code==200){
|
||||
yearList.value=response.data;
|
||||
filteredContent.value=(response.data[0]).list;
|
||||
let all=[{uuid:'',name:'全部视频'}];
|
||||
filteredContent.value=all.concat((response.data[0]).list);
|
||||
console.log(33)
|
||||
let arr=response.data.map(item=>{
|
||||
return {
|
||||
@ -612,33 +615,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
// Banner相关方法
|
||||
const getMockBannerData = () => {
|
||||
return [
|
||||
{
|
||||
id: 'banner_1',
|
||||
title: '《2025年版慢加急性肝衰竭指南》解读',
|
||||
subtitle: '专业医学视频教育平台',
|
||||
thumbnail: '/static/big_background_my.png',
|
||||
doctorAvatar: '/static/doctor-avatar-1.png'
|
||||
},
|
||||
{
|
||||
id: 'banner_2',
|
||||
title: '自身免疫性肝病专栏|免疫治疗的双刃剑',
|
||||
subtitle: '专业医学视频教育平台',
|
||||
thumbnail: '/static/big_background_my.png',
|
||||
doctorAvatar: '/static/doctor-avatar-2.png'
|
||||
},
|
||||
{
|
||||
id: 'banner_3',
|
||||
title: '徐医感染:硬化出血发热路,关关难过关关过',
|
||||
subtitle: '专业医学视频教育平台',
|
||||
thumbnail: '/static/big_background_my.png',
|
||||
doctorAvatar: '/static/doctor-avatar-3.png'
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
const onSwiperChange = (e) => {
|
||||
currentBannerIndex.value = e.detail.current;
|
||||
};
|
||||
@ -663,19 +640,18 @@
|
||||
selectedCategory.value = categoryValue;
|
||||
console.log(yearList.value)
|
||||
console.log('选择分类:', categoryValue);
|
||||
let all=[{uuid:'',name:'全部视频'}];
|
||||
for (var i = 0; i < yearList.value.length; i++) {
|
||||
|
||||
if(categoryValue==yearList.value[i].name){
|
||||
console.log(yearList.value[i]);
|
||||
filteredContent.value=yearList.value[i].list;
|
||||
filteredContent.value=categoryValue=='全部'?all.concat(yearList.value[i].list):yearList.value[i].list;
|
||||
console.log(filteredContent.value)
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
const selectContent = (content) => {
|
||||
// 这里可以根据选中的内容进行相应的操作
|
||||
console.log('选中内容:', content);
|
||||
@ -684,10 +660,10 @@
|
||||
typeUuid.value=content.uuid;
|
||||
typeName.value=content.name;
|
||||
isAllActive.value=true;
|
||||
|
||||
currentPage.value = 1;
|
||||
hasMoreData.value = true;
|
||||
loadVideoData(true);
|
||||
};
|
||||
|
||||
|
||||
// 筛选弹窗相关方法
|
||||
const showFilterPopup = () => {
|
||||
showFilter.value = true;
|
||||
@ -720,9 +696,9 @@
|
||||
console.log('选中的筛选标签:', selectedTags);
|
||||
for (var i = 0; i < selectedTags.length; i++) {
|
||||
if(keywords.value){
|
||||
keywords.value+=","+selectedTags[i].DES
|
||||
keywords.value+=","+selectedTags[i].NAME
|
||||
}else{
|
||||
keywords.value=selectedTags[i].DES
|
||||
keywords.value=selectedTags[i].NAME
|
||||
}
|
||||
|
||||
|
||||
@ -849,10 +825,10 @@
|
||||
.scroll-view {
|
||||
position: fixed;
|
||||
bottom:0rpx;
|
||||
height: calc(100vh - 658rpx); /* 固定高度,减去固定的banner和Filter Tabs空间 */
|
||||
height: calc(100vh - var(--status-bar-height) - 54px - 400rpx); /* 固定高度,减去固定的banner和Filter Tabs空间 */
|
||||
background-color: #f5f5f5;
|
||||
margin-bottom: 200rpx;
|
||||
top: 614rpx; /* 为固定的banner和Filter Tabs留出空间 */
|
||||
top: calc(var(--status-bar-height) + 54px + 400rpx); /* 为固定的banner和Filter Tabs留出空间 */
|
||||
}
|
||||
|
||||
/* Banner Styles */
|
||||
@ -861,7 +837,12 @@
|
||||
height: 400rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.bar{
|
||||
width:2rpx;
|
||||
margin:0 26rpx 0 30rpx;
|
||||
height: 32rpx;
|
||||
background-color: #666;
|
||||
}
|
||||
.banner-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@ -894,7 +875,7 @@
|
||||
.tab-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 60rpx;
|
||||
|
||||
padding: 10rpx 0;
|
||||
}
|
||||
|
||||
@ -903,6 +884,8 @@
|
||||
}
|
||||
.right{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.tab-item.active .tab-text {
|
||||
@ -929,7 +912,7 @@
|
||||
/* Fixed Banner Container */
|
||||
.banner-container {
|
||||
position: fixed;
|
||||
top: 180rpx; /* uni-nav-bar height */
|
||||
top: calc(var(--status-bar-height) + 44px); /* uni-nav-bar height */
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 50;
|
||||
@ -967,7 +950,7 @@
|
||||
/* Fixed Filter Tabs Container */
|
||||
.filter-tabs-container {
|
||||
position: fixed;
|
||||
top: 580rpx; /* banner-container top + banner height */
|
||||
top: calc(var(--status-bar-height) + 44px + 400rpx); /* banner-container top + banner height */
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 40;
|
||||
@ -1154,7 +1137,7 @@
|
||||
|
||||
.popup-content {
|
||||
width: 100%;
|
||||
margin-top: 650rpx;
|
||||
margin-top: calc(var(--status-bar-height) + 44px + 400rpx + 117rpx);
|
||||
height: 80vh;
|
||||
background-color: #fff;
|
||||
|
||||
@ -1276,7 +1259,7 @@
|
||||
z-index: 9999;
|
||||
|
||||
.filter-content {
|
||||
margin-top:660rpx;
|
||||
margin-top:calc(var(--status-bar-height) + 44px + 400rpx + 117rpx);
|
||||
overflow-y:scroll;
|
||||
background-color: $white;
|
||||
// border-radius: 20rpx 20rpx 0 0;
|
||||
|
||||
@ -1,26 +1,142 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<navBar :title="title" :showLeft="true"></navBar>
|
||||
<view class="container" :style="{ backgroundColor: backgroundColor }">
|
||||
<!-- 分享弹窗 -->
|
||||
|
||||
|
||||
<view class="navbox">
|
||||
<view class="status_bar"></view>
|
||||
<uni-nav-bar
|
||||
left-icon="left"
|
||||
:title="title"
|
||||
@clickLeft="goBack"
|
||||
color="#8B2316"
|
||||
:border="false"
|
||||
backgroundColor="#eeeeee"
|
||||
>
|
||||
<template #right>
|
||||
<view class="nav-actions">
|
||||
<view class="collect-img" @click="shareToggle" v-if="canShare">
|
||||
<image class="share-img-icon" :src="shareIcon" mode="aspectFill" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</uni-nav-bar>
|
||||
</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>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { onLoad,onHide,onShow,onUnload} from "@dcloudio/uni-app";
|
||||
import navBar from "@/components/navBar/navBar.vue";
|
||||
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";
|
||||
const title = ref("新闻详情");
|
||||
const safeUrl = ref("");
|
||||
|
||||
const backgroundColor = ref("");
|
||||
const hasBg = ref(false);
|
||||
const canShare = ref(false);
|
||||
const summary = ref("");
|
||||
const shareLink = ref("");
|
||||
const shareImg=ref("");
|
||||
const shareTitle = ref("");
|
||||
const goBack = () => {
|
||||
uni.navigateBack({
|
||||
fail() {
|
||||
uni.redirectTo({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
onShow(() => {
|
||||
uni.hideLoading();
|
||||
// console.log('show');
|
||||
// plus.screen.lockOrientation('portrait-primary');
|
||||
|
||||
|
||||
});
|
||||
onUnload(() => {
|
||||
// console.log('onUnload');
|
||||
// plus.screen.lockOrientation('portrait-primary');
|
||||
});
|
||||
onHide(() => {
|
||||
// console.log('onHide');
|
||||
// plus.screen.lockOrientation('landscape-primary');
|
||||
|
||||
|
||||
});
|
||||
onLoad((query) => {
|
||||
// 兼容编码后的 url
|
||||
if(query.title){
|
||||
title.value = query.title;
|
||||
}
|
||||
if(query.share == 1){
|
||||
canShare.value = true;
|
||||
}
|
||||
if(query.bg == 1){
|
||||
hasBg.value = true;
|
||||
|
||||
backgroundColor.value = "linear-gradient(to bottom,'#fff' , '#398775')";
|
||||
}
|
||||
|
||||
var height = 0; //定义动态的高度变量,如高度为定值,可以直接写
|
||||
uni.getSystemInfo({
|
||||
success: (sysinfo) => {
|
||||
height = sysinfo.windowHeight; //自行修改
|
||||
},
|
||||
complete: () => {}
|
||||
});
|
||||
const raw = query && (query.url || "");
|
||||
try {
|
||||
safeUrl.value = decodeURIComponent(raw);
|
||||
title.value = query.title;
|
||||
shareImg.value = decodeURIComponent(query.imgPath);
|
||||
if(query.type == "live_yugao"){
|
||||
shareTitle.value = query.sharetitle;
|
||||
summary.value = "分享一篇来自“肝胆相照”的会议预告:"+shareTitle.value;
|
||||
|
||||
}else if(query.type == "live_old"){
|
||||
shareTitle.value = query.sharetitle; shareTitle.value = query.sharetitle;
|
||||
summary.value = "分享一篇来自“肝胆相照”的历史会议:"+shareTitle.value;
|
||||
}else if(query.type == "live"){
|
||||
shareTitle.value = '肝胆相照直播:'+query.shareTitle;
|
||||
summary.value = shareTitle.value;
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
let wv = plus.webview.create("", "custom-webview", {
|
||||
top: "140rpx",
|
||||
bottom:"20rpx",
|
||||
bottom:"0rpx",
|
||||
|
||||
});
|
||||
wv.loadURL( safeUrl.value);
|
||||
@ -32,30 +148,720 @@ onLoad((query) => {
|
||||
currentWebview.append(wv);
|
||||
setTimeout(function () {
|
||||
wv = currentWebview.children()[0];
|
||||
uni.getSystemInfo({
|
||||
//成功获取的回调函数,返回值为系统信息
|
||||
success: (sysinfo) => {
|
||||
|
||||
let height = sysinfo.windowHeight; //自行修改,自己需要的高度 此处如底部有其他内容,可以直接---(-50)这种
|
||||
wv.setStyle({ top: 70,height: height- 70});
|
||||
},
|
||||
complete: () => {}
|
||||
});
|
||||
|
||||
wv.setStyle({ top: 80,height: height- 80,bottom:0,scalable:true, videoFullscreen: 'landscape',zIndex:-1});
|
||||
|
||||
}, 300); //如果是页面初始化调用时,需要延时一下
|
||||
wv.onloaded = (e) => {
|
||||
wv.show();
|
||||
|
||||
};
|
||||
|
||||
uni.onWindowResize((res) => {
|
||||
if (res.size.windowHeight < height) {
|
||||
console.log(res.size.windowHeight);
|
||||
|
||||
|
||||
console.log(height)
|
||||
console.log('键盘高度',res.height);
|
||||
setTimeout(function() {
|
||||
wv.setStyle({ //设置web-view距离顶部的距离以及自己的高度,单位为px
|
||||
top:80,
|
||||
videoFullscreen: 'landscape',
|
||||
height: height-res.size.windowHeight+100,
|
||||
scalable: true, //webview的页面是否可以缩放,双指放大缩小
|
||||
})
|
||||
},0);
|
||||
|
||||
//高度缩小
|
||||
//如页面初始化调用需要写延迟
|
||||
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
wv.setStyle({ //设置web-view距离顶部的距离以及自己的高度,单位为px
|
||||
top:80,
|
||||
height:height-80,
|
||||
videoFullscreen: 'landscape',
|
||||
scalable: true, //webview的页面是否可以缩放,双指放大缩小
|
||||
})
|
||||
},0);
|
||||
}
|
||||
})
|
||||
// 创建并展示原生弹窗
|
||||
createNativePopup();
|
||||
|
||||
// #endif
|
||||
} catch (e) {
|
||||
safeUrl.value = raw;
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
const shareRef = ref(null);
|
||||
shareRef.value?.open();
|
||||
// 分享APP
|
||||
const shareToggle = () => {
|
||||
showNativePopup();
|
||||
// console.log(shareRef.value);
|
||||
// shareRef.value?.open();
|
||||
// uni.showActionSheet({
|
||||
// title:"分享",
|
||||
// itemList: ['分享到微信', '分享到朋友圈', '分享到微博'],
|
||||
// success: function (res) {
|
||||
// if(res.tapIndex==0){
|
||||
// shareToWechat()
|
||||
// }else if(res.tapIndex==1){
|
||||
// shareToMoments()
|
||||
// }else{
|
||||
// shareToWeibo()
|
||||
// }
|
||||
// },
|
||||
// })
|
||||
};
|
||||
|
||||
// 关闭分享弹窗
|
||||
const closeShare = () => {
|
||||
shareRef.value.close();
|
||||
};
|
||||
|
||||
// ========= 原生弹窗(plus.nativeObj.view)============
|
||||
const nativeMaskView = ref(null);
|
||||
const nativePopupView = ref(null);
|
||||
const popupShowing = ref(false);
|
||||
// 保存弹窗尺寸信息,供事件处理使用
|
||||
const popupInfo = ref({
|
||||
screenW: 0,
|
||||
screenH: 0,
|
||||
panelH: 0,
|
||||
cancelH: 0,
|
||||
contentTop: 0,
|
||||
iconSize: 0,
|
||||
textSize: 0
|
||||
});
|
||||
|
||||
function createNativePopup() {
|
||||
// #ifdef APP-PLUS
|
||||
if (nativeMaskView.value || nativePopupView.value) return;
|
||||
const screenW = plus.screen.resolutionWidth;
|
||||
const screenH = plus.screen.resolutionHeight;
|
||||
const panelH = uni.upx2px(520); // 面板高度(含标题+内容+取消)
|
||||
const radius = uni.upx2px(20);
|
||||
|
||||
// 保存尺寸信息
|
||||
const iconSize = 50; // 图标大小80px(与图标文件尺寸一致)
|
||||
const titleH = uni.upx2px(80);
|
||||
const cancelH = uni.upx2px(100);
|
||||
const contentTop = uni.upx2px(90) + titleH;
|
||||
const textSize = uni.upx2px(24);
|
||||
|
||||
popupInfo.value = {
|
||||
screenW,
|
||||
screenH,
|
||||
panelH,
|
||||
cancelH,
|
||||
contentTop,
|
||||
iconSize,
|
||||
textSize
|
||||
};
|
||||
// 遮罩
|
||||
nativeMaskView.value = new plus.nativeObj.View('native-share-mask', {
|
||||
left: '0px',
|
||||
top: '0px',
|
||||
width: screenW + 'px',
|
||||
height: screenH + 'px',
|
||||
zindex: 99998,
|
||||
touchable: true,
|
||||
interceptTouchEvent: true
|
||||
}, [
|
||||
{ tag: 'rect', id: 'mask', position: { left: '0px', top: '0px', width: screenW + 'px', height: screenH + 'px' }, color: 'rgba(0,0,0,0.5)' }
|
||||
]);
|
||||
// 面板
|
||||
nativePopupView.value = new plus.nativeObj.View('native-share-panel', {
|
||||
left: '0px',
|
||||
top: (screenH - panelH) + 'px',
|
||||
width: screenW + 'px',
|
||||
height: panelH + 'px',
|
||||
zindex: 99999,
|
||||
touchable: true,
|
||||
interceptTouchEvent: true
|
||||
}, []);
|
||||
// 背景+圆角
|
||||
nativePopupView.value.drawRect({
|
||||
color: '#FFFFFF',
|
||||
radius: radius,
|
||||
rectStyles: {}
|
||||
}, {
|
||||
left: uni.upx2px(0) + 'px',
|
||||
top: uni.upx2px(0) + 'px',
|
||||
width: screenW + 'px',
|
||||
height: panelH + 'px'
|
||||
});
|
||||
// 标题
|
||||
nativePopupView.value.drawText('分享到', {
|
||||
left: '0px',
|
||||
top: uni.upx2px(20) + 'px',
|
||||
width: screenW + 'px',
|
||||
height: titleH + 'px'
|
||||
}, {
|
||||
size: uni.upx2px(32) + 'px',
|
||||
color: '#333333',
|
||||
align: 'center',
|
||||
verticalAlign: 'middle',
|
||||
weight: '500'
|
||||
});
|
||||
// 三个分享项区域(使用图标)
|
||||
const itemW = screenW / 3;
|
||||
const iconTop = contentTop;
|
||||
const textTop = iconTop + iconSize + uni.upx2px(16);
|
||||
|
||||
console.log('图标布局信息:', {
|
||||
screenW,
|
||||
itemW,
|
||||
iconSize,
|
||||
iconTop,
|
||||
contentTop
|
||||
});
|
||||
|
||||
// 图标文件名映射(直接使用文件名,避免路径转换问题)
|
||||
const iconFiles = [
|
||||
'share_weixin.png', // 微信
|
||||
'share_wxc.png', // 朋友圈
|
||||
'share_sina.png' // 微博
|
||||
];
|
||||
|
||||
const items = [
|
||||
{ id: 'it-wechat', text: '微信' },
|
||||
{ id: 'it-moments', text: '朋友圈' },
|
||||
{ id: 'it-weibo', text: '微博' }
|
||||
];
|
||||
|
||||
items.forEach((it, idx) => {
|
||||
const left = idx * itemW;
|
||||
// 计算图标居中位置(确保是整数像素)
|
||||
const iconLeft = Math.round(left + (itemW - iconSize) / 2);
|
||||
const iconLeftPx = iconLeft;
|
||||
// 确保所有图标使用相同的 top 值,保证在一行
|
||||
const iconTopPx = Math.round(iconTop);
|
||||
const iconSizePx = iconSize;
|
||||
|
||||
console.log(`图标 ${idx} (${it.text}): left=${left}, itemW=${itemW.toFixed(2)}, iconLeft=${iconLeftPx}, iconTop=${iconTopPx}, iconSize=${iconSizePx}`);
|
||||
|
||||
// 构建图标本地路径
|
||||
let iconPath = null;
|
||||
try {
|
||||
// 直接使用静态资源路径
|
||||
const iconFile = iconFiles[idx];
|
||||
iconPath = plus.io.convertLocalFileSystemURL('_www/static/' + iconFile);
|
||||
console.log(`图标 ${it.text} 路径: ${iconPath}`);
|
||||
} catch (e) {
|
||||
console.log('构建图标路径失败:', e);
|
||||
iconPath = null;
|
||||
}
|
||||
|
||||
// 绘制图标
|
||||
if (iconPath) {
|
||||
try {
|
||||
console.log(`绘制图标 ${it.text}: 位置=(${iconLeftPx}, ${iconTopPx}), 大小=${iconSizePx}x${iconSizePx}`);
|
||||
// 使用 drawBitmap 绘制图标
|
||||
// 尝试不同的参数格式,确保图标不变形且正确显示
|
||||
// 格式1: drawBitmap(src, position, options)
|
||||
try {
|
||||
nativePopupView.value.drawBitmap(iconPath, {}, {
|
||||
left: iconLeftPx + 'px',
|
||||
top: iconTopPx + 'px',
|
||||
width: iconSizePx + 'px',
|
||||
height: iconSizePx + 'px'
|
||||
});
|
||||
} catch (e1) {
|
||||
// 如果格式1失败,尝试格式2: drawBitmap(src, position)
|
||||
try {
|
||||
nativePopupView.value.drawBitmap(iconPath, {
|
||||
left: iconLeftPx + 'px',
|
||||
top: iconTopPx + 'px',
|
||||
width: iconSizePx + 'px',
|
||||
height: iconSizePx + 'px'
|
||||
});
|
||||
} catch (e2) {
|
||||
console.log('drawBitmap 两种格式都失败:', e1, e2);
|
||||
throw e2;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('绘制图标失败,使用圆形色块代替:', e);
|
||||
// 如果图标加载失败,使用圆形色块作为后备
|
||||
const bgColor = idx === 2 ? '#E6162D' : '#07C160';
|
||||
nativePopupView.value.drawRect({
|
||||
color: bgColor,
|
||||
radius: Math.round(iconSize / 2)
|
||||
}, {
|
||||
left: Math.round(iconLeft) + 'px',
|
||||
top: Math.round(iconTop) + 'px',
|
||||
width: Math.round(iconSize) + 'px',
|
||||
height: Math.round(iconSize) + 'px'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 如果没有图标路径,使用圆形色块
|
||||
const bgColor = idx === 2 ? '#E6162D' : '#07C160';
|
||||
nativePopupView.value.drawRect({
|
||||
color: bgColor,
|
||||
radius: Math.round(iconSize / 2)
|
||||
}, {
|
||||
left: Math.round(iconLeft) + 'px',
|
||||
top: Math.round(iconTop) + 'px',
|
||||
width: Math.round(iconSize) + 'px',
|
||||
height: Math.round(iconSize) + 'px'
|
||||
});
|
||||
}
|
||||
|
||||
// 绘制文字
|
||||
nativePopupView.value.drawText(it.text, {
|
||||
left: left + 'px',
|
||||
top: textTop + 'px',
|
||||
width: itemW + 'px',
|
||||
height: textSize + uni.upx2px(20) + 'px'
|
||||
}, {
|
||||
size: textSize + 'px',
|
||||
color: '#666666',
|
||||
align: 'center',
|
||||
verticalAlign: 'top'
|
||||
});
|
||||
});
|
||||
// 取消按钮分割线
|
||||
const cancelTop = panelH - cancelH;
|
||||
nativePopupView.value.drawRect({ color: '#F0F0F0' }, {
|
||||
left: '0px',
|
||||
top: (cancelTop - 1) + 'px',
|
||||
width: screenW + 'px',
|
||||
height: '1px'
|
||||
});
|
||||
nativePopupView.value.drawText('取消', {
|
||||
left: '0px',
|
||||
top: cancelTop + 'px',
|
||||
width: screenW + 'px',
|
||||
height: cancelH + 'px'
|
||||
}, {
|
||||
size: uni.upx2px(32) + 'px',
|
||||
color: '#333333',
|
||||
align: 'center',
|
||||
verticalAlign: 'middle'
|
||||
});
|
||||
// 事件处理函数
|
||||
const handleMaskClick = () => {
|
||||
console.log('遮罩被点击');
|
||||
closeNativePopup();
|
||||
};
|
||||
|
||||
const handlePanelClick = (e) => {
|
||||
console.log('面板被点击', e);
|
||||
const info = popupInfo.value;
|
||||
|
||||
// 获取点击坐标
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
|
||||
// 尝试多种方式获取坐标
|
||||
if (e.clientX !== undefined && e.clientY !== undefined) {
|
||||
x = e.clientX;
|
||||
y = e.clientY;
|
||||
} else if (e.pageX !== undefined && e.pageY !== undefined) {
|
||||
x = e.pageX;
|
||||
y = e.pageY;
|
||||
} else if (e.touches && e.touches.length > 0) {
|
||||
x = e.touches[0].clientX || e.touches[0].pageX || 0;
|
||||
y = e.touches[0].clientY || e.touches[0].pageY || 0;
|
||||
} else if (e.changedTouches && e.changedTouches.length > 0) {
|
||||
x = e.changedTouches[0].clientX || e.changedTouches[0].pageX || 0;
|
||||
y = e.changedTouches[0].clientY || e.changedTouches[0].pageY || 0;
|
||||
}
|
||||
|
||||
console.log('原始坐标:', x, y);
|
||||
console.log('屏幕信息:', info);
|
||||
|
||||
if (!x || !y) {
|
||||
console.log('坐标无效');
|
||||
return;
|
||||
}
|
||||
|
||||
// 判断坐标是相对于屏幕还是相对于视图
|
||||
// 如果 y 小于 panelH,说明是相对于视图的坐标
|
||||
// 如果 y 大于等于 screenH - panelH,说明是相对于屏幕的坐标
|
||||
let relativeY = y;
|
||||
let relativeX = x;
|
||||
|
||||
if (y < info.panelH) {
|
||||
// 相对于视图的坐标,直接使用
|
||||
relativeY = y;
|
||||
relativeX = x;
|
||||
console.log('使用相对于视图的坐标:', relativeX, relativeY);
|
||||
} else if (y >= (info.screenH - info.panelH)) {
|
||||
// 相对于屏幕的坐标,转换为相对于视图的坐标
|
||||
relativeY = y - (info.screenH - info.panelH);
|
||||
relativeX = x;
|
||||
console.log('使用相对于屏幕的坐标,转换为相对视图:', relativeX, relativeY);
|
||||
} else {
|
||||
// 可能是其他情况,尝试直接使用
|
||||
console.log('坐标类型不确定,尝试直接使用');
|
||||
}
|
||||
|
||||
// 取消区域(底部取消按钮)- 相对于视图
|
||||
const cancelTop = info.panelH - info.cancelH;
|
||||
console.log('取消区域判断: relativeY =', relativeY, ', cancelTop =', cancelTop);
|
||||
if (relativeY >= cancelTop) {
|
||||
console.log('点击了取消按钮');
|
||||
closeNativePopup();
|
||||
return;
|
||||
}
|
||||
|
||||
// 分享项区域(图标+文字区域)- 相对于视图
|
||||
const shareAreaTop = info.contentTop;
|
||||
const shareAreaBottom = shareAreaTop + info.iconSize + info.textSize + uni.upx2px(20);
|
||||
|
||||
console.log('分享区域: relativeY =', relativeY, ', 范围 =', shareAreaTop, '到', shareAreaBottom);
|
||||
|
||||
if (relativeY >= shareAreaTop && relativeY <= shareAreaBottom) {
|
||||
// 计算点击的是第几个分享项(0:微信, 1:朋友圈, 2:微博)
|
||||
const itemWidth = info.screenW / 3;
|
||||
const idx = Math.min(2, Math.max(0, Math.floor(relativeX / itemWidth)));
|
||||
|
||||
console.log('点击了分享项:', idx, ', x =', relativeX, ', itemWidth =', itemWidth);
|
||||
|
||||
if (idx === 0) {
|
||||
console.log('执行微信分享');
|
||||
shareToWechat();
|
||||
closeNativePopup();
|
||||
} else if (idx === 1) {
|
||||
console.log('执行朋友圈分享');
|
||||
shareToMoments();
|
||||
closeNativePopup();
|
||||
} else if (idx === 2) {
|
||||
console.log('执行微博分享');
|
||||
shareToWeibo();
|
||||
closeNativePopup();
|
||||
}
|
||||
} else {
|
||||
console.log('点击位置不在分享区域内, relativeY =', relativeY, ', 需要范围:', shareAreaTop, '到', shareAreaBottom);
|
||||
}
|
||||
};
|
||||
|
||||
// 同时监听 click 和 touchstart 事件
|
||||
nativeMaskView.value.addEventListener('click', handleMaskClick, false);
|
||||
nativeMaskView.value.addEventListener('touchstart', handleMaskClick, false);
|
||||
|
||||
nativePopupView.value.addEventListener('click', handlePanelClick, false);
|
||||
nativePopupView.value.addEventListener('touchstart', handlePanelClick, false);
|
||||
nativePopupView.value.addEventListener('touchend', handlePanelClick, false);
|
||||
// #endif
|
||||
}
|
||||
|
||||
function showNativePopup() {
|
||||
// #ifdef APP-PLUS
|
||||
if (popupShowing.value) return;
|
||||
if (!nativeMaskView.value || !nativePopupView.value) {
|
||||
createNativePopup();
|
||||
}
|
||||
nativeMaskView.value && nativeMaskView.value.show();
|
||||
nativePopupView.value && nativePopupView.value.show();
|
||||
popupShowing.value = true;
|
||||
// #endif
|
||||
}
|
||||
|
||||
function closeNativePopup() {
|
||||
// #ifdef APP-PLUS
|
||||
if (!popupShowing.value) return;
|
||||
nativeMaskView.value && nativeMaskView.value.hide();
|
||||
nativePopupView.value && nativePopupView.value.hide();
|
||||
popupShowing.value = false;
|
||||
// #endif
|
||||
}
|
||||
|
||||
// 分享到微信
|
||||
const shareToWechat = () => {
|
||||
// #ifdef APP-PLUS
|
||||
// 使用系统分享
|
||||
uni.share({
|
||||
provider: "weixin",
|
||||
scene: "WXSceneSession",
|
||||
type: 0,
|
||||
title: shareTitle.value,
|
||||
summary:summary.value,
|
||||
href: safeUrl.value,
|
||||
imageUrl: shareImg.value,
|
||||
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();
|
||||
};
|
||||
|
||||
// 页面隐藏/销毁时清理原生弹窗
|
||||
onHide(() => {
|
||||
// #ifdef APP-PLUS
|
||||
closeNativePopup();
|
||||
// #endif
|
||||
});
|
||||
onUnload(() => {
|
||||
// #ifdef APP-PLUS
|
||||
try{
|
||||
nativeMaskView.value && nativeMaskView.value.close && nativeMaskView.value.close();
|
||||
nativePopupView.value && nativePopupView.value.close && nativePopupView.value.close();
|
||||
}catch(e){}
|
||||
nativeMaskView.value = null;
|
||||
nativePopupView.value = null;
|
||||
popupShowing.value = false;
|
||||
// #endif
|
||||
});
|
||||
// 分享到朋友圈
|
||||
const shareToMoments = () => {
|
||||
// #ifdef APP-PLUS
|
||||
uni.share({
|
||||
provider: "weixin",
|
||||
scene: "WXSceneTimeline",
|
||||
type: 0,
|
||||
title: shareTitle.value,
|
||||
summary:summary.value,
|
||||
href: safeUrl.value,
|
||||
imageUrl: shareImg.value,
|
||||
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: shareTitle.value ,
|
||||
summary:summary.value,
|
||||
href: safeUrl.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>
|
||||
|
||||
<style>
|
||||
.mask{
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 10000000;
|
||||
}
|
||||
/* 分享弹窗样式 */
|
||||
.share-popup {
|
||||
background-color: #fff;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
padding: 40rpx 0 0;
|
||||
}
|
||||
.share-img {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
}
|
||||
.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;
|
||||
}
|
||||
.nav-actions .share-img-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
.nav-actions .collect-img-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
.nav-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
height: 100vh;
|
||||
position: relative;
|
||||
z-index:0;
|
||||
overflow: scroll;
|
||||
}
|
||||
.tip {
|
||||
|
||||
@ -232,7 +232,7 @@
|
||||
:class="{ active: tag.selected }"
|
||||
@click="toggleTag(index)"
|
||||
>
|
||||
{{ tag.DES }}
|
||||
{{ tag.NAME }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -313,9 +313,9 @@
|
||||
console.log('选中的筛选标签:', selectedTags);
|
||||
for (var i = 0; i < selectedTags.length; i++) {
|
||||
if(keywords.value){
|
||||
keywords.value+=","+selectedTags[i].DES
|
||||
keywords.value+=","+selectedTags[i].NAME
|
||||
}else{
|
||||
keywords.value=selectedTags[i].DES
|
||||
keywords.value=selectedTags[i].NAME
|
||||
}
|
||||
|
||||
navTo({
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
:class="{ active: tag.selected }"
|
||||
@click="toggleTag(index)"
|
||||
>
|
||||
{{ tag.DES }}
|
||||
{{ tag.NAME }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -316,7 +316,7 @@
|
||||
|
||||
// 执行筛选逻辑
|
||||
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);
|
||||
keywords.value = selectedTags.join(',');
|
||||
} else {
|
||||
|
||||
@ -56,7 +56,7 @@
|
||||
:class="{ active: tag.selected }"
|
||||
@click="toggleTag(index)"
|
||||
>
|
||||
{{ tag.DES }}
|
||||
{{ tag.NAME }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@ -356,7 +356,7 @@
|
||||
|
||||
// 执行筛选逻辑
|
||||
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);
|
||||
keywords.value = selectedTags.join(',');
|
||||
} else {
|
||||
|
||||
BIN
static/fxbb.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
static/huanhuan.png
Normal file
|
After Width: | Height: | Size: 928 B |
BIN
static/ic_about_app.png
Normal file
|
After Width: | Height: | Size: 147 KiB |
BIN
static/icon_share.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
static/meetHis.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/pcquer.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
static/share_sina.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
static/share_weixin.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
static/share_wxc.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
static/suifang.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
static/weiboShare.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
static/yingxiongbanglog.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
static/yxb.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
static/zixunexpert.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
@ -43,6 +43,22 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
9
uni_modules/mumu-previewOffce/changelog.md
Normal file
@ -0,0 +1,9 @@
|
||||
## 1.0.3(2023-02-22)
|
||||
本插件将于2023/11/30停止提供服务
|
||||
## 1.0.2(2022-07-19)
|
||||
- 【添加】 兼容大部分小程序
|
||||
- 【修复】 微信小程序中直接打开问题
|
||||
## 1.0.1(2022-07-02)
|
||||
修复在 ios 下背景出现大量标题,主题,创作者等等数据
|
||||
## 1.0.0(2022-05-25)
|
||||
版本上线
|
||||
@ -0,0 +1,208 @@
|
||||
<template>
|
||||
<view class="preview" v-if="value && isMp === false">
|
||||
<view class="right" :class="previewType"></view>
|
||||
<view class="left" :class="previewType"></view>
|
||||
<iframe :src="previewUrl" width="100%" frameborder="0" id="if"></iframe>
|
||||
<view class="error" v-if="isError">传入文件格式不正确</view>
|
||||
<view class="loading">预览模块加载中...</view>
|
||||
|
||||
<view class="close" @click="closePre()">关闭</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
model: {
|
||||
event: 'change'
|
||||
},
|
||||
props: {
|
||||
fileUrl: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
value: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
previewUrl: ``,
|
||||
isError: false,
|
||||
isMp: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
fileUrl: {
|
||||
handler(newValue) {
|
||||
if (!newValue) return
|
||||
//#ifdef MP
|
||||
this.isMp = true
|
||||
uni.downloadFile({
|
||||
url: newValue,
|
||||
success: res => {
|
||||
const filePath = res.tempFilePath
|
||||
uni.openDocument({
|
||||
filePath: filePath,
|
||||
success: res => {
|
||||
console.log('打开文档成功')
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
//#endif
|
||||
|
||||
//#ifndef MP
|
||||
let exit = newValue.split('.')
|
||||
if (!exit.length) return (this.isError = true)
|
||||
exit = exit.pop()
|
||||
const arr = ['pptx', 'ppt', 'docx', 'doc', 'xlsx', 'xls', 'pdf']
|
||||
if (arr.indexOf(exit) === -1) return (this.isError = true)
|
||||
this.isError = false
|
||||
if (exit === 'pdf') return (this.previewUrl = this.pasePdfUrl(newValue))
|
||||
this.previewUrl = this.paseOfficeUrl(newValue)
|
||||
//#endif
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
closePre() {
|
||||
this.$emit('change', false)
|
||||
},
|
||||
paseOfficeUrl(url) {
|
||||
url = encodeURIComponent(url)
|
||||
return `https://view.officeapps.live.com/op/embed.aspx?src=${url}&wdPrint=0&wdEmbedCode=0&wdStartOn=1`
|
||||
},
|
||||
pasePdfUrl(url) {
|
||||
//url = encodeURIComponent(url)
|
||||
return `https://previewpdf.mumudev.top/?file=${url}`
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
previewType() {
|
||||
let exit = this.fileUrl.split('.')
|
||||
if (!exit.length) return console.log('传入文件格式不正确')
|
||||
exit = exit.pop()
|
||||
|
||||
switch (exit) {
|
||||
case 'pptx':
|
||||
case 'ppt':
|
||||
return 'ppt'
|
||||
case 'docx':
|
||||
case 'doc':
|
||||
return 'word'
|
||||
case 'xlsx':
|
||||
case 'xls':
|
||||
return 'excel'
|
||||
case 'pdf':
|
||||
return ''
|
||||
default:
|
||||
console.log('传入文件格式不正确')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.preview {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #fff;
|
||||
z-index: 100;
|
||||
|
||||
.right,
|
||||
.left {
|
||||
position: absolute;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.ppt {
|
||||
height: 20px;
|
||||
width: 80px;
|
||||
background-color: #444444;
|
||||
|
||||
&.right {
|
||||
bottom: 2px;
|
||||
right: 4px;
|
||||
}
|
||||
|
||||
&.left {
|
||||
left: 4px;
|
||||
bottom: 2px;
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.word {
|
||||
position: absolute;
|
||||
width: 80px;
|
||||
height: 17px;
|
||||
background-color: #ffffff;
|
||||
|
||||
&.right {
|
||||
bottom: 2px;
|
||||
right: 2px;
|
||||
}
|
||||
|
||||
&.left {
|
||||
left: 2px;
|
||||
bottom: 2px;
|
||||
width: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.excel {
|
||||
position: absolute;
|
||||
width: 90px;
|
||||
height: 23px;
|
||||
background-image: linear-gradient(#3f4244, #36383a);
|
||||
|
||||
&.right {
|
||||
bottom: 2px;
|
||||
right: 2px;
|
||||
}
|
||||
|
||||
&.left {
|
||||
left: 2px;
|
||||
bottom: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: 10px;
|
||||
background-color: #ccc;
|
||||
color: #fff;
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
font-size: 12px;
|
||||
z-index: 102;
|
||||
}
|
||||
|
||||
.error {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.loading {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
#if {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
z-index: 101;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
85
uni_modules/mumu-previewOffce/package.json
Normal file
@ -0,0 +1,85 @@
|
||||
{
|
||||
"id": "mumu-previewOffce",
|
||||
"displayName": "预览offce文件。可以打开 PDF WORD PPT EXCEL 文件",
|
||||
"version": "1.0.3",
|
||||
"description": "在程序中直接打开 offce 文件进行预览。可以打开 PDF WORD PPT EXCEL 文件",
|
||||
"keywords": [
|
||||
"PDF",
|
||||
"WORD",
|
||||
"PPT",
|
||||
"EXCEL",
|
||||
"offce"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "n"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "n",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "y",
|
||||
"快手": "u",
|
||||
"飞书": "y",
|
||||
"京东": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
85
uni_modules/mumu-previewOffce/readme.md
Normal file
@ -0,0 +1,85 @@
|
||||
# 插件介绍
|
||||
|
||||
** 预览的文件地址必须是可以通过互联网访问的!!! **
|
||||
|
||||
** 预览的文件地址必须是可以直接复制在浏览器地址中访问的!!! **
|
||||
|
||||
## 本插件将于2023/11/30停止提供服务
|
||||
|
||||
文档预览工具新版本已上线
|
||||
|
||||
对比当前版本支持了手机端双手缩放操作,office文件不在依赖微软的解析接口,支持服务端完全私有化部署(内网部署),UI界面有单独的电脑端、ios端、安卓端。
|
||||
|
||||
新版地址:[h5office。预览office文件,预览文档,打开PDF WORD PPT EXCEL 文件 - DCloud 插件市场](https://ext.dcloud.net.cn/plugin?id=10895)
|
||||
|
||||
## 插件原理
|
||||
|
||||
> pdf 文件预览是通过 `pdf.js` 开源库,搭建了一个pdf预览的网站。前端只需要使用 iframe 加载这个网站即可。[pdf.js 官网](http://mozilla.github.io/pdf.js/api/draft/index.html)
|
||||
>
|
||||
> offce 文件的预览是通过微软offce在线接口进行解析的。offce在线地址:https://view.officeapps.live.com/op/embed.aspx?src=‘你的文件网络地址’
|
||||
>
|
||||
> 在微信小程序中,是通过小程序中的API进行预览的。[小程序文档](https://developers.weixin.qq.com/miniprogram/dev/api/file/wx.openDocument.html)
|
||||
|
||||
## 使用环境
|
||||
|
||||
** 不支持nvue 。小程序中使用官方提供的api。h5与其他环境是通过上面介绍的插件原理加载。**
|
||||
|
||||
## 插件使用
|
||||
|
||||
**插件已支持 uni_modules 支持组件easycom,以下代码演示的是普通使用**
|
||||
|
||||
``` html
|
||||
<!-- HTML -->
|
||||
<mumu-previewOffce :fileUrl='fileUrl' v-model='showPreview'></mumu-previewOffce>
|
||||
|
||||
<button @click='showPreview = true'></button>
|
||||
```
|
||||
|
||||
``` js
|
||||
import MumuPreviewOffce from '@/uni_modules/mumu-previewOffce/components/mumu-previewOffce/mumu-previewOffce.vue'
|
||||
export default {
|
||||
components: {
|
||||
MumuPreviewOffce
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showPreview: false,
|
||||
fileUrl: 'https://h5plugin.mumudev.top/public/previewOffce/333.docx'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 相关 API
|
||||
|
||||
### 可传属性(Props)
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 可选 |
|
||||
| ------- | ------------------------ | ------- | ------ | ------------ |
|
||||
| v-model | 双向绑定,显示或隐藏组件 | Boolean | false | false / true |
|
||||
| fileUrl | 预览文件的网络地址 | String | - | - |
|
||||
|
||||
|
||||
|
||||
## 打开本地预览
|
||||
|
||||
本地预览功能还在开发中...
|
||||
|
||||
开发思路是:
|
||||
|
||||
> 选择打开本地文件,上传到服务器。获取到服务器中的文件地址,传递给当前组件展示。
|
||||
|
||||
没有办法直接在本地打开,所有采取这种方案。有条件的同学可以自己开发。我也会尽快把这个功能做出来。
|
||||
|
||||
|
||||
|
||||
## 案例演示
|
||||
|
||||

|
||||
|
||||
## 支持作者
|
||||
|
||||

|
||||
70
utils/aesEcb.js
Normal file
@ -0,0 +1,70 @@
|
||||
import crypto from "crypto-js";
|
||||
//解密
|
||||
|
||||
const decryptAesEcb = (sSrc, sKey) => {
|
||||
try {
|
||||
if (!sKey) {
|
||||
console.error("Key为空null");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 1. 将密钥转为 WordArray(crypto 内部格式)
|
||||
const key = crypto.enc.Utf8.parse(sKey);
|
||||
|
||||
// 2. Base64 解码密文,得到 WordArray
|
||||
const encryptedBytes = crypto.enc.Base64.parse(sSrc);
|
||||
|
||||
// 3. 使用 AES/ECB/PKCS7 解密
|
||||
const decrypted = crypto.AES.decrypt(
|
||||
{ ciphertext: encryptedBytes }, // 加密数据
|
||||
key, // 密钥
|
||||
{
|
||||
mode: crypto.mode.ECB, // ECB 模式
|
||||
padding: crypto.pad.Pkcs7, // PKCS7(等同于 Java 的 PKCS5Padding)
|
||||
}
|
||||
);
|
||||
|
||||
// 4. 将解密结果转为 UTF-8 字符串
|
||||
const decryptedText = decrypted.toString(crypto.enc.Utf8);
|
||||
|
||||
return decryptedText; // 如果解密失败,可能返回空字符串或非法字符
|
||||
} catch (error) {
|
||||
console.error("解密失败:", error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
//加密
|
||||
const encryptAesEcb = (sSrc, sKey) => {
|
||||
try {
|
||||
if (!sKey) {
|
||||
console.error("Key为空null");
|
||||
return null;
|
||||
}
|
||||
|
||||
// 1. 将密钥转为 WordArray(crypto 内部格式)
|
||||
const key = crypto.enc.Utf8.parse(sKey);
|
||||
|
||||
// 2. 将明文转为 WordArray
|
||||
const srcBytes = crypto.enc.Utf8.parse(sSrc);
|
||||
|
||||
// 3. 使用 AES/ECB/PKCS7 加密
|
||||
const encrypted = crypto.AES.encrypt(
|
||||
srcBytes, // 明文数据
|
||||
key, // 密钥
|
||||
{
|
||||
mode: crypto.mode.ECB, // ECB 模式
|
||||
padding: crypto.pad.Pkcs7, // PKCS7 填充
|
||||
}
|
||||
);
|
||||
|
||||
// 4. 将加密结果转为 Base64 字符串
|
||||
// crypto-js 的 encrypt 方法返回的对象中,ciphertext 是 WordArray 格式
|
||||
const encryptedBase64 = encrypted.ciphertext.toString(crypto.enc.Base64);
|
||||
|
||||
return encryptedBase64;
|
||||
} catch (error) {
|
||||
console.error("加密失败:", error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
export { decryptAesEcb, encryptAesEcb };
|
||||
@ -14,5 +14,6 @@ if(process.env.UNI_PLATFORM =="h5"){
|
||||
}
|
||||
}else{
|
||||
BASE_URL='https://dev-app.igandan.com/app'
|
||||
//BASE_URL='https://app.igandan.com/app'
|
||||
}
|
||||
export default BASE_URL
|
||||
@ -14,5 +14,6 @@ if(process.env.UNI_PLATFORM =="h5"){
|
||||
}
|
||||
}else{
|
||||
DOC_URL='https://dev-doc.igandan.com/app/'
|
||||
//DOC_URL='https://doc.igandan.com/app/'
|
||||
}
|
||||
export default DOC_URL
|
||||
9
utils/formatNumber.js
Normal file
@ -0,0 +1,9 @@
|
||||
const formatNumber = (number) => {
|
||||
|
||||
if(number < 10000){
|
||||
return number;
|
||||
}else{
|
||||
return (number / 10000).toFixed(1) + 'w';
|
||||
}
|
||||
}
|
||||
export default formatNumber;
|
||||
13
utils/otherHost.js
Normal file
@ -0,0 +1,13 @@
|
||||
let OTHER_HOST=''
|
||||
if(process.env.UNI_PLATFORM =="mp-weixin"){
|
||||
const { envVersion } = uni.getAccountInfoSync().miniProgram;
|
||||
if (envVersion == "release") {
|
||||
OTHER_HOST='https://wx.igandan.com'
|
||||
}else{
|
||||
OTHER_HOST='https://dev-wx.igandan.com'
|
||||
}
|
||||
}else{
|
||||
OTHER_HOST='https://dev-wx.igandan.com'
|
||||
//OTHER_HOST='https://wx.igandan.com'
|
||||
}
|
||||
export default OTHER_HOST
|
||||
35
utils/permission.js
Normal file
@ -0,0 +1,35 @@
|
||||
import permision from "@/js_sdk/wa-permission/permission.js"
|
||||
const getCameraPermission = async(callback) => {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
// 判断平台
|
||||
if (systemInfo.platform === 'android') {
|
||||
let result = await permision.requestAndroidPermission('android.permission.CAMERA');
|
||||
if(result == 1){
|
||||
callback();
|
||||
}else{
|
||||
openModal('请授权相机权限');
|
||||
}
|
||||
} else if (systemInfo.platform === 'ios') {
|
||||
let iosResult = await permision.judgeIosPermission("camera")
|
||||
if(iosResult){
|
||||
callback();
|
||||
}else{
|
||||
openModal('请授权相机权限');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
const openModal=(content)=>{
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content:content,
|
||||
showCancel: true,
|
||||
success: (res) => {
|
||||
if(res.confirm){
|
||||
permision.gotoAppPermissionSetting();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
export { getCameraPermission };
|
||||
@ -137,8 +137,10 @@ export const request = (url, data = {}, method = 'post', loading = false, conten
|
||||
n(res)
|
||||
} else {
|
||||
|
||||
if(url.indexOf('addOutPatientA')!=-1){
|
||||
if(url.indexOf('addOutPatientA')!=-1 || url.indexOf('checkVersion')!=-1){
|
||||
e(res.data)
|
||||
}else if(res.data.code==35002){
|
||||
n(res)
|
||||
}else{
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
|
||||