Flash在FF下当设置overflow-y:scroll时,失去热点的bug

今天遇到了一个奇怪的问题,flash在FF下不能点击,所有按钮均失效,而且flash自身的右键菜单明显不在鼠标XY点上。

而当flash设置为不透明时,此问题就不存在。

 

后来经过多次试验,终于找着原因,是因为网页中有一个div设置了overflow-y:scroll,如果将此设置去掉,即使flash是透明的,问题也不存在。断定是FF的bug。

 

然后接着在网上搜结果,发现有人遇到过此问题,说把设置了overflow-y:scroll的Dom的margin设置为非零的数(如margin:0.1px)就可以解决此问题,照此做了,仍然不行。

 

再后来仍然没有解决办法,先暂时在此记录此事吧,以后有结果了,或者有哪位仁兄有解决方法的话,要分享一下。

<template> <view class="container"> <!-- 顶部导航栏 --> <view class="nav_title"> <image class="image_btn mr24" src="/static/user/left.png" mode="aspectFit" @click="backOut"></image> <text class="nav_text">个人中心</text> </view> <scroll-view style="flex: 1;"> <!-- 用户信息区域 --> <view class="normal_box user_info"> <text class="user_name">{{ userNickName }}</text> <view class="user_number"> <image class="image_btn mr24" src="/static/user/phone.png" mode="aspectFit"></image> <text class="number">{{ userPhoneNumber }}</text> </view> </view> <!-- 功能列表 --> <view class="normal_box function_box"> <!-- 账号切换 --> <view class="function_ul" @click="showPopup('user')"> <view class="function_li"> <image class="image_btn mr24" src="/static/user/user.png" mode="aspectFit"></image> <text class="function_tit">账号切换</text> </view> <view class="function_li"> <text class="function_text">{{ userNickName }}</text> <image class="image_btn" src="/static/user/right.png" mode="aspectFit"></image> </view> </view> <view class="function_ul mt80" @click="toSetPsd"> <view class="function_li"> <image class="image_btn mr24" src="/static/user/psd.png" mode="aspectFit"></image> <text class="function_tit">修改密码</text> </view> <view class="function_li"> <image class="image_btn" src="/static/user/right.png" mode="aspectFit"></image> </view> </view> </view> <view class="normal_box function_box"> <view class="function_ul"> <view class="function_li"> <image class="image_btn mr24" src="/static/user/voice.png" mode="aspectFit"></image> <text class="function_tit">语音播报</text> </view> <view class="function_li"> <!-- 修复:直接使用 data 变量,无 this --> <switch :checked="isVoiceChecked" @change="switchChange" /> </view> </view> <!-- 声音类别 --> <!-- 修复:简化条件表达式,直接使用布尔变量 --> <view class="function_ul mt80" @click="showPopup('voice')" v-show="isVoiceChecked"> <view class="function_li"> <image class="image_btn mr24" src="/static/user/voice_type.png" mode="aspectFit"></image> <text class="function_tit">声音类别</text> </view> <view class="function_li"> <text class="function_text">{{ selectedVoice }}</text> <image class="image_btn" src="/static/user/right.png" mode="aspectFit"></image> </view> </view> </view> <view class="normal_box function_box"> <view class="function_ul" @click="toProblem"> <view class="function_li"> <image class="image_btn mr24" src="/static/user/issue.png" mode="aspectFit"></image> <text class="function_tit">常见问题</text> </view> <view class="function_li"> <image class="image_btn" src="/static/user/right.png" mode="aspectFit"></image> </view> </view> <view class="function_ul mt80" @click="toVersion"> <view class="function_li"> <image class="image_btn mr24" src="/static/user/normal.png" mode="aspectFit"></image> <text class="function_tit">版本号</text> </view> <view class="function_li"> <text class="function_text">V2.62</text> <image class="image_btn" src="/static/user/right.png" mode="aspectFit"></image> </view> </view> <view class="function_ul mt80" @click="toAccord"> <view class="function_li"> <image class="image_btn mr24" src="/static/user/normal.png" mode="aspectFit"></image> <text class="function_tit">软件协议</text> </view> <view class="function_li"> <image class="image_btn" src="/static/user/right.png" mode="aspectFit"></image> </view> </view> </view> <view class="normal_box mt80" @click="logout"><text class="exit">退出登录</text></view> <!-- 遮罩层 --> <view class="mask" v-if="isPopupShow" @click="closePopup"></view> <!-- 自定义底部弹窗 --> <view class="bottom-popup" :class="{ 'popup-show': isPopupShow }"> <view class="popup-header"> <image @click="closePopup" class="image_btn mr24 popup-img" src="/static/user/close.png" mode="aspectFit"></image> <text class="popup-title">{{ popupTitleText }}</text> </view> <view class="popup-list"> <!-- 账号切换弹窗 --> <view v-if="popupType === 'user'"> <view class="account-item" v-for="(account, index) in savedAccountList" :key="index"> <view class="account-info" @click="selectAccount(account)"> <text class="account-name">{{ getAccountNickName(account) }}</text> <text class="account-phone">{{ account.phone }}</text> </view> <view class="account-actions"> <text class="current-tag" v-if="account.isCurrent">当前</text> <text class="delete-btn" v-else @click.stop="deleteAccount(account.phone)">删除</text> </view> </view> </view> <!-- 声音选择弹窗 --> <view v-else-if="popupType === 'voice'"> <view class="popup-item" v-for="(item, index) in voiceOptions" :key="index" @click="selectVoice(item)"> <text class="popup-item-text">{{ item }}</text> </view> </view> </view> </view> </scroll-view> </view> </template> <script lang="uts"> import { UserInfo, AccountInfo } from '@/utils/typedef'; import { getCurrentUserInfoObj, getSavedAccounts, switchCurrentAccount, deleteAccount as deleteAccountApi } from '@/utils/common'; type DataReturn = { userNickName : string; userPhoneNumber : string; selectedVoice : string; selectedGps : string; isPopupShow : boolean; popupType : 'user' | 'voice' | 'gps' | ''; popupTitleText : string; isVoiceChecked : boolean; userInfo : UserInfo | null; savedAccountList : AccountInfo[]; voiceOptions : string[]; userPhoneMap : UTSJSONObject; } export default { components: {}, data() : DataReturn { return { userNickName: '未登录', userPhoneNumber: '', selectedVoice: '男声', selectedGps: '仅设备', isPopupShow: false, popupType: '', popupTitleText: '', isVoiceChecked: false, userInfo: null, savedAccountList: [] as AccountInfo[], voiceOptions: ['男声', '女声'], userPhoneMap: {} // UTSJSONObject,初始值为空对象 }; }, onLoad() { this.getUserInfo(); }, onShow() { this.getUserInfo(); }, methods: { // 返回首页 backOut() { uni.redirectTo({ url: '/pages/index/index' }); }, // 获取当前用户信息(更新数据到 data,避免模板调用方法) getUserInfo() : void { this.userInfo = getCurrentUserInfoObj(); // 明确布尔判断,替换可选链和 || 短路运算(UTS 要求) this.userNickName = (this.userInfo !== null && this.userInfo.nickName !== null && this.userInfo.nickName !== '') ? this.userInfo.nickName : '未登录'; this.userPhoneNumber = (this.userInfo !== null && this.userInfo.phoneNumber !== null && this.userInfo.phoneNumber !== '') ? this.userInfo.phoneNumber : ''; // 同步账号列表 this.savedAccountList = getSavedAccounts().accounts; }, // 解析账号昵称(仅用于账号列表) getAccountNickName(account : AccountInfo) : string { try { const userInfo = JSON.parse(account.userInfo) as UTSJSONObject; // 明确布尔判断,替换可选链 return (userInfo !== null && userInfo.nickName !== null && userInfo.nickName !== '') ? userInfo.nickName : account.phone; } catch (e) { return account.phone; } }, // 语音开关切换 switchChange(e : UniSwitchChangeEvent) { this.isVoiceChecked = e.detail.value; // 赋值给明确的布尔变量 }, // 选择声音 selectVoice(voice : string) : void { this.selectedVoice = voice; this.closePopup(); }, // 选择GPS模式 selectGps(gpsMode : string) : void { this.selectedGps = gpsMode; this.closePopup(); }, // 页面跳转方法(不变) toSetPsd() { uni.navigateTo({ url: "/pages/user/reset" }); }, toProblem() { uni.navigateTo({ url: "/pages/user/problem" }); }, toAccord() { uni.navigateTo({ url: "/pages/user/accord" }); }, toVersion() { uni.navigateTo({ url: "/pages/user/version" }); }, // 退出登录 logout() { uni.showModal({ title: '确认退出', content: '确定要退出当前账号吗?', success: (res) => { if (res.confirm) { const { accounts } = getSavedAccounts(); const updatedAccounts = accounts.map(item => ({ ...item, isCurrent: false })); uni.setStorageSync('savedAccounts', JSON.stringify({ accounts: updatedAccounts })); uni.removeStorageSync('userToken'); uni.removeStorageSync('userInfo'); uni.removeStorageSync('loginTime'); uni.redirectTo({ url: '/pages/login/login' }); } } }); }, // 显示弹窗(简化逻辑,直接赋值预定义选项) showPopup(type : 'user' | 'voice' | 'gps') : void { this.isPopupShow = true; this.popupType = type; switch (type) { case 'user': this.popupTitleText = '选择账号'; this.savedAccountList = getSavedAccounts().accounts; // 刷新账号列表 break; case 'voice': this.popupTitleText = '选择声音'; break; case 'gps': this.popupTitleText = '选择GPS模式'; break; } }, // 关闭弹窗 closePopup() : void { this.isPopupShow = false; this.popupType = ''; }, // 选择账号 selectAccount(account : AccountInfo) : void { if (account.isCurrent) { this.closePopup(); return; } switchCurrentAccount(account.phone); this.getUserInfo(); // 重新获取用户信息 uni.showToast({ title: '账号切换成功' }); setTimeout(() => { this.closePopup(); uni.redirectTo({ url: '/pages/index/index' }); }, 500); }, // 删除账号 deleteAccount(phone : string) { uni.showModal({ title: '确认删除', content: '确定要删除该账号吗?删除后需重新登录', success: (res) => { if (res.confirm) { const newAccounts = deleteAccountApi(phone); this.savedAccountList = newAccounts; // 更新本地列表 if (newAccounts.length === 0) { this.closePopup(); uni.redirectTo({ url: '/pages/login/login' }); } } } }); } } }; </script> <style scoped> .image_btn { width: 36rpx; height: 36rpx; } .mr24 { margin-right: 14rpx; } .normal_box { border-radius: 16px; opacity: 1; background: #fff; padding: 40rpx 50rpx; box-sizing: border-box; border: 1rpx solid #FFFFFF; margin-top: 24rpx; } .container { padding: 20rpx 32rpx; height: 100%; background: linear-gradient(to bottom, #CAD9F9, #E9F0FF); } /* 导航栏样式 */ .nav_title { display: flex; flex-direction: row; align-items: center; margin-bottom: 45rpx; margin-top: 100rpx; } .nav_text { font-size: 48rpx; font-weight: 400; color: #333333; margin: auto; } /* 用户信息样式 */ .user_info { background: rgba(255, 255, 255, 0.6); } .user_name { font-size: 64rpx; font-weight: 400; color: #333333; } .user_number { display: flex; flex-direction: row; align-items: center; margin-top: 30rpx; } .number { font-size: 48rpx; font-weight: 400; color: #777; } /* 功能列表样式 */ .function_box { font-size: 44rpx; font-weight: normal; color: #333333; } .function_ul { display: flex; flex-direction: row; align-items: center; justify-content: space-between; touch-action: manipulation; } .function_li { display: flex; flex-direction: row; align-items: center; } .function_text { font-size: 36rpx; font-weight: 400; color: #333333; margin-right: 8rpx; } .mt80 { margin-top: 40rpx; } .exit { font-size: 40rpx; color: #333333; text-align: center; display: block; } /* 弹窗样式 */ .mask { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); z-index: 998; transition: opacity 0.3s ease; } .bottom-popup { position: fixed; left: 0; right: 0; bottom: 0; background: #fff; border-top-left-radius: 20rpx; border-top-right-radius: 20rpx; z-index: 999; transition: transform 0.3s ease-out; padding: 30rpx; box-sizing: border-box; transform: translateY(100%); max-height: 70vh; overflow-y: auto; } .popup-show { transform: translateY(0); } .popup-header { display: flex; flex-direction: row; align-items: center; justify-content: center; margin-bottom: 20rpx; position: relative; padding-bottom: 20rpx; border-bottom: 1rpx solid #eee; } .popup-title { text-align: center; font-size: 32rpx; color: #999; } .popup-img { position: absolute; left: 0px; } .popup-list { padding: 10rpx 0; } /* 普通弹窗选项样式 */ .popup-item { text-align: center; padding: 30rpx 0rpx; font-size: 36rpx; color: #333; border-bottom: 1rpx solid #eee; } .popup-item-text { font-size: 36rpx; color: #333; } /* 账号弹窗样式 */ .account-item { display: flex; justify-content: space-between; align-items: center; padding: 25rpx 0; border-bottom: 1rpx solid #eee; } .account-info { flex: 1; cursor: pointer; } .account-name { font-size: 36rpx; color: #333; display: block; } .account-phone { font-size: 28rpx; color: #999; margin-top: 4rpx; } .account-actions { display: flex; align-items: center; } .delete-btn { font-size: 32rpx; color: #ff4d4f; margin-left: 20rpx; cursor: pointer; padding: 8rpx 16rpx; border-radius: 8rpx; background: #fff5f5; } .current-tag { font-size: 28rpx; color: #1890ff; background: #e6f7ff; padding: 4rpx 16rpx; border-radius: 16rpx; } /* GPS 说明样式 */ .popup-detail { border-radius: 8px; opacity: 1; background: #EBF1FF; padding: 12rpx; margin-top: 20rpx; } .popup-text { font-size: 32rpx; font-weight: normal; color: #777777; line-height: 48rpx; } </style>报错16:31:09.756 找不到名称“userNickName”。参考: https://doc.dcloud.net.cn/uni-app-x/uts/compiler-known-issues.html#error18 16:31:09.756 at pages/user/user.uvue:11:31 16:31:09.757 9 | <!-- 用户信息区域 --> 16:31:09.757 10 | <view class="normal_box user_info"> 16:31:09.757 11 | <text class="user_name">{{ userNickName }}</text> 16:31:09.757 | ^ 16:31:09.757 12 | <view class="user_number"> 16:31:09.757 13 | <image class="image_btn mr24" src="/static/user/phone.png" mode="aspectFit"></image>⁠ 16:31:09.757 找不到名称“userPhoneNumber”。参考: https://doc.dcloud.net.cn/uni-app-x/uts/compiler-known-issues.html#error18 16:31:09.757 at pages/user/user.uvue:14:29 16:31:09.757 12 | <view class="user_number"> 16:31:09.757 13 | <image class="image_btn mr24" src="/static/user/phone.png" mode="aspectFit"></image> 16:31:09.757 14 | <text class="number">{{ userPhoneNumber }}</text> 16:31:09.757 | ^ 16:31:09.757 15 | </view> 16:31:09.757 16 | </view>⁠ 16:31:09.757 找不到名称“userNickName”。参考: https://doc.dcloud.net.cn/uni-app-x/uts/compiler-known-issues.html#error18 16:31:09.757 at pages/user/user.uvue:27:37 16:31:09.757 25 | </view> 16:31:09.757 26 | <view class="function_li"> 16:31:09.757 27 | <text class="function_text">{{ userNickName }}</text> 16:31:09.757 | ^ 16:31:09.757 28 | <image class="image_btn" src="/static/user/right.png" mode="aspectFit"></image> 16:31:09.757 29 | </view>⁠ 16:31:09.757 找不到名称“isVoiceChecked”。参考: https://doc.dcloud.net.cn/uni-app-x/uts/compiler-known-issues.html#error18 16:31:09.757 at pages/user/user.uvue:50:24 16:31:09.757 48 | <view class="function_li"> 16:31:09.757 49 | <!-- 修复:直接使用 data 变量,无 this --> 16:31:09.758 50 | <switch :checked="isVoiceChecked" @change="switchChange" /> 16:31:09.758 | ^ 16:31:09.758 51 | </view> 16:31:09.758 52 | </view>⁠ 16:31:09.758 找不到名称“selectedVoice”。参考: https://doc.dcloud.net.cn/uni-app-x/uts/compiler-known-issues.html#error18 16:31:09.758 at pages/user/user.uvue:61:37 16:31:09.758 59 | </view> 16:31:09.758 60 | <view class="function_li"> 16:31:09.758 61 | <text class="function_text">{{ selectedVoice }}</text> 16:31:09.758 | ^ 16:31:09.758 62 | <image class="image_btn" src="/static/user/right.png" mode="aspectFit"></image> 16:31:09.758 63 | </view>⁠ 16:31:09.758 [plugin:uni:app-uts] 编译失败 16:31:09.814 代码编译报错
最新发布
12-02
<template> <view class=""> <!-- <uni-nav-bar :style="{ position: 'fixed', width: '100%', float: 'left', zIndex: ' 10086', height: '44px', marginTop: '-' + titleHei + '44px', paddingTop: titleHei, backgroundColor: 'rgb(50,133,236) ' }" left-icon="left" right-icon="search" color="white" @clickLeft="clickLeftTitle" @clickRight="clickRightTitle" title="进场管理" background-color="rgb(50,133,236)" /> <view class="" :style="{ height: '44px' }"></view> --> <ActionBar :pageInfo="pageInfo" :showSearch="true" @search="handleSearchClick" /> <view class="bodyClass" v-for="(item, index) in infoList" :key="index" v-show="searchClick"> <div class="titleClass"> <uni-list> <uni-section style="font-size: 16px" :title="item.F_ProjectName?item.F_ProjectName:'项目名称'" type="line"></uni-section> </uni-list> </div> <div class="contentClassMiddle"> <view @click="goNext(item.F_Id)"> <div class="conterContent">要求到岗间:{{item.F_PlanEnterDate|timeFilter}}</div> <div class="conterContent flex-row-between"> <span>岗位/专业:{{getOptText(item.F_PostCode,BasePostMajor)}}</span> <text>学历:{{ getOptText(item.F_AreaEdu,AreaEdu)}}</text> </div> <div class="conterContent flex-row-between"> <span>年龄:{{getOptText(item.F_AreaAge,AreaAge)}}</span> <text>需求人数:{{item.F_UserCount}}</text> </div> <div class="conterContent flex-row-between"> <span>职称:{{getOptText(item.F_TechnicalTitle,AreaTechnicalTitle)}}</span> <text>调配人数:{{item.F_UserInCount}}</text> </div> <div class="conterContent flex-row-between"> <span>持证:{{getOptText(item.F_Credentials,AreaCredentials)}}</span> <text>招聘人数:{{item.F_RecruitCount}}</text> </div> </view> <div class="buttonCLassBoFd row-flex" style="margin-top: 4%;"> <span class="buttonCLassBo" style="color:#409EFF;font-size: 16px;" @click="goRetreat(item)"> <l-icon slot="suffix" type='sort'></l-icon> 退场人员 </span> <span class="borderClass"></span> <span class="buttonCLassBo" style="color:orange;font-size: 16px;cursor:pointer;" @click.stop="goPeople(item)"> <l-icon slot="suffix" type='edit'></l-icon> <span style="margin-left: 2%;">待岗人员</span> </span> <span class="borderClass"></span> <!-- <span class="buttonCLassBo" style="color:red;font-size: 16px;cursor:pointer;" @click.stop="goAudit(item)"> <l-icon slot="suffix" type='post'></l-icon> <span style="margin-left: 2%;">发布招聘</span> </span> --> <span class="buttonCLassBo" style="color:red;font-size: 16px;cursor:pointer;" @click.stop="goAudit(item)" v-if="item.F_UserCount > (item.F_UserInCount + item.F_RecruitCount)"> <l-icon slot="suffix" type='post'></l-icon> <span style="margin-left: 2%;">发布招聘</span> </span> <span class="buttonCLassBo" style="color:lightgray;font-size: 16px;cursor:default;" v-else> <l-icon slot="suffix" type='post'></l-icon> <span style="margin-left: 2%;">发布招聘</span> </span> </div> </div> </div> <!-- <div class="contentClassRight" @click="goNext(item.F_Id)"></div> --> </view> <view style="width:100%;clear: both;" v-show="searchClick"> <uni-load-more :status="status"></uni-load-more> </view> <!-- <view style="padding: 6% 6% 0 6%" v-show="!searchClick"> <l-select :range="BasePostMajor" title="岗位专业" placeholder="请选择岗位专业" right v-model="queryJson.F_PostCode" /> <l-select :range="Deps" title="项目名称" placeholder="请选择项目名称" right v-model="queryJson.F_ProjectId" /> <picker mode="date" fields="day" :value="queryJson.F_PlanEnterDate" @change="bindDateChange"> <l-input title="要求到岗间" right v-model="queryJson.F_PlanEnterDate" placeholder="请选择到岗间" /> </picker> <br /> <view class="padding-lr bg-white margin-tb padding-tb"> <l-button class="block" size="lg" color="blue" block @click="handleSearch()">确定</l-button> <br /> <l-button class="block" size="lg" color="red" block @click="cancelCLikck">取消</l-button> </view> </view> --> <view class="side-mask" :class="{'show': sideOpen}" @click="sideOpen = false"></view> <view class="side-filter" :class="{'show': sideOpen}"> <scroll-view scroll-y class="filter-content"> <view class="filter-header"> <text class="filter-title">筛选条件</text> <l-icon type="close" size="36rpx" color="#999" @click="sideOpen = false" class="close-icon" /> </view> <view class="filter-body"> <view class="filter-item"> <l-select :range="BasePostMajor" title="岗位专业" placeholder="请选择岗位专业" right v-model="queryJson.F_PostCode" /> </view> <view class="filter-item"> <l-select :range="Deps" title="项目名称" placeholder="请选择项目名称" right v-model="queryJson.F_ProjectId" /> </view> <view class="filter-item"> <picker mode="date" fields="day" :value="queryJson.F_PlanEnterDate" @change="bindDateChange"> <l-input title="要求到岗间" right v-model="queryJson.F_PlanEnterDate" placeholder="请选择到岗间" /> </picker> </view> <view class="filter-actions"> <l-button class="reset-btn" @click="reset" plain> 重置条件 </l-button> <l-button class="confirm-btn" @click="handleConfirm" type="primary"> 确定筛选 </l-button> </view> </view> </scroll-view> </view> </view> </template> <script> import ActionBar from '@/components/action-bar.vue' export default { components: { ActionBar }, data() { return { infoList: [], searchClick: true, create: '', userId: '', status: "loading", currentPage: 1, size: 10, pageCount: 1, BasePostMajor: [], AreaAge: [], AreaEdu: [], F_TechnicalTitle: [], AreaCredentials: [], defaultQueryJson: {}, queryJson: { F_ByBusinessId: this.$store.state.user.departmentId }, Deps: [], sideOpen: false, pageInfo: '加载中...', searchClick: true, }; }, async onLoad({ type, id }) { const sysInfo = uni.getSystemInfoSync(); this.titleHei = sysInfo.statusBarHeight + 'px'; this.contentHei = this.contentHei + sysInfo.statusBarHeight + 'px'; this.getDataSource("BasePostMajor"); // await this.init(type, id); uni.$on('awaitEtl', function(data) { if (data == 2) { this.getList(); } }) this.defaultQueryJson = { ...this.queryJson } this.getProjects("Deps") this.getList(); this.initOptions() }, onReachBottom() { if (this.currentPage < this.pageCount && this.status !== "loading") { this.status = "loading"; // 开始加载设置状态 this.currentPage++; this.getList(); } else { this.status = "nomore"; } }, onShow() { this.getList(1) }, filters: { statusFilter(v) { if (v == 1) { return "审核中"; } else if (v == 2) { return "已审核"; } else { return "待审核"; } }, timeFilter(v) { if (v) { return v.substring(0, 10); } return "-"; } }, methods: { handleSearchClick() { this.sideOpen = true; }, reset() { this.queryJson = { ...this.defaultQueryJson }; this.getList(1); }, async handleConfirm() { this.sideOpen = false; await this.getList(1); }, bindDateChange: function(e) { this.$set(this.queryJson, 'F_PlanEnterDate', e.detail.value); }, clickLeftTitle() { const pages = getCurrentPages(); // 有可返回的页面则直接返回,uni.navigateBack 默认返回失败之后会自动刷新页面 ,无法继续返回 if (pages.length > 1) { uni.navigateBack(1); return; } else { uni.reLaunch({ url: '/pages/home' }); return; } }, initOptions() { this.getOpts('AreaAge,AreaEdu,AreaTechnicalTitle,CertifcateCategory,AreaCredentials'); }, async init(type, id) { await uni.request({ url: this.apiRoot + '/user/become/getdata', header: this.headers, data: { ...this.auth, data: this.$store.state.user.userId } }).then(([err, res]) => { console.log(err, 'err'); console.log(res, 'res'); }) }, getList(num) { let queryJson = this.queryJson if (num) { this.currentPage = num; } uni.request({ url: this.apiRoot + "/career/enter/postpagelist", header: this.headers, method: "post", data: { ...this.auth, data: { "pagination": { "rows": this.size, "page": this.currentPage, "sidx": "", "sord": "" }, "queryJson": JSON.stringify(queryJson) } } }).then(([err, res]) => { this.status = ""; let result = res.data; if (result.data && result.data.rows) { result.data.rows.map(item => { item.F_OptStatus = item.F_OptStatus == null ? "0" : item.F_OptStatus; }) this.infoList = this.infoList.concat(result.data.rows); // this.infoList.push(...result.data.rows); this.pageCount = result.data.total; this.pageInfo = `共 ${result.data.records} 条,当前 ${result.data.page}/${result.data.total} 页` if (this.currentPage >= this.pageCount) { this.status = "nomore"; } } }) }, clickRightTitle() { this.searchClick = !this.searchClick; }, cancelCLikck() { this.searchClick = true; }, goNext(id) { uni.navigateTo({ url: '../enterPlan/listDetail?id=' + id // url: '../enterPlan/approachPlanDetail?id=' + id }); }, goPlan(id) { }, goPeople(obj) { this.setPageParam(obj); uni.navigateTo({ url: './awaitEtList?id=' + obj.F_Id // url: `./?type=create&id=this.userId` }); }, goRetreat(obj) { this.setPageParam(obj); uni.navigateTo({ url: './retreatEtList?id=' + obj.F_Id }); }, goAudit(item) { uni.navigateTo({ url: './recruitAudit?id=' + item.F_Id }); } } }; </script> <style scoped lang="less"> /* 基础样式 */ .page-container { position: relative; background-color: #f5f7fa; overflow: hidden; padding: 0px; } .bodyClass { min-height: 16vh; float: left; width: 96%; margin-top: 2%; margin-left: 2%; padding: 2%; border: 1px #cccac6 solid; border-radius: 10px; position: relative; .titleClassLeft { height: 20%; width: 10%; float: left; text-align: center; position: relative; .leftImg { display: flex; position: absolute; margin: auto; right: 0; left: 0; top: 0; bottom: 0; background-color: #2086df; height: 80%; width: 20%; } } .titleClass { // height: 20%; width: 100%; margin-left: 2%; // float: right; // line-height: 4vh; } .contentClassLeft { height: 72%; width: 30%; margin-left: 2%; float: left; } .contentClassMiddle { display: grid; width: 86%; margin-left: 4%; margin-top: 2%; float: left; .conterContent { margin-top: 4%; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; overflow: hidden; } .buttonCLassBo { margin: 2%; display: inline-block; width: 45%; text-align: center; } } .contentClassRight { width: 6%; margin-top: 12vh; float: left; width: 12px; height: 12px; background-color: transparent; border-color: #cccac6; border-style: solid; border-width: 2px 2px 0 0; -webkit-transform: rotate(45deg); transform: rotate(45deg); } } .titleRightText { right: 4%; z-index: 2000000000000000; color: #000; } .trapezoid { color: white; font-size: 10px; position: absolute; width: 34px; height: 0; border-right: 26px solid transparent; border-bottom: 25px solid green; border-left: 25px solid transparent; -webkit-transform: rotate(54deg); transform: rotate(46deg); right: -22px; top: 9px; text-align: center; } .trapezoid0 { border-bottom: 25px solid #F95E5A; } .trapezoid1 { border-bottom: 25px solid #FF9900; } .trapezoid2 { border-bottom: 25px solid #409EFF; } .uni-list[data-v-5009d455] { position: static; /deep/.uni-section .uni-section-header[data-v-f7ca1098] { padding: 0; font-size: 16px; font-weight: 700; } } .flex-between { display: flex; justify-content: space-between; } .w80 { width: 80%; margin: 10px auto; } .flex-row { display: flex; clear: both; justify-content: space-around; align-items: center; } .grey-line { height: 16px; width: 1px; background-color: #797979; } .orange-word { color: #f59a23; } .blue-word { color: #409eff; } ::v-deep .uni-list--border-top { height: 0px !important; background-color: transparent !important; border: none !important; } ::v-deep .uni-list--border-bottom { height: 0px !important; background-color: transparent !important; border: none !important; } </style>bug修改
10-17
<!-- 修复后的 videoUpload.vue --> <template> <view class="video-upload-container"> <view v-if="permission === 'E' && !readonly" class="video-upload-area"> <view v-if="!videoUrl" class="upload-placeholder" @click="chooseVideo"> <text class="upload-icon">+</text> <text class="upload-text">点击上传视频</text> </view> <view v-else class="video-preview"> <video :src="getVideoUrl()" :controls="true" :autoplay="false" :show-fullscreen-btn="true" :show-play-btn="true" class="video-player" object-fit="cover" @loadstart="() => console.log('开始加载视频')" @loadeddata="() => console.log('视频数据加载完成')"> </video> <button v-if="!disabled" class="remove-btn" @click="removeVideo">删除视频</button> </view> <!-- <view v-if="isShowTip" class="upload-tip"> <text class="tip-text">支持格式: {{ fileType.join(', ') }} | 大小不超过 {{ fileSize }}MB</text> </view> --> </view> <view v-else class="readonly-video"> <video v-if="videoUrl" :src="getVideoUrl()" :controls="true" :autoplay="false" :show-fullscreen-btn="true" :show-play-btn="true" class="video-player" object-fit="cover" @loadstart="() => console.log('开始加载视频')" @loadeddata="() => console.log('视频数据加载完成')" > </video> <view v-else class="no-video"> <text>未上传视频</text> </view> </view> </view> </template> <script> import config from '../../../common/config'; export default { name: "VideoUpload", props: { field: { type: String, required: true }, videoUrl: { type: String, default: "" }, permission: { type: String, default: "R" }, readonly: { type: Boolean, default: false }, disabled: { type: Boolean, default: false }, uploadFileUrl: { type: String, default: "/base/base/file/upload" }, fileSize: { type: Number, default: 50 }, fileType: { type: Array, default: () => ['video/mp4', 'video/avi', 'video/mov', 'video/wmv', 'video/flv', 'video/mkv'] }, isShowTip: { type: Boolean, default: true }, baseURL: { type: String, default: '' } }, methods: { getVideoUrl() { const url = this.videoUrl; // 如果没有URL,返回空字符串 if (!url) return ''; // 如果URL包含http,则直接返回 if (url.includes('http')) { // 如果URL包含/hvs,则替换为https://oss.0898hq.com/hvs if (url.includes('/hvs')) { return config.imageUrl + url.substring(url.indexOf('/hvs')); } return url; } else { // 修改URL前缀为 https://oss.0898hq.com if (url.startsWith('/hvs')) { return config.imageUrl + url; } // 确保基础URL末尾没有斜杠,路径开头有斜杠 const base = this.baseURL || config.baseUrl; if (url.startsWith('/')) { return base.replace(/\/$/, '') + url; } else { return base.replace(/\/$/, '') + '/' + url; } } }, // 修改 chooseVideo 方法 chooseVideo() { if (this.disabled) return; uni.chooseVideo({ count: 1, sourceType: ['album', 'camera'], compressed: true, maxDuration: 60, success: (res) => { console.log('视频信息', res); // 检查文件格式 const tempFilePath = res.tempFilePath; let fileName = res.name; // 如果没有文件名,从路径中提取 if (!fileName) { fileName = tempFilePath.split('/').pop(); } // 转换为小写进行比较 const fileExt = fileName.split('.').pop().toLowerCase(); console.log('文件扩展名:', fileExt); const supportedFormats = ['mp4', 'mov', 'avi', 'wmv', 'flv', 'mkv']; if (!supportedFormats.includes(fileExt)) { uni.showToast({ title: '不支持的视频格式', icon: 'none' }); return; } this.uploadVideo(res.tempFilePath); }, fail: (err) => { console.error('选择视频失败:', err); uni.showToast({ title: '选择视频失败', icon: 'none' }); } }); }, // 修改 uploadVideo 方法,使其更接近 imageUpload 的处理方式 async uploadVideo(filePath) { try { uni.showLoading({ title: '上传中...' }); // 使用 Promise 包装 uni.uploadFile 以便使用 async/await const uploadResult = await new Promise((resolve, reject) => { uni.uploadFile({ url: config.baseUrl + this.uploadFileUrl, filePath: filePath, name: 'files[0]', formData: { dir: 'video' }, success: (res) => resolve(JSON.parse(res.data)), fail: (err) => reject(err) }); }); if (uploadResult.code === 0 && uploadResult.data && uploadResult.data.length > 0) { const videoInfo = uploadResult.data[0]; const urls = videoInfo.url.split(','); // 取第一个URL并处理 let url = urls[0]; // 处理URL前缀,与 getImageUrl 保持一致 if (url.includes('/hvs')) { url = config.imageUrl + url.substring(url.indexOf('/hvs')); } else if (url.startsWith('/hvs')) { url = config.imageUrl + url; } else { const base = this.baseURL || config.baseUrl; if (url.startsWith('/')) { url = base.replace(/\/$/, '') + url; } else { url = base.replace(/\/$/, '') + '/' + url; } } // 验证并设置视频URL this.validateAndSetVideoUrl(url); } else { throw new Error(uploadResult.msg || '上传失败'); } } catch (error) { console.error('上传失败:', error); uni.showToast({ title: error.message || '上传失败', icon: 'none' }); } finally { uni.hideLoading(); } }, // 验证并设置视频URL validateAndSetVideoUrl(url) { console.log('视频地址:', url); if (!url) { uni.showToast({ title: '视频地址无效', icon: 'none' }); return; } // 检查是否以http/https开头 if (url.startsWith('http') || url.startsWith('https')) { this.$emit('update:videoUrl', url); uni.showToast({ title: '上传成功', icon: 'success' }); } else { uni.showToast({ title: '视频地址格式错误', icon: 'none' }); } }, // 处理视频错误 handleVideoError(e) { console.error('视频加载错误:', e); uni.showToast({ title: '视频加载失败,请检查网络或视频格式', icon: 'none', duration: 3000 }); }, removeVideo() { this.$emit('update:videoUrl', ''); } } } </script> <style scoped> .video-upload-container { width: 100%; } .upload-placeholder { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 200rpx; border: 2rpx dashed #ccc; border-radius: 10rpx; background-color: #f9f9f9; } .upload-icon { font-size: 60rpx; color: #999; } .upload-text { margin-top: 10rpx; color: #999; font-size: 28rpx; } .video-player { width: 100%; height: 300rpx; border-radius: 10rpx; } .video-preview { } .remove-btn { margin-top: 20rpx; background-color: #ff4d4f; color: white; border: none; border-radius: 8rpx; padding: 10rpx 20rpx; font-size: 26rpx; } .upload-tip { margin-top: 15rpx; } .tip-text { color: #999; font-size: 24rpx; } .readonly-video .video-player { width: 100%; height: 300rpx; border-radius: 10rpx; overflow: hidden; } .no-video { padding: 40rpx; text-align: center; color: #999; background-color: #f5f5f5; border-radius: 10rpx; } </style>的.uni-video-cover在手机预览的候是固定在原地的。但是工具预览是正常随页面滚动的
11-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值