@ -1,5 +1,5 @@ |
|||
#Generated by Maven |
|||
#Tue Feb 25 16:56:11 CST 2025 |
|||
#Fri Nov 28 08:06:23 CST 2025 |
|||
version=3.8.9 |
|||
groupId=com.datangMeeting |
|||
artifactId=datang-meeting-admin |
|||
|
|||
@ -1,5 +1,5 @@ |
|||
#Generated by Maven |
|||
#Tue Feb 25 16:55:53 CST 2025 |
|||
#Fri Nov 28 08:06:13 CST 2025 |
|||
version=3.8.9 |
|||
groupId=com.datangMeeting |
|||
artifactId=datang-meeting-common |
|||
|
|||
@ -1,5 +1,5 @@ |
|||
#Generated by Maven |
|||
#Tue Feb 25 16:56:05 CST 2025 |
|||
#Fri Nov 28 08:06:18 CST 2025 |
|||
version=3.8.9 |
|||
groupId=com.datangMeeting |
|||
artifactId=datang-meeting-framework |
|||
|
|||
@ -1,5 +1,5 @@ |
|||
#Generated by Maven |
|||
#Tue Feb 25 16:56:09 CST 2025 |
|||
#Fri Nov 28 08:06:21 CST 2025 |
|||
version=3.8.9 |
|||
groupId=com.datangMeeting |
|||
artifactId=datang-meeting-generator |
|||
|
|||
@ -1,5 +1,5 @@ |
|||
#Generated by Maven |
|||
#Tue Feb 25 16:56:07 CST 2025 |
|||
#Fri Nov 28 08:06:19 CST 2025 |
|||
version=3.8.9 |
|||
groupId=com.datangMeeting |
|||
artifactId=datang-meeting-quartz |
|||
|
|||
@ -1,5 +1,5 @@ |
|||
#Generated by Maven |
|||
#Tue Feb 25 16:55:58 CST 2025 |
|||
#Fri Nov 28 08:06:16 CST 2025 |
|||
version=3.8.9 |
|||
groupId=com.datangMeeting |
|||
artifactId=datang-meeting-system |
|||
|
|||
@ -0,0 +1,22 @@ |
|||
<script> |
|||
export default { |
|||
onLaunch: function() { |
|||
console.log('App Launch') |
|||
// #ifndef H5 |
|||
// 非H5平台 |
|||
// 设置横屏方向 |
|||
plus.screen.lockOrientation('landscape-primary'); |
|||
// #endif |
|||
}, |
|||
onShow: function() { |
|||
console.log('App Show') |
|||
}, |
|||
onHide: function() { |
|||
console.log('App Hide') |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
/*每个页面公共css */ |
|||
</style> |
|||
@ -0,0 +1 @@ |
|||
平板APP |
|||
@ -0,0 +1,32 @@ |
|||
{ |
|||
"version" : "1", |
|||
"prompt" : "template", |
|||
"title" : "服务协议和隐私政策", |
|||
"message" : " 请你务必审慎阅读、充分理解“服务协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/> 你可阅读<a href=\"https://test.tall.wiki/htage2023/client/#/agreement\">《服务协议》</a>和<a href=\"https://test.tall.wiki/htage2023/client/#/privacyPolicy\">《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。", |
|||
"buttonAccept" : "同意并接受", |
|||
"buttonRefuse" : "暂不同意", |
|||
"hrefLoader" : "system|default", |
|||
"backToExit" : "false", |
|||
"second" : { |
|||
"title" : "确认提示", |
|||
"message" : "进入应用前,你需先同意<a href=\"https://test.tall.wiki/htage2023/client/#/agreement\">《服务协议》</a>和<a href=\"https://test.tall.wiki/htage2023/client/#/privacyPolicy\">《隐私政策》</a>,否则将退出应用。", |
|||
"buttonAccept" : "同意并继续", |
|||
"buttonRefuse" : "退出应用" |
|||
}, |
|||
"disagreeMode" : { |
|||
"support" : false, |
|||
"loadNativePlugins" : false, |
|||
"visitorEntry" : true, |
|||
"showAlways" : false |
|||
}, |
|||
"styles" : { |
|||
"backgroundColor" : "#fff", |
|||
"borderRadius" : "5px", |
|||
"title" : { |
|||
"color" : "#000" |
|||
}, |
|||
"buttonAccept" : { |
|||
"color" : "#002582" |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<script> |
|||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || |
|||
CSS.supports('top: constant(a)')) |
|||
document.write( |
|||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + |
|||
(coverSupport ? ', viewport-fit=cover' : '') + '" />') |
|||
</script> |
|||
<title></title> |
|||
<!--preload-links--> |
|||
<!--app-context--> |
|||
</head> |
|||
<body> |
|||
<div id="app"><!--app-html--></div> |
|||
<script type="module" src="/main.js"></script> |
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,22 @@ |
|||
import App from './App' |
|||
|
|||
// #ifndef VUE3
|
|||
import Vue from 'vue' |
|||
import './uni.promisify.adaptor' |
|||
Vue.config.productionTip = false |
|||
App.mpType = 'app' |
|||
const app = new Vue({ |
|||
...App |
|||
}) |
|||
app.$mount() |
|||
// #endif
|
|||
|
|||
// #ifdef VUE3
|
|||
import { createSSRApp } from 'vue' |
|||
export function createApp() { |
|||
const app = createSSRApp(App) |
|||
return { |
|||
app |
|||
} |
|||
} |
|||
// #endif
|
|||
@ -0,0 +1,120 @@ |
|||
{ |
|||
"name" : "神头发电会议系统", |
|||
"appid" : "__UNI__4D0EF3F", |
|||
"description" : "", |
|||
"versionName" : "1.0.0", |
|||
"versionCode" : "100", |
|||
"transformPx" : false, |
|||
/* 5+App特有相关 */ |
|||
"app-plus" : { |
|||
"usingComponents" : true, |
|||
"nvueStyleCompiler" : "uni-app", |
|||
"compilerVersion" : 3, |
|||
"splashscreen" : { |
|||
"alwaysShowBeforeRender" : true, |
|||
"waiting" : true, |
|||
"autoclose" : true, |
|||
"delay" : 0 |
|||
}, |
|||
/* 模块配置 */ |
|||
"modules" : { |
|||
"Record" : {}, |
|||
"Camera" : {}, |
|||
"Barcode" : {} |
|||
}, |
|||
/* 应用发布信息 */ |
|||
"distribute" : { |
|||
/* android打包配置 */ |
|||
"android" : { |
|||
"permissions" : [ |
|||
"<uses-feature android:name=\"android.hardware.camera\"/>", |
|||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>", |
|||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", |
|||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", |
|||
"<uses-permission android:name=\"android.permission.CAMERA\"/>", |
|||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", |
|||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", |
|||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", |
|||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", |
|||
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>", |
|||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", |
|||
"<uses-permission android:name=\"android.permission.PERSISTENT_ACTIVITY\"/>", |
|||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>", |
|||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", |
|||
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>", |
|||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>", |
|||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", |
|||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>" |
|||
], |
|||
"abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ] |
|||
}, |
|||
/* ios打包配置 */ |
|||
"ios" : { |
|||
"dSYMs" : false |
|||
}, |
|||
/* SDK配置 */ |
|||
"sdkConfigs" : { |
|||
"ad" : {} |
|||
}, |
|||
"icons" : { |
|||
"android" : { |
|||
"hdpi" : "unpackage/res/icons/72x72.png", |
|||
"xhdpi" : "unpackage/res/icons/96x96.png", |
|||
"xxhdpi" : "unpackage/res/icons/144x144.png", |
|||
"xxxhdpi" : "unpackage/res/icons/192x192.png" |
|||
}, |
|||
"ios" : { |
|||
"appstore" : "unpackage/res/icons/1024x1024.png", |
|||
"ipad" : { |
|||
"app" : "unpackage/res/icons/76x76.png", |
|||
"app@2x" : "unpackage/res/icons/152x152.png", |
|||
"notification" : "unpackage/res/icons/20x20.png", |
|||
"notification@2x" : "unpackage/res/icons/40x40.png", |
|||
"proapp@2x" : "unpackage/res/icons/167x167.png", |
|||
"settings" : "unpackage/res/icons/29x29.png", |
|||
"settings@2x" : "unpackage/res/icons/58x58.png", |
|||
"spotlight" : "unpackage/res/icons/40x40.png", |
|||
"spotlight@2x" : "unpackage/res/icons/80x80.png" |
|||
}, |
|||
"iphone" : { |
|||
"app@2x" : "unpackage/res/icons/120x120.png", |
|||
"app@3x" : "unpackage/res/icons/180x180.png", |
|||
"notification@2x" : "unpackage/res/icons/40x40.png", |
|||
"notification@3x" : "unpackage/res/icons/60x60.png", |
|||
"settings@2x" : "unpackage/res/icons/58x58.png", |
|||
"settings@3x" : "unpackage/res/icons/87x87.png", |
|||
"spotlight@2x" : "unpackage/res/icons/80x80.png", |
|||
"spotlight@3x" : "unpackage/res/icons/120x120.png" |
|||
} |
|||
} |
|||
}, |
|||
"splashscreen" : { |
|||
"useOriginalMsgbox" : true, |
|||
"androidStyle" : "default" |
|||
} |
|||
} |
|||
}, |
|||
/* 快应用特有相关 */ |
|||
"quickapp" : {}, |
|||
/* 小程序特有相关 */ |
|||
"mp-weixin" : { |
|||
"appid" : "", |
|||
"setting" : { |
|||
"urlCheck" : false |
|||
}, |
|||
"usingComponents" : true |
|||
}, |
|||
"mp-alipay" : { |
|||
"usingComponents" : true |
|||
}, |
|||
"mp-baidu" : { |
|||
"usingComponents" : true |
|||
}, |
|||
"mp-toutiao" : { |
|||
"usingComponents" : true |
|||
}, |
|||
"uniStatistics" : { |
|||
"enable" : false |
|||
}, |
|||
"vueVersion" : "2" |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
{ |
|||
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages |
|||
{ |
|||
"path": "pages/index/index", |
|||
"style": { |
|||
"navigationBarTitleText": "神头发电会议系统", |
|||
"navigationStyle": "custom", |
|||
"app-plus": { |
|||
"titleNView": false //禁用原生导航栏 |
|||
} |
|||
} |
|||
} |
|||
], |
|||
"globalStyle": { |
|||
"navigationBarTextStyle": "black", |
|||
"navigationBarTitleText": "神头发电会议系统", |
|||
"navigationBarBackgroundColor": "#F8F8F8", |
|||
"backgroundColor": "#F8F8F8", |
|||
"pageOrientation": "landscape" |
|||
}, |
|||
"uniIdRouter": {} |
|||
} |
|||
@ -0,0 +1,110 @@ |
|||
<template> |
|||
<view class="container"> |
|||
<web-view :src="src" @message="handlePostMessage"></web-view> |
|||
</view> |
|||
</template> |
|||
<script> |
|||
var wv; |
|||
// #ifdef APP-PLUS |
|||
import permision from '@/utils/wa-permission/permission.js' |
|||
// #endif |
|||
export default { |
|||
data() { |
|||
return { |
|||
src: '', |
|||
} |
|||
}, |
|||
onLoad() { |
|||
this.onReloadWebview() |
|||
}, |
|||
onReady() { |
|||
// #ifdef APP-PLUS |
|||
var currentWebview = this.$scope.$getAppWebview() |
|||
//此对象相当于html5plus里的plus.webview.currentWebview()。在uni-app里vue页面直接使用plus.webview.currentWebview()无效 |
|||
//如果是页面初始化调用时,需要延时一下 |
|||
setTimeout(function() { |
|||
wv = currentWebview.children()[0] |
|||
}, 1000); |
|||
// #endif |
|||
}, |
|||
methods: { |
|||
onReloadWebview() { |
|||
this.src = 'http://10.89.114.11:9001/datang/meeting/client/' |
|||
}, |
|||
// webview向外部发送消息 |
|||
handlePostMessage(e) { |
|||
var data = e.detail.data || [] |
|||
if (data.length) { |
|||
var bridgeParam = data[0] |
|||
// 集中控制bridge |
|||
this.onBridgeHandler(bridgeParam) |
|||
} |
|||
}, |
|||
onBridgeHandler({ |
|||
method, |
|||
param, |
|||
callback |
|||
}) { |
|||
var currentWebview = this.$scope.$getAppWebview() |
|||
wv = currentWebview.children()[0] |
|||
var onAuthHandlerFinished = (result) => { |
|||
wv.evalJS(`${callback}(${result})`); |
|||
} |
|||
if (method === 'camera') { |
|||
this.getCameraAuth(param, onAuthHandlerFinished) |
|||
} |
|||
if (method === 'record') { |
|||
this.getAudioAuth(param, onAuthHandlerFinished) |
|||
} |
|||
}, |
|||
getCameraAuth(param, callback) { |
|||
var result = uni.getAppAuthorizeSetting() |
|||
if (result.cameraAuthorized === 'authorized') { |
|||
// 已获取到权限了 |
|||
callback && callback(1) |
|||
} else { |
|||
permision.requestAndroidPermission('android.permission.CAMERA').then((e) => { |
|||
// 已获取到权限了 |
|||
callback && callback(e) |
|||
}).catch((err) => { |
|||
// 没有获取到权限 |
|||
callback && callback(false) |
|||
// 打开系统设置界面 |
|||
uni.openAppAuthorizeSetting({ |
|||
success(res) { |
|||
console.log('openAppAuthorizeSetting::', res) |
|||
} |
|||
}) |
|||
}) |
|||
} |
|||
}, |
|||
getAudioAuth(param, callback) { |
|||
var result = uni.getAppAuthorizeSetting() |
|||
if (result.microphoneAuthorized === 'authorized') { |
|||
// 已获取到权限了 |
|||
callback && callback(1) |
|||
} else { |
|||
permision.requestAndroidPermission('android.permission.RECORD_AUDIO').then((e) => { |
|||
// 已获取到权限了 |
|||
callback && callback(e) |
|||
}).catch((err) => { |
|||
// 没有获取到权限 |
|||
callback && callback(false) |
|||
// 打开系统设置界面 |
|||
uni.openAppAuthorizeSetting({ |
|||
success(res) { |
|||
console.log('openAppAuthorizeSetting::', res) |
|||
} |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss"> |
|||
.container { |
|||
height: 100vh; |
|||
} |
|||
</style> |
|||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
@ -0,0 +1,10 @@ |
|||
uni.addInterceptor({ |
|||
returnValue (res) { |
|||
if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) { |
|||
return res; |
|||
} |
|||
return new Promise((resolve, reject) => { |
|||
res.then((res) => res[0] ? reject(res[0]) : resolve(res[1])); |
|||
}); |
|||
}, |
|||
}); |
|||
@ -0,0 +1,76 @@ |
|||
/** |
|||
* 这里是uni-app内置的常用样式变量 |
|||
* |
|||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 |
|||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App |
|||
* |
|||
*/ |
|||
|
|||
/** |
|||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 |
|||
* |
|||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 |
|||
*/ |
|||
|
|||
/* 颜色变量 */ |
|||
|
|||
/* 行为相关颜色 */ |
|||
$uni-color-primary: #007aff; |
|||
$uni-color-success: #4cd964; |
|||
$uni-color-warning: #f0ad4e; |
|||
$uni-color-error: #dd524d; |
|||
|
|||
/* 文字基本颜色 */ |
|||
$uni-text-color:#333;//基本色 |
|||
$uni-text-color-inverse:#fff;//反色 |
|||
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息 |
|||
$uni-text-color-placeholder: #808080; |
|||
$uni-text-color-disable:#c0c0c0; |
|||
|
|||
/* 背景颜色 */ |
|||
$uni-bg-color:#ffffff; |
|||
$uni-bg-color-grey:#f8f8f8; |
|||
$uni-bg-color-hover:#f1f1f1;//点击状态颜色 |
|||
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色 |
|||
|
|||
/* 边框颜色 */ |
|||
$uni-border-color:#c8c7cc; |
|||
|
|||
/* 尺寸变量 */ |
|||
|
|||
/* 文字尺寸 */ |
|||
$uni-font-size-sm:12px; |
|||
$uni-font-size-base:14px; |
|||
$uni-font-size-lg:16; |
|||
|
|||
/* 图片尺寸 */ |
|||
$uni-img-size-sm:20px; |
|||
$uni-img-size-base:26px; |
|||
$uni-img-size-lg:40px; |
|||
|
|||
/* Border Radius */ |
|||
$uni-border-radius-sm: 2px; |
|||
$uni-border-radius-base: 3px; |
|||
$uni-border-radius-lg: 6px; |
|||
$uni-border-radius-circle: 50%; |
|||
|
|||
/* 水平间距 */ |
|||
$uni-spacing-row-sm: 5px; |
|||
$uni-spacing-row-base: 10px; |
|||
$uni-spacing-row-lg: 15px; |
|||
|
|||
/* 垂直间距 */ |
|||
$uni-spacing-col-sm: 4px; |
|||
$uni-spacing-col-base: 8px; |
|||
$uni-spacing-col-lg: 12px; |
|||
|
|||
/* 透明度 */ |
|||
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 |
|||
|
|||
/* 文章场景相关 */ |
|||
$uni-color-title: #2C405A; // 文章标题颜色 |
|||
$uni-font-size-title:20px; |
|||
$uni-color-subtitle: #555555; // 二级标题颜色 |
|||
$uni-font-size-subtitle:26px; |
|||
$uni-color-paragraph: #3F536E; // 文章段落颜色 |
|||
$uni-font-size-paragraph:15px; |
|||
@ -0,0 +1 @@ |
|||
https://app.liuyingyong.cn/build/download/7924ad90-1b2a-11f0-b490-41f6f524206e |
|||
@ -0,0 +1,4 @@ |
|||
andrCertfile=D:/公司项目/HBuilderX/plugins/app-safe-pack/Test.keystore |
|||
andrCertAlias=android |
|||
andrCertPass=ep/Tdjka4Y7WYqDB6/S7dw== |
|||
storePassword=ep/Tdjka4Y7WYqDB6/S7dw== |
|||
@ -0,0 +1,4 @@ |
|||
[General] |
|||
andrCertfile=package.keystore |
|||
andrCertAlias=__UNI__4D0EF3F |
|||
andrCertPass="jZ3sIvAof+ZIPDHsK0/UhQ==" |
|||
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,25 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="zh-CN"> |
|||
|
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<script> |
|||
var __UniViewStartTime__ = Date.now(); |
|||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || |
|||
CSS.supports('top: constant(a)')) |
|||
document.write( |
|||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + |
|||
(coverSupport ? ', viewport-fit=cover' : '') + '" />') |
|||
</script> |
|||
<title>View</title> |
|||
<link rel="stylesheet" href="view.css" /> |
|||
</head> |
|||
|
|||
<body> |
|||
<div id="app"></div> |
|||
<script src="__uniappes6.js"></script> |
|||
<script src="view.umd.min.js"></script> |
|||
<script src="app-view.js"></script> |
|||
</body> |
|||
|
|||
</html> |
|||
@ -0,0 +1,32 @@ |
|||
{ |
|||
"version" : "1", |
|||
"prompt" : "template", |
|||
"title" : "服务协议和隐私政策", |
|||
"message" : " 请你务必审慎阅读、充分理解“服务协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/> 你可阅读<a href=\"https://test.tall.wiki/htage2023/client/#/agreement\">《服务协议》</a>和<a href=\"https://test.tall.wiki/htage2023/client/#/privacyPolicy\">《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。", |
|||
"buttonAccept" : "同意并接受", |
|||
"buttonRefuse" : "暂不同意", |
|||
"hrefLoader" : "system|default", |
|||
"backToExit" : "false", |
|||
"second" : { |
|||
"title" : "确认提示", |
|||
"message" : "进入应用前,你需先同意<a href=\"https://test.tall.wiki/htage2023/client/#/agreement\">《服务协议》</a>和<a href=\"https://test.tall.wiki/htage2023/client/#/privacyPolicy\">《隐私政策》</a>,否则将退出应用。", |
|||
"buttonAccept" : "同意并继续", |
|||
"buttonRefuse" : "退出应用" |
|||
}, |
|||
"disagreeMode" : { |
|||
"support" : false, |
|||
"loadNativePlugins" : false, |
|||
"visitorEntry" : true, |
|||
"showAlways" : false |
|||
}, |
|||
"styles" : { |
|||
"backgroundColor" : "#fff", |
|||
"borderRadius" : "5px", |
|||
"title" : { |
|||
"color" : "#000" |
|||
}, |
|||
"buttonAccept" : { |
|||
"color" : "#002582" |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
|
|||
var isReady=false;var onReadyCallbacks=[]; |
|||
var isServiceReady=false;var onServiceReadyCallbacks=[]; |
|||
var __uniConfig = {"pages":["pages/index/index"],"window":{"navigationBarTextStyle":"black","navigationBarTitleText":"神头发电会议系统","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":"#F8F8F8","pageOrientation":"landscape"},"darkmode":false,"nvueCompiler":"uni-app","nvueStyleCompiler":"uni-app","renderer":"auto","splashscreen":{"alwaysShowBeforeRender":true,"autoclose":false},"appname":"神头发电会议系统","compilerVersion":"4.57","entryPagePath":"pages/index/index","networkTimeout":{"request":60000,"connectSocket":60000,"uploadFile":60000,"downloadFile":60000}}; |
|||
var __uniRoutes = [{"path":"/pages/index/index","meta":{"isQuit":true},"window":{"navigationBarTitleText":"神头发电会议系统","navigationStyle":"custom","titleNView":false}}]; |
|||
__uniConfig.onReady=function(callback){if(__uniConfig.ready){callback()}else{onReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"ready",{get:function(){return isReady},set:function(val){isReady=val;if(!isReady){return}const callbacks=onReadyCallbacks.slice(0);onReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}}); |
|||
__uniConfig.onServiceReady=function(callback){if(__uniConfig.serviceReady){callback()}else{onServiceReadyCallbacks.push(callback)}};Object.defineProperty(__uniConfig,"serviceReady",{get:function(){return isServiceReady},set:function(val){isServiceReady=val;if(!isServiceReady){return}const callbacks=onServiceReadyCallbacks.slice(0);onServiceReadyCallbacks.length=0;callbacks.forEach(function(callback){callback()})}}); |
|||
service.register("uni-app-config",{create(a,b,c){if(!__uniConfig.viewport){var d=b.weex.config.env.scale,e=b.weex.config.env.deviceWidth,f=Math.ceil(e/d);Object.assign(__uniConfig,{viewport:f,defaultFontSize:Math.round(f/20)})}return{instance:{__uniConfig:__uniConfig,__uniRoutes:__uniRoutes,global:void 0,window:void 0,document:void 0,frames:void 0,self:void 0,location:void 0,navigator:void 0,localStorage:void 0,history:void 0,Caches:void 0,screen:void 0,alert:void 0,confirm:void 0,prompt:void 0,fetch:void 0,XMLHttpRequest:void 0,WebSocket:void 0,webkit:void 0,print:void 0}}}}); |
|||
@ -0,0 +1 @@ |
|||
(function(e){function r(r){for(var n,l,i=r[0],p=r[1],a=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in p)Object.prototype.hasOwnProperty.call(p,n)&&(e[n]=p[n]);f&&f(r);while(s.length)s.shift()();return u.push.apply(u,a||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var p=t[i];0!==o[p]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={"app-config":0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"===typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e["default"]}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this["webpackJsonp"]=this["webpackJsonp"]||[],p=i.push.bind(i);i.push=r,i=i.slice();for(var a=0;a<i.length;a++)r(i[a]);var f=p;t()})([]); |
|||
@ -0,0 +1 @@ |
|||
{"@platforms":["android","iPhone","iPad"],"id":"__UNI__4D0EF3F","name":"神头发电会议系统","version":{"name":"1.0.0","code":"100"},"description":"","launch_path":"__uniappview.html","developer":{"name":"","email":"","url":""},"permissions":{"Record":{},"Camera":{},"Barcode":{},"UniNView":{"description":"UniNView原生渲染"}},"plus":{"useragent":{"value":"uni-app","concatenate":true},"splashscreen":{"autoclose":true,"delay":0,"target":"id:1","waiting":true},"popGesture":"close","launchwebview":{"render":"always","id":"1","kernel":"WKWebview"},"statusbar":{"immersed":"supportedDevice","style":"dark","background":"#F8F8F8"},"usingComponents":true,"nvueStyleCompiler":"uni-app","compilerVersion":3,"distribute":{"icons":{"android":{"hdpi":"icon-android-hdpi.png","xhdpi":"icon-android-xhdpi.png","xxhdpi":"icon-android-xxhdpi.png","xxxhdpi":"icon-android-xxxhdpi.png"},"ios":{"appstore":"unpackage/res/icons/1024x1024.png","ipad":{"app":"unpackage/res/icons/76x76.png","app@2x":"unpackage/res/icons/152x152.png","notification":"unpackage/res/icons/20x20.png","notification@2x":"unpackage/res/icons/40x40.png","proapp@2x":"unpackage/res/icons/167x167.png","settings":"unpackage/res/icons/29x29.png","settings@2x":"unpackage/res/icons/58x58.png","spotlight":"unpackage/res/icons/40x40.png","spotlight@2x":"unpackage/res/icons/80x80.png"},"iphone":{"app@2x":"unpackage/res/icons/120x120.png","app@3x":"unpackage/res/icons/180x180.png","notification@2x":"unpackage/res/icons/40x40.png","notification@3x":"unpackage/res/icons/60x60.png","settings@2x":"unpackage/res/icons/58x58.png","settings@3x":"unpackage/res/icons/87x87.png","spotlight@2x":"unpackage/res/icons/80x80.png","spotlight@3x":"unpackage/res/icons/120x120.png"},"prerendered":"false"}},"splashscreen":{"useOriginalMsgbox":true,"androidStyle":"default"},"google":{"abiFilters":["armeabi-v7a","arm64-v8a","x86"],"permissions":["<uses-feature android:name=\"android.hardware.camera\"/>","<uses-feature android:name=\"android.hardware.camera.autofocus\"/>","<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.CAMERA\"/>","<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>","<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>","<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>","<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>","<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>","<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>","<uses-permission android:name=\"android.permission.PERSISTENT_ACTIVITY\"/>","<uses-permission android:name=\"android.permission.READ_LOGS\"/>","<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>","<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>","<uses-permission android:name=\"android.permission.VIBRATE\"/>","<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>","<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"],"packagename":"uni.UNI4D0EF3F","custompermissions":true},"apple":{"dSYMs":false,"devices":"universal"},"plugins":{"ad":{},"audio":{"mp3":{"description":"Android平台录音支持MP3格式文件"}}},"orientation":"portrait-primary"},"uniStatistics":{"enable":false},"allowsInlineMediaPlayback":true,"uni-app":{"compilerVersion":"4.57","control":"uni-v3","nvueCompiler":"uni-app","renderer":"auto","nvue":{"flex-direction":"column"},"nvueLaunchMode":"normal"},"launch_path":"__uniappview.html","adid":"128096300305"},"screenOrientation":["landscape-primary","landscape-secondary"]} |
|||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
@ -0,0 +1 @@ |
|||
forceInstall |
|||
|
After Width: | Height: | Size: 207 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 952 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
@ -0,0 +1,272 @@ |
|||
/** |
|||
* 本模块封装了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 |
|||
} |
|||
@ -0,0 +1,488 @@ |
|||
<<<<<<< HEAD |
|||
======= |
|||
import Sortable from "sortablejs"; |
|||
import { insertNodeAt, camelize, console, removeNode } from "./util/helper"; |
|||
|
|||
function buildAttribute(object, propName, value) { |
|||
if (value === undefined) { |
|||
return object; |
|||
} |
|||
object = object || {}; |
|||
object[propName] = value; |
|||
return object; |
|||
} |
|||
|
|||
function computeVmIndex(vnodes, element) { |
|||
return vnodes.map(elt => elt.elm).indexOf(element); |
|||
} |
|||
|
|||
function computeIndexes(slots, children, isTransition, footerOffset) { |
|||
if (!slots) { |
|||
return []; |
|||
} |
|||
|
|||
const elmFromNodes = slots.map(elt => elt.elm); |
|||
const footerIndex = children.length - footerOffset; |
|||
const rawIndexes = [...children].map((elt, idx) => |
|||
idx >= footerIndex ? elmFromNodes.length : elmFromNodes.indexOf(elt) |
|||
); |
|||
return isTransition ? rawIndexes.filter(ind => ind !== -1) : rawIndexes; |
|||
} |
|||
|
|||
function emit(evtName, evtData) { |
|||
this.$nextTick(() => this.$emit(evtName.toLowerCase(), evtData)); |
|||
} |
|||
|
|||
function delegateAndEmit(evtName) { |
|||
return evtData => { |
|||
if (this.realList !== null) { |
|||
this["onDrag" + evtName](evtData); |
|||
} |
|||
emit.call(this, evtName, evtData); |
|||
}; |
|||
} |
|||
|
|||
function isTransitionName(name) { |
|||
return ["transition-group", "TransitionGroup"].includes(name); |
|||
} |
|||
|
|||
function isTransition(slots) { |
|||
if (!slots || slots.length !== 1) { |
|||
return false; |
|||
} |
|||
const [{ componentOptions }] = slots; |
|||
if (!componentOptions) { |
|||
return false; |
|||
} |
|||
return isTransitionName(componentOptions.tag); |
|||
} |
|||
|
|||
function getSlot(slot, scopedSlot, key) { |
|||
return slot[key] || (scopedSlot[key] ? scopedSlot[key]() : undefined); |
|||
} |
|||
|
|||
function computeChildrenAndOffsets(children, slot, scopedSlot) { |
|||
let headerOffset = 0; |
|||
let footerOffset = 0; |
|||
const header = getSlot(slot, scopedSlot, "header"); |
|||
if (header) { |
|||
headerOffset = header.length; |
|||
children = children ? [...header, ...children] : [...header]; |
|||
} |
|||
const footer = getSlot(slot, scopedSlot, "footer"); |
|||
if (footer) { |
|||
footerOffset = footer.length; |
|||
children = children ? [...children, ...footer] : [...footer]; |
|||
} |
|||
return { children, headerOffset, footerOffset }; |
|||
} |
|||
|
|||
function getComponentAttributes($attrs, componentData) { |
|||
let attributes = null; |
|||
const update = (name, value) => { |
|||
attributes = buildAttribute(attributes, name, value); |
|||
}; |
|||
const attrs = Object.keys($attrs) |
|||
.filter(key => key === "id" || key.startsWith("data-")) |
|||
.reduce((res, key) => { |
|||
res[key] = $attrs[key]; |
|||
return res; |
|||
}, {}); |
|||
update("attrs", attrs); |
|||
|
|||
if (!componentData) { |
|||
return attributes; |
|||
} |
|||
const { on, props, attrs: componentDataAttrs } = componentData; |
|||
update("on", on); |
|||
update("props", props); |
|||
Object.assign(attributes.attrs, componentDataAttrs); |
|||
return attributes; |
|||
} |
|||
|
|||
const eventsListened = ["Start", "Add", "Remove", "Update", "End"]; |
|||
const eventsToEmit = ["Choose", "Unchoose", "Sort", "Filter", "Clone"]; |
|||
const readonlyProperties = ["Move", ...eventsListened, ...eventsToEmit].map( |
|||
evt => "on" + evt |
|||
); |
|||
var draggingElement = null; |
|||
|
|||
const props = { |
|||
options: Object, |
|||
list: { |
|||
type: Array, |
|||
required: false, |
|||
default: null |
|||
}, |
|||
value: { |
|||
type: Array, |
|||
required: false, |
|||
default: null |
|||
}, |
|||
noTransitionOnDrag: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
clone: { |
|||
type: Function, |
|||
default: original => { |
|||
return original; |
|||
} |
|||
}, |
|||
element: { |
|||
type: String, |
|||
default: "div" |
|||
}, |
|||
tag: { |
|||
type: String, |
|||
default: null |
|||
}, |
|||
move: { |
|||
type: Function, |
|||
default: null |
|||
}, |
|||
componentData: { |
|||
type: Object, |
|||
required: false, |
|||
default: null |
|||
} |
|||
}; |
|||
|
|||
const draggableComponent = { |
|||
name: "draggable", |
|||
|
|||
inheritAttrs: false, |
|||
|
|||
props, |
|||
|
|||
data() { |
|||
return { |
|||
transitionMode: false, |
|||
noneFunctionalComponentMode: false |
|||
}; |
|||
}, |
|||
|
|||
render(h) { |
|||
const slots = this.$slots.default; |
|||
this.transitionMode = isTransition(slots); |
|||
const { children, headerOffset, footerOffset } = computeChildrenAndOffsets( |
|||
slots, |
|||
this.$slots, |
|||
this.$scopedSlots |
|||
); |
|||
this.headerOffset = headerOffset; |
|||
this.footerOffset = footerOffset; |
|||
const attributes = getComponentAttributes(this.$attrs, this.componentData); |
|||
return h(this.getTag(), attributes, children); |
|||
}, |
|||
|
|||
created() { |
|||
if (this.list !== null && this.value !== null) { |
|||
console.error( |
|||
"Value and list props are mutually exclusive! Please set one or another." |
|||
); |
|||
} |
|||
|
|||
if (this.element !== "div") { |
|||
console.warn( |
|||
"Element props is deprecated please use tag props instead. See https://github.com/SortableJS/Vue.Draggable/blob/master/documentation/migrate.md#element-props" |
|||
); |
|||
} |
|||
|
|||
if (this.options !== undefined) { |
|||
console.warn( |
|||
"Options props is deprecated, add sortable options directly as vue.draggable item, or use v-bind. See https://github.com/SortableJS/Vue.Draggable/blob/master/documentation/migrate.md#options-props" |
|||
); |
|||
} |
|||
}, |
|||
|
|||
mounted() { |
|||
this.noneFunctionalComponentMode = |
|||
this.getTag().toLowerCase() !== this.$el.nodeName.toLowerCase() && |
|||
!this.getIsFunctional(); |
|||
if (this.noneFunctionalComponentMode && this.transitionMode) { |
|||
throw new Error( |
|||
`Transition-group inside component is not supported. Please alter tag value or remove transition-group. Current tag value: ${this.getTag()}` |
|||
); |
|||
} |
|||
const optionsAdded = {}; |
|||
eventsListened.forEach(elt => { |
|||
optionsAdded["on" + elt] = delegateAndEmit.call(this, elt); |
|||
}); |
|||
|
|||
eventsToEmit.forEach(elt => { |
|||
optionsAdded["on" + elt] = emit.bind(this, elt); |
|||
}); |
|||
|
|||
const attributes = Object.keys(this.$attrs).reduce((res, key) => { |
|||
res[camelize(key)] = this.$attrs[key]; |
|||
return res; |
|||
}, {}); |
|||
|
|||
const options = Object.assign({}, this.options, attributes, optionsAdded, { |
|||
onMove: (evt, originalEvent) => { |
|||
return this.onDragMove(evt, originalEvent); |
|||
} |
|||
}); |
|||
!("draggable" in options) && (options.draggable = ">*"); |
|||
this._sortable = new Sortable(this.rootContainer, options); |
|||
this.computeIndexes(); |
|||
}, |
|||
|
|||
beforeDestroy() { |
|||
if (this._sortable !== undefined) this._sortable.destroy(); |
|||
}, |
|||
|
|||
computed: { |
|||
rootContainer() { |
|||
return this.transitionMode ? this.$el.children[0] : this.$el; |
|||
}, |
|||
|
|||
realList() { |
|||
return this.list ? this.list : this.value; |
|||
} |
|||
}, |
|||
|
|||
watch: { |
|||
options: { |
|||
handler(newOptionValue) { |
|||
this.updateOptions(newOptionValue); |
|||
}, |
|||
deep: true |
|||
}, |
|||
|
|||
$attrs: { |
|||
handler(newOptionValue) { |
|||
this.updateOptions(newOptionValue); |
|||
}, |
|||
deep: true |
|||
}, |
|||
|
|||
realList() { |
|||
this.computeIndexes(); |
|||
} |
|||
}, |
|||
|
|||
methods: { |
|||
getIsFunctional() { |
|||
const { fnOptions } = this._vnode; |
|||
return fnOptions && fnOptions.functional; |
|||
}, |
|||
|
|||
getTag() { |
|||
return this.tag || this.element; |
|||
}, |
|||
|
|||
updateOptions(newOptionValue) { |
|||
for (var property in newOptionValue) { |
|||
const value = camelize(property); |
|||
if (readonlyProperties.indexOf(value) === -1) { |
|||
this._sortable.option(value, newOptionValue[property]); |
|||
} |
|||
} |
|||
}, |
|||
|
|||
getChildrenNodes() { |
|||
if (this.noneFunctionalComponentMode) { |
|||
return this.$children[0].$slots.default; |
|||
} |
|||
const rawNodes = this.$slots.default; |
|||
return this.transitionMode ? rawNodes[0].child.$slots.default : rawNodes; |
|||
}, |
|||
|
|||
computeIndexes() { |
|||
this.$nextTick(() => { |
|||
this.visibleIndexes = computeIndexes( |
|||
this.getChildrenNodes(), |
|||
this.rootContainer.children, |
|||
this.transitionMode, |
|||
this.footerOffset |
|||
); |
|||
}); |
|||
}, |
|||
|
|||
getUnderlyingVm(htmlElt) { |
|||
const index = computeVmIndex(this.getChildrenNodes() || [], htmlElt); |
|||
if (index === -1) { |
|||
//Edge case during move callback: related element might be
|
|||
//an element different from collection
|
|||
return null; |
|||
} |
|||
const element = this.realList[index]; |
|||
return { index, element }; |
|||
}, |
|||
|
|||
getUnderlyingPotencialDraggableComponent({ __vue__: vue }) { |
|||
if ( |
|||
!vue || |
|||
!vue.$options || |
|||
!isTransitionName(vue.$options._componentTag) |
|||
) { |
|||
if ( |
|||
!("realList" in vue) && |
|||
vue.$children.length === 1 && |
|||
"realList" in vue.$children[0] |
|||
) |
|||
return vue.$children[0]; |
|||
|
|||
return vue; |
|||
} |
|||
return vue.$parent; |
|||
}, |
|||
|
|||
emitChanges(evt) { |
|||
this.$nextTick(() => { |
|||
this.$emit("change", evt); |
|||
}); |
|||
}, |
|||
|
|||
alterList(onList) { |
|||
if (this.list) { |
|||
onList(this.list); |
|||
return; |
|||
} |
|||
const newList = [...this.value]; |
|||
onList(newList); |
|||
this.$emit("input", newList); |
|||
}, |
|||
|
|||
spliceList() { |
|||
const spliceList = list => list.splice(...arguments); |
|||
this.alterList(spliceList); |
|||
}, |
|||
|
|||
updatePosition(oldIndex, newIndex) { |
|||
const updatePosition = list => |
|||
list.splice(newIndex, 0, list.splice(oldIndex, 1)[0]); |
|||
this.alterList(updatePosition); |
|||
}, |
|||
|
|||
getRelatedContextFromMoveEvent({ to, related }) { |
|||
const component = this.getUnderlyingPotencialDraggableComponent(to); |
|||
if (!component) { |
|||
return { component }; |
|||
} |
|||
const list = component.realList; |
|||
const context = { list, component }; |
|||
if (to !== related && list && component.getUnderlyingVm) { |
|||
const destination = component.getUnderlyingVm(related); |
|||
if (destination) { |
|||
return Object.assign(destination, context); |
|||
} |
|||
} |
|||
return context; |
|||
}, |
|||
|
|||
getVmIndex(domIndex) { |
|||
const indexes = this.visibleIndexes; |
|||
const numberIndexes = indexes.length; |
|||
return domIndex > numberIndexes - 1 ? numberIndexes : indexes[domIndex]; |
|||
}, |
|||
|
|||
getComponent() { |
|||
return this.$slots.default[0].componentInstance; |
|||
}, |
|||
|
|||
resetTransitionData(index) { |
|||
if (!this.noTransitionOnDrag || !this.transitionMode) { |
|||
return; |
|||
} |
|||
var nodes = this.getChildrenNodes(); |
|||
nodes[index].data = null; |
|||
const transitionContainer = this.getComponent(); |
|||
transitionContainer.children = []; |
|||
transitionContainer.kept = undefined; |
|||
}, |
|||
|
|||
onDragStart(evt) { |
|||
this.context = this.getUnderlyingVm(evt.item); |
|||
evt.item._underlying_vm_ = this.clone(this.context.element); |
|||
draggingElement = evt.item; |
|||
}, |
|||
|
|||
onDragAdd(evt) { |
|||
const element = evt.item._underlying_vm_; |
|||
if (element === undefined) { |
|||
return; |
|||
} |
|||
removeNode(evt.item); |
|||
const newIndex = this.getVmIndex(evt.newIndex); |
|||
this.spliceList(newIndex, 0, element); |
|||
this.computeIndexes(); |
|||
const added = { element, newIndex }; |
|||
this.emitChanges({ added }); |
|||
}, |
|||
|
|||
onDragRemove(evt) { |
|||
insertNodeAt(this.rootContainer, evt.item, evt.oldIndex); |
|||
if (evt.pullMode === "clone") { |
|||
removeNode(evt.clone); |
|||
return; |
|||
} |
|||
const oldIndex = this.context.index; |
|||
this.spliceList(oldIndex, 1); |
|||
const removed = { element: this.context.element, oldIndex }; |
|||
this.resetTransitionData(oldIndex); |
|||
this.emitChanges({ removed }); |
|||
}, |
|||
|
|||
onDragUpdate(evt) { |
|||
removeNode(evt.item); |
|||
insertNodeAt(evt.from, evt.item, evt.oldIndex); |
|||
const oldIndex = this.context.index; |
|||
const newIndex = this.getVmIndex(evt.newIndex); |
|||
this.updatePosition(oldIndex, newIndex); |
|||
const moved = { element: this.context.element, oldIndex, newIndex }; |
|||
this.emitChanges({ moved }); |
|||
}, |
|||
|
|||
updateProperty(evt, propertyName) { |
|||
evt.hasOwnProperty(propertyName) && |
|||
(evt[propertyName] += this.headerOffset); |
|||
}, |
|||
|
|||
computeFutureIndex(relatedContext, evt) { |
|||
if (!relatedContext.element) { |
|||
return 0; |
|||
} |
|||
const domChildren = [...evt.to.children].filter( |
|||
el => el.style["display"] !== "none" |
|||
); |
|||
const currentDOMIndex = domChildren.indexOf(evt.related); |
|||
const currentIndex = relatedContext.component.getVmIndex(currentDOMIndex); |
|||
const draggedInList = domChildren.indexOf(draggingElement) !== -1; |
|||
return draggedInList || !evt.willInsertAfter |
|||
? currentIndex |
|||
: currentIndex + 1; |
|||
}, |
|||
|
|||
onDragMove(evt, originalEvent) { |
|||
const onMove = this.move; |
|||
if (!onMove || !this.realList) { |
|||
return true; |
|||
} |
|||
|
|||
const relatedContext = this.getRelatedContextFromMoveEvent(evt); |
|||
const draggedContext = this.context; |
|||
const futureIndex = this.computeFutureIndex(relatedContext, evt); |
|||
Object.assign(draggedContext, { futureIndex }); |
|||
const sendEvt = Object.assign({}, evt, { |
|||
relatedContext, |
|||
draggedContext |
|||
}); |
|||
return onMove(sendEvt, originalEvent); |
|||
}, |
|||
|
|||
onDragEnd() { |
|||
this.computeIndexes(); |
|||
draggingElement = null; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
if (typeof window !== "undefined" && "Vue" in window) { |
|||
window.Vue.component("draggable", draggableComponent); |
|||
} |
|||
|
|||
export default draggableComponent; |
|||
>>>>>>> fb3b4fc780fb389b9972fb75a2a499f29694144b |
|||
@ -1,302 +1,322 @@ |
|||
<template> |
|||
<view class="box" style="position: relative;"> |
|||
<!-- <image class="back" src='../../imgs/back.png' mode="widthFix" @click="handleBack"></image> --> |
|||
<image class="logo" src='../../imgs/logo.png' mode="widthFix" ></image> |
|||
<view class="box-cent"> |
|||
<view class="box-cent1"> |
|||
<view class="view-pdf"> |
|||
<pdf ref="pdf" :page="pageNum" @progress="loadedRatio = $event" @page-loaded="pageLoaded($event)" |
|||
@num-pages="pageTotalNum=$event" @error="pdfError($event)" @link-clicked="page = $event" |
|||
:src="filePdfUrl"> |
|||
</pdf> |
|||
</view> |
|||
</view> |
|||
<u-modal v-if="show" :show="show" @cancel="show = false" :showCancelButton="true" content='是否确认退出登录?' @confirm="handleOut"></u-modal> |
|||
</view> |
|||
<!-- 底部背景图 --> |
|||
<view class="view-backimg"> |
|||
<view class="view-backimg-top"></view> |
|||
<!-- <view class="view-backimg-bottom"></view> --> |
|||
</view> |
|||
<div class="tools"> |
|||
<view style="width:50vw;display: flex;margin: auto;"> |
|||
<button :theme="'default'" type="submit" @click.stop="prePage" class="mr10"> |
|||
上一页 |
|||
</button> |
|||
<div class="page">{{pageNum}}/{{pageTotalNum}}</div> |
|||
<button :theme="'default'" type="submit" @click.stop="nextPage" class="mr10"> |
|||
下一页 |
|||
</button> |
|||
</view> |
|||
</div> |
|||
<!-- 头像 - 头像 --> |
|||
<view class="avatarobx"> |
|||
<view class="name">{{userName}}</view> |
|||
<image @click='handleBack' class="avatar" src='../../imgs/arrow-left.png' mode="widthFix"></image> |
|||
<image @click="show = true" class="avatar" src='../../imgs/out.png' mode="widthFix"></image> |
|||
</view> |
|||
</view> |
|||
<view class="box" style="position: relative"> |
|||
<image class="logo" src="../../imgs/logo.png" mode="widthFix"></image> |
|||
<view class="box-cent"> |
|||
<view class="box-cent1"> |
|||
<view class="view-pdf"> |
|||
<pdf |
|||
v-for="i in loadedPages" |
|||
:key="i" |
|||
:src="filePdfUrl" |
|||
:page="i" |
|||
></pdf> |
|||
</view> |
|||
</view> |
|||
<u-modal |
|||
v-if="show" |
|||
:show="show" |
|||
@cancel="show = false" |
|||
:showCancelButton="true" |
|||
content="是否确认退出登录?" |
|||
@confirm="handleOut" |
|||
></u-modal> |
|||
</view> |
|||
<view class="view-backimg"> |
|||
<view class="view-backimg-top"></view> |
|||
</view> |
|||
<view class="avatarobx"> |
|||
<view class="name">{{ userName }}</view> |
|||
<image |
|||
@click="handleBack" |
|||
class="avatar" |
|||
src="../../imgs/arrow-left.png" |
|||
mode="widthFix" |
|||
></image> |
|||
<image |
|||
@click="show = true" |
|||
class="avatar" |
|||
src="../../imgs/out.png" |
|||
mode="widthFix" |
|||
></image> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import pdf from 'vue-pdf' |
|||
export default { |
|||
name: 'MeetingList', |
|||
props: ['infos'], |
|||
components: { |
|||
pdf |
|||
}, |
|||
data() { |
|||
return { |
|||
pageNum: 1, |
|||
pageTotalNum: 1, |
|||
// 加载进度 |
|||
loadedRatio: 0, |
|||
curPageNum: 0, |
|||
filePdfUrl: '', |
|||
userName: uni.getStorageSync("userName"), |
|||
show: false, |
|||
detailsId:'', |
|||
}; |
|||
}, |
|||
created() { |
|||
let routes = getCurrentPages(); // 获取当前打开过的页面路由数组 |
|||
let curParam = routes[routes.length - 1].options; //获取路由参数 |
|||
this.detailsId = curParam.detailsId |
|||
console.log('this.detailsId ',this.detailsId) |
|||
this.filePdfUrl = curParam.filePdfUrl |
|||
}, |
|||
methods: { |
|||
// logo 回到首页 |
|||
handleBack() { |
|||
uni.navigateTo({ |
|||
url: `/pages/index/details?id=${this.detailsId}`, |
|||
}); |
|||
// uni.navigateBack({ |
|||
// delta: 1 |
|||
// }); |
|||
}, |
|||
// 退出登录 |
|||
handleOut() { |
|||
uni.clearStorage(); |
|||
uni.reLaunch({ |
|||
url: '/pages/user/login', |
|||
}); |
|||
}, |
|||
// logo 回到首页 |
|||
handleLogo() { |
|||
uni.navigateTo({ |
|||
url: `/pages/index/index`, |
|||
}); |
|||
}, |
|||
|
|||
// 关闭弹窗 |
|||
handleClose() { |
|||
this.pdfId = '' |
|||
this.show = false |
|||
}, |
|||
// 上一页函数, |
|||
prePage() { |
|||
var page = this.pageNum |
|||
page = page > 1 ? page - 1 : this.pageTotalNum |
|||
this.pageNum = page |
|||
}, |
|||
// 下一页函数 |
|||
nextPage() { |
|||
var page = this.pageNum |
|||
page = page < this.pageTotalNum ? page + 1 : 1 |
|||
this.pageNum = page |
|||
}, |
|||
// 页面加载回调函数,其中e为当前页数 |
|||
pageLoaded(e) { |
|||
this.curPageNum = e |
|||
}, |
|||
// 其他的一些回调函数。 |
|||
pdfError(error) { |
|||
console.error(error) |
|||
}, |
|||
}, |
|||
// 页面显示调用接口 |
|||
onLoad() {}, |
|||
}; |
|||
import pdf from "vue-pdf"; |
|||
export default { |
|||
name: "MeetingList", |
|||
props: ["infos"], |
|||
components: { |
|||
pdf, |
|||
}, |
|||
data() { |
|||
return { |
|||
filePdfUrl: "", |
|||
userName: uni.getStorageSync("userName"), |
|||
detailsId: "", |
|||
numPages: 0, |
|||
show: false, |
|||
loadedPages: [], |
|||
currentPage: 1, |
|||
loadInterval: null, |
|||
loadCount: 5, // 默认每次加载5页 |
|||
}; |
|||
}, |
|||
created() { |
|||
let routes = getCurrentPages(); |
|||
let curParam = routes[routes.length - 1].options; |
|||
this.detailsId = curParam.detailsId; |
|||
this.filePdfUrl = curParam.filePdfUrl; |
|||
this.getNumPages(this.filePdfUrl); |
|||
}, |
|||
beforeDestroy() { |
|||
if (this.loadInterval) { |
|||
clearInterval(this.loadInterval); |
|||
} |
|||
}, |
|||
methods: { |
|||
getNumPages(url) { |
|||
this.pdfSrc = url; |
|||
this.pdfSrc = pdf.createLoadingTask(this.pdfSrc); |
|||
this.pdfSrc.promise.then((pdf) => { |
|||
this.numPages = pdf.numPages; |
|||
this.startLoadingPages(); |
|||
}); |
|||
}, |
|||
|
|||
startLoadingPages() { |
|||
this.loadInterval = setInterval(() => { |
|||
if (this.currentPage <= this.numPages) { |
|||
// 每次加载loadCount页 |
|||
const endPage = Math.min( |
|||
this.currentPage + this.loadCount - 1, |
|||
this.numPages |
|||
); |
|||
for (let i = this.currentPage; i <= endPage; i++) { |
|||
this.loadedPages.push(i); |
|||
} |
|||
this.currentPage = endPage + 1; |
|||
} else { |
|||
clearInterval(this.loadInterval); |
|||
} |
|||
}, 500); |
|||
}, |
|||
handleBack() { |
|||
uni.navigateTo({ |
|||
url: `/pages/index/details?id=${this.detailsId}`, |
|||
}); |
|||
}, |
|||
handleOut() { |
|||
uni.clearStorage(); |
|||
uni.reLaunch({ |
|||
url: "/pages/user/login", |
|||
}); |
|||
}, |
|||
handleLogo() { |
|||
uni.navigateTo({ |
|||
url: `/pages/index/index`, |
|||
}); |
|||
}, |
|||
handleClose() { |
|||
this.pdfId = ""; |
|||
this.show = false; |
|||
}, |
|||
prePage() { |
|||
var page = this.pageNum; |
|||
page = page > 1 ? page - 1 : this.pageTotalNum; |
|||
this.pageNum = page; |
|||
}, |
|||
nextPage() { |
|||
var page = this.pageNum; |
|||
page = page < this.pageTotalNum ? page + 1 : 1; |
|||
this.pageNum = page; |
|||
}, |
|||
pageLoaded(e) { |
|||
this.curPageNum = e; |
|||
}, |
|||
pdfError(error) { |
|||
console.error(error); |
|||
}, |
|||
}, |
|||
onLoad() {}, |
|||
}; |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
/deep/ .u-modal__content{ |
|||
text-align: center; |
|||
} |
|||
.popup-close { |
|||
position: fixed; |
|||
right: 20px; |
|||
top: 20px; |
|||
z-index: 9999; |
|||
|
|||
/deep/.uni-icons { |
|||
font-size: 40px !important; |
|||
color: #fff !important; |
|||
} |
|||
} |
|||
|
|||
.view-gb { |
|||
max-width: 100px; |
|||
margin-left: 16px; |
|||
} |
|||
|
|||
.view-li { |
|||
// padding-left: 10px; |
|||
} |
|||
|
|||
.view-pdf { |
|||
width: 60vw; |
|||
margin: auto; |
|||
} |
|||
|
|||
.tools { |
|||
display: flex; |
|||
align-items: center; |
|||
position: absolute; |
|||
bottom: 26px; |
|||
left:16px; |
|||
right:16px; |
|||
|
|||
uni-button { |
|||
font-size: 18px; |
|||
line-height: 44px; |
|||
height: 44px; |
|||
flex: 1 |
|||
} |
|||
|
|||
.page { |
|||
line-height: 44px; |
|||
height: 44px; |
|||
width: 100px; |
|||
text-align: center; |
|||
} |
|||
} |
|||
|
|||
.pathsName { |
|||
color: #fff; |
|||
font-size: 12px; |
|||
} |
|||
|
|||
.pdfBox .el-button { |
|||
background: rgba(255, 255, 255, 0); |
|||
border: none; |
|||
/* width: 30px; */ |
|||
} |
|||
|
|||
.pdfBox>>>.el-icon-arrow-left, |
|||
.pdfBox>>>.el-icon-arrow-right { |
|||
font-size: 18px; |
|||
color: #000; |
|||
} |
|||
|
|||
.pdfBox .page { |
|||
margin: 0 10px; |
|||
} |
|||
|
|||
.pdfBox .el-button-group { |
|||
width: 100%; |
|||
justify-content: center; |
|||
display: flex; |
|||
align-items: center; |
|||
padding-top: 20px; |
|||
} |
|||
|
|||
.pdfBox { |
|||
padding-bottom: 20px; |
|||
margin-top: 20px; |
|||
background: #fff; |
|||
min-height: 300px; |
|||
} |
|||
|
|||
.contLeft-pane>>>.el-form-item__label { |
|||
text-align: right; |
|||
margin-right: 10px !important; |
|||
padding: 0 !important; |
|||
} |
|||
|
|||
.contLeft-pane>>>.el-form-item--medium .el-form-item__content { |
|||
flex: 1; |
|||
} |
|||
|
|||
.li-item { |
|||
uni-view { |
|||
font-size: 20px; |
|||
line-height: 40px; |
|||
|
|||
span { |
|||
font-size: 20px; |
|||
} |
|||
} |
|||
|
|||
|
|||
.li-title { |
|||
font-size: 20px; |
|||
font-weight: bold; |
|||
line-height: 30px; |
|||
} |
|||
} |
|||
|
|||
.view-box { |
|||
margin-top: 50px; |
|||
} |
|||
|
|||
.view-none { |
|||
height: 100%; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
font-size: 40px !important; |
|||
} |
|||
|
|||
.view-ul { |
|||
text-align: left; |
|||
margin-bottom: 16px; |
|||
|
|||
.view-li { |
|||
span { |
|||
font-size: 20px; |
|||
line-height: 40px; |
|||
} |
|||
|
|||
} |
|||
} |
|||
|
|||
.view-title { |
|||
display: inline-block; |
|||
border: 1px solid #000; |
|||
padding: 0 14px; |
|||
margin-bottom: 30px; |
|||
line-height: 50px; |
|||
border-radius: 6px; |
|||
font-size: 20px; |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.box { |
|||
height: 100vh; |
|||
background-size: cover; |
|||
box-sizing: border-box; |
|||
padding: 20px 100px; |
|||
display: flex; |
|||
flex-direction: column; |
|||
|
|||
.box-cent { |
|||
flex: 1; |
|||
margin-top: 70px; |
|||
position: relative; |
|||
} |
|||
|
|||
.box-cent1 { |
|||
position: absolute; |
|||
top: 0; |
|||
bottom: 0; |
|||
left: 0; |
|||
right: 0; |
|||
overflow: auto; |
|||
|
|||
} |
|||
} |
|||
::v-deep .u-modal__content { |
|||
text-align: center; |
|||
} |
|||
.popup-close { |
|||
position: fixed; |
|||
right: 20px; |
|||
top: 20px; |
|||
z-index: 9999; |
|||
|
|||
::v-deep.uni-icons { |
|||
font-size: 40px !important; |
|||
color: #fff !important; |
|||
} |
|||
} |
|||
|
|||
.view-gb { |
|||
max-width: 100px; |
|||
margin-left: 16px; |
|||
} |
|||
|
|||
.view-li { |
|||
// padding-left: 10px; |
|||
} |
|||
|
|||
.view-pdf { |
|||
max-width: 100%; |
|||
width: 60vw; |
|||
margin: auto; |
|||
} |
|||
|
|||
.tools { |
|||
display: flex; |
|||
align-items: center; |
|||
position: absolute; |
|||
bottom: 26px; |
|||
left: 16px; |
|||
right: 16px; |
|||
|
|||
uni-button { |
|||
font-size: 18px; |
|||
line-height: 44px; |
|||
height: 44px; |
|||
flex: 1; |
|||
} |
|||
|
|||
.page { |
|||
line-height: 44px; |
|||
height: 44px; |
|||
width: 100px; |
|||
text-align: center; |
|||
} |
|||
} |
|||
|
|||
.pathsName { |
|||
color: #fff; |
|||
font-size: 12px; |
|||
} |
|||
|
|||
.pdfBox .el-button { |
|||
background: rgba(255, 255, 255, 0); |
|||
border: none; |
|||
/* width: 30px; */ |
|||
} |
|||
|
|||
.pdfBox >>> .el-icon-arrow-left, |
|||
.pdfBox >>> .el-icon-arrow-right { |
|||
font-size: 18px; |
|||
color: #000; |
|||
} |
|||
|
|||
.pdfBox .page { |
|||
margin: 0 10px; |
|||
} |
|||
|
|||
.pdfBox .el-button-group { |
|||
width: 100%; |
|||
justify-content: center; |
|||
display: flex; |
|||
align-items: center; |
|||
padding-top: 20px; |
|||
} |
|||
|
|||
.pdfBox { |
|||
padding-bottom: 20px; |
|||
margin-top: 20px; |
|||
background: #fff; |
|||
min-height: 300px; |
|||
} |
|||
|
|||
.contLeft-pane >>> .el-form-item__label { |
|||
text-align: right; |
|||
margin-right: 10px !important; |
|||
padding: 0 !important; |
|||
} |
|||
|
|||
.contLeft-pane >>> .el-form-item--medium .el-form-item__content { |
|||
flex: 1; |
|||
} |
|||
|
|||
.li-item { |
|||
uni-view { |
|||
font-size: 20px; |
|||
line-height: 40px; |
|||
|
|||
span { |
|||
font-size: 20px; |
|||
} |
|||
} |
|||
|
|||
.li-title { |
|||
font-size: 20px; |
|||
font-weight: bold; |
|||
line-height: 30px; |
|||
} |
|||
} |
|||
|
|||
.view-box { |
|||
margin-top: 50px; |
|||
} |
|||
|
|||
.view-none { |
|||
height: 100%; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
font-size: 40px !important; |
|||
} |
|||
|
|||
.view-ul { |
|||
text-align: left; |
|||
margin-bottom: 16px; |
|||
|
|||
.view-li { |
|||
span { |
|||
font-size: 20px; |
|||
line-height: 40px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.view-title { |
|||
display: inline-block; |
|||
border: 1px solid #000; |
|||
padding: 0 14px; |
|||
margin-bottom: 30px; |
|||
line-height: 50px; |
|||
border-radius: 6px; |
|||
font-size: 20px; |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.box { |
|||
height: 100vh; |
|||
background-size: cover; |
|||
box-sizing: border-box; |
|||
padding: 20px 100px; |
|||
display: flex; |
|||
flex-direction: column; |
|||
|
|||
.box-cent { |
|||
flex: 1; |
|||
margin-top: 70px; |
|||
position: relative; |
|||
} |
|||
|
|||
.box-cent1 { |
|||
position: absolute; |
|||
top: 0; |
|||
bottom: 0; |
|||
left: 0; |
|||
right: 0; |
|||
overflow-y: scroll; |
|||
} |
|||
} |
|||
</style> |
|||
<style></style> |
|||
<style></style> |
|||
|
|||
@ -0,0 +1,333 @@ |
|||
<template> |
|||
<view class="box" style="position: relative"> |
|||
<!-- <image class="back" src='../../imgs/back.png' mode="widthFix" @click="handleBack"></image> --> |
|||
<image class="logo" src="../../imgs/logo.png" mode="widthFix"></image> |
|||
<view class="box-cent"> |
|||
<view class="box-cent1"> |
|||
<view class="view-pdf"> |
|||
<pdf |
|||
ref="pdf" |
|||
:page="pageNum" |
|||
@progress="loadedRatio = $event" |
|||
@page-loaded="pageLoaded($event)" |
|||
@num-pages="pageTotalNum = $event" |
|||
@error="pdfError($event)" |
|||
@link-clicked="page = $event" |
|||
:src="filePdfUrl" |
|||
> |
|||
</pdf> |
|||
</view> |
|||
</view> |
|||
<u-modal |
|||
v-if="show" |
|||
:show="show" |
|||
@cancel="show = false" |
|||
:showCancelButton="true" |
|||
content="是否确认退出登录?" |
|||
@confirm="handleOut" |
|||
></u-modal> |
|||
</view> |
|||
<!-- 底部背景图 --> |
|||
<view class="view-backimg"> |
|||
<view class="view-backimg-top"></view> |
|||
<!-- <view class="view-backimg-bottom"></view> --> |
|||
</view> |
|||
<div class="tools"> |
|||
<view style="width: 50vw; display: flex; margin: auto"> |
|||
<button |
|||
:theme="'default'" |
|||
type="submit" |
|||
@click.stop="prePage" |
|||
class="mr10" |
|||
> |
|||
上一页 |
|||
</button> |
|||
<div class="page">{{ pageNum }}/{{ pageTotalNum }}</div> |
|||
<button |
|||
:theme="'default'" |
|||
type="submit" |
|||
@click.stop="nextPage" |
|||
class="mr10" |
|||
> |
|||
下一页 |
|||
</button> |
|||
</view> |
|||
</div> |
|||
<!-- 头像 - 头像 --> |
|||
<view class="avatarobx"> |
|||
<view class="name">{{ userName }}</view> |
|||
<image |
|||
@click="handleBack" |
|||
class="avatar" |
|||
src="../../imgs/arrow-left.png" |
|||
mode="widthFix" |
|||
></image> |
|||
<image |
|||
@click="show = true" |
|||
class="avatar" |
|||
src="../../imgs/out.png" |
|||
mode="widthFix" |
|||
></image> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import pdf from 'vue-pdf'; |
|||
export default { |
|||
name: 'MeetingList', |
|||
props: ['infos'], |
|||
components: { |
|||
pdf, |
|||
}, |
|||
data() { |
|||
return { |
|||
pageNum: 1, |
|||
pageTotalNum: 1, |
|||
// 加载进度 |
|||
loadedRatio: 0, |
|||
curPageNum: 0, |
|||
filePdfUrl: '', |
|||
userName: uni.getStorageSync('userName'), |
|||
show: false, |
|||
detailsId: '', |
|||
}; |
|||
}, |
|||
created() { |
|||
let routes = getCurrentPages(); // 获取当前打开过的页面路由数组 |
|||
let curParam = routes[routes.length - 1].options; //获取路由参数 |
|||
this.detailsId = curParam.detailsId; |
|||
console.log('this.detailsId ', this.detailsId); |
|||
this.filePdfUrl = curParam.filePdfUrl; |
|||
}, |
|||
methods: { |
|||
// logo 回到首页 |
|||
handleBack() { |
|||
uni.navigateTo({ |
|||
url: `/pages/index/details?id=${this.detailsId}`, |
|||
}); |
|||
// uni.navigateBack({ |
|||
// delta: 1 |
|||
// }); |
|||
}, |
|||
// 退出登录 |
|||
handleOut() { |
|||
uni.clearStorage(); |
|||
uni.reLaunch({ |
|||
url: '/pages/user/login', |
|||
}); |
|||
}, |
|||
// logo 回到首页 |
|||
handleLogo() { |
|||
uni.navigateTo({ |
|||
url: `/pages/index/index`, |
|||
}); |
|||
}, |
|||
|
|||
// 关闭弹窗 |
|||
handleClose() { |
|||
this.pdfId = ''; |
|||
this.show = false; |
|||
}, |
|||
// 上一页函数, |
|||
prePage() { |
|||
var page = this.pageNum; |
|||
page = page > 1 ? page - 1 : this.pageTotalNum; |
|||
this.pageNum = page; |
|||
}, |
|||
// 下一页函数 |
|||
nextPage() { |
|||
var page = this.pageNum; |
|||
page = page < this.pageTotalNum ? page + 1 : 1; |
|||
this.pageNum = page; |
|||
}, |
|||
// 页面加载回调函数,其中e为当前页数 |
|||
pageLoaded(e) { |
|||
this.curPageNum = e; |
|||
}, |
|||
// 其他的一些回调函数。 |
|||
pdfError(error) { |
|||
console.error(error); |
|||
}, |
|||
}, |
|||
// 页面显示调用接口 |
|||
onLoad() {}, |
|||
}; |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
::v-deep .u-modal__content { |
|||
text-align: center; |
|||
} |
|||
.popup-close { |
|||
position: fixed; |
|||
right: 20px; |
|||
top: 20px; |
|||
z-index: 9999; |
|||
|
|||
::v-deep.uni-icons { |
|||
font-size: 40px !important; |
|||
color: #fff !important; |
|||
} |
|||
} |
|||
|
|||
.view-gb { |
|||
max-width: 100px; |
|||
margin-left: 16px; |
|||
} |
|||
|
|||
.view-li { |
|||
// padding-left: 10px; |
|||
} |
|||
|
|||
.view-pdf { |
|||
width: 60vw; |
|||
margin: auto; |
|||
} |
|||
|
|||
.tools { |
|||
display: flex; |
|||
align-items: center; |
|||
position: absolute; |
|||
bottom: 26px; |
|||
left: 16px; |
|||
right: 16px; |
|||
|
|||
uni-button { |
|||
font-size: 18px; |
|||
line-height: 44px; |
|||
height: 44px; |
|||
flex: 1; |
|||
} |
|||
|
|||
.page { |
|||
line-height: 44px; |
|||
height: 44px; |
|||
width: 100px; |
|||
text-align: center; |
|||
} |
|||
} |
|||
|
|||
.pathsName { |
|||
color: #fff; |
|||
font-size: 12px; |
|||
} |
|||
|
|||
.pdfBox .el-button { |
|||
background: rgba(255, 255, 255, 0); |
|||
border: none; |
|||
/* width: 30px; */ |
|||
} |
|||
|
|||
.pdfBox >>> .el-icon-arrow-left, |
|||
.pdfBox >>> .el-icon-arrow-right { |
|||
font-size: 18px; |
|||
color: #000; |
|||
} |
|||
|
|||
.pdfBox .page { |
|||
margin: 0 10px; |
|||
} |
|||
|
|||
.pdfBox .el-button-group { |
|||
width: 100%; |
|||
justify-content: center; |
|||
display: flex; |
|||
align-items: center; |
|||
padding-top: 20px; |
|||
} |
|||
|
|||
.pdfBox { |
|||
padding-bottom: 20px; |
|||
margin-top: 20px; |
|||
background: #fff; |
|||
min-height: 300px; |
|||
} |
|||
|
|||
.contLeft-pane >>> .el-form-item__label { |
|||
text-align: right; |
|||
margin-right: 10px !important; |
|||
padding: 0 !important; |
|||
} |
|||
|
|||
.contLeft-pane >>> .el-form-item--medium .el-form-item__content { |
|||
flex: 1; |
|||
} |
|||
|
|||
.li-item { |
|||
uni-view { |
|||
font-size: 20px; |
|||
line-height: 40px; |
|||
|
|||
span { |
|||
font-size: 20px; |
|||
} |
|||
} |
|||
|
|||
.li-title { |
|||
font-size: 20px; |
|||
font-weight: bold; |
|||
line-height: 30px; |
|||
} |
|||
} |
|||
|
|||
.view-box { |
|||
margin-top: 50px; |
|||
} |
|||
|
|||
.view-none { |
|||
height: 100%; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
font-size: 40px !important; |
|||
} |
|||
|
|||
.view-ul { |
|||
text-align: left; |
|||
margin-bottom: 16px; |
|||
|
|||
.view-li { |
|||
span { |
|||
font-size: 20px; |
|||
line-height: 40px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.view-title { |
|||
display: inline-block; |
|||
border: 1px solid #000; |
|||
padding: 0 14px; |
|||
margin-bottom: 30px; |
|||
line-height: 50px; |
|||
border-radius: 6px; |
|||
font-size: 20px; |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.box { |
|||
height: 100vh; |
|||
background-size: cover; |
|||
box-sizing: border-box; |
|||
padding: 20px 100px; |
|||
display: flex; |
|||
flex-direction: column; |
|||
|
|||
.box-cent { |
|||
flex: 1; |
|||
margin-top: 70px; |
|||
position: relative; |
|||
} |
|||
|
|||
.box-cent1 { |
|||
position: absolute; |
|||
top: 0; |
|||
bottom: 0; |
|||
left: 0; |
|||
right: 0; |
|||
overflow: auto; |
|||
} |
|||
} |
|||
</style> |
|||
<style></style> |
|||
@ -0,0 +1,190 @@ |
|||
<<<<<<< HEAD |
|||
======= |
|||
export default { |
|||
props: { |
|||
// 输入的值
|
|||
value: { |
|||
type: [String, Number], |
|||
default: uni.$u.props.input.value, |
|||
}, |
|||
// 输入框类型
|
|||
// number-数字输入键盘,app-vue下可以输入浮点数,app-nvue和小程序平台下只能输入整数
|
|||
// idcard-身份证输入键盘,微信、支付宝、百度、QQ小程序
|
|||
// digit-带小数点的数字键盘,App的nvue页面、微信、支付宝、百度、头条、QQ小程序
|
|||
// text-文本输入键盘
|
|||
type: { |
|||
type: String, |
|||
default: uni.$u.props.input.type, |
|||
}, |
|||
// 如果 textarea 是在一个 position:fixed 的区域,需要显示指定属性 fixed 为 true,
|
|||
// 兼容性:微信小程序、百度小程序、字节跳动小程序、QQ小程序
|
|||
fixed: { |
|||
type: Boolean, |
|||
default: uni.$u.props.input.fixed, |
|||
}, |
|||
// 是否禁用输入框
|
|||
disabled: { |
|||
type: Boolean, |
|||
default: uni.$u.props.input.disabled, |
|||
}, |
|||
// 禁用状态时的背景色
|
|||
disabledColor: { |
|||
type: String, |
|||
default: uni.$u.props.input.disabledColor, |
|||
}, |
|||
// 是否显示清除控件
|
|||
clearable: { |
|||
type: Boolean, |
|||
default: uni.$u.props.input.clearable, |
|||
}, |
|||
// 是否密码类型
|
|||
password: { |
|||
type: Boolean, |
|||
default: uni.$u.props.input.password, |
|||
}, |
|||
// 最大输入长度,设置为 -1 的时候不限制最大长度
|
|||
maxlength: { |
|||
type: [String, Number], |
|||
default: uni.$u.props.input.maxlength, |
|||
}, |
|||
// 输入框为空时的占位符
|
|||
placeholder: { |
|||
type: String, |
|||
default: uni.$u.props.input.placeholder, |
|||
}, |
|||
// 指定placeholder的样式类,注意页面或组件的style中写了scoped时,需要在类名前写::v-deep
|
|||
placeholderClass: { |
|||
type: String, |
|||
default: uni.$u.props.input.placeholderClass, |
|||
}, |
|||
// 指定placeholder的样式
|
|||
placeholderStyle: { |
|||
type: [String, Object], |
|||
default: uni.$u.props.input.placeholderStyle, |
|||
}, |
|||
// 是否显示输入字数统计,只在 type ="text"或type ="textarea"时有效
|
|||
showWordLimit: { |
|||
type: Boolean, |
|||
default: uni.$u.props.input.showWordLimit, |
|||
}, |
|||
// 设置右下角按钮的文字,有效值:send|search|next|go|done,兼容性详见uni-app文档
|
|||
// https://uniapp.dcloud.io/component/input
|
|||
// https://uniapp.dcloud.io/component/textarea
|
|||
confirmType: { |
|||
type: String, |
|||
default: uni.$u.props.input.confirmType, |
|||
}, |
|||
// 点击键盘右下角按钮时是否保持键盘不收起,H5无效
|
|||
confirmHold: { |
|||
type: Boolean, |
|||
default: uni.$u.props.input.confirmHold, |
|||
}, |
|||
// focus时,点击页面的时候不收起键盘,微信小程序有效
|
|||
holdKeyboard: { |
|||
type: Boolean, |
|||
default: uni.$u.props.input.holdKeyboard, |
|||
}, |
|||
// 自动获取焦点
|
|||
// 在 H5 平台能否聚焦以及软键盘是否跟随弹出,取决于当前浏览器本身的实现。nvue 页面不支持,需使用组件的 focus()、blur() 方法控制焦点
|
|||
focus: { |
|||
type: Boolean, |
|||
default: uni.$u.props.input.focus, |
|||
}, |
|||
// 键盘收起时,是否自动失去焦点,目前仅App3.0.0+有效
|
|||
autoBlur: { |
|||
type: Boolean, |
|||
default: uni.$u.props.input.autoBlur, |
|||
}, |
|||
// 是否去掉 iOS 下的默认内边距,仅微信小程序,且type=textarea时有效
|
|||
disableDefaultPadding: { |
|||
type: Boolean, |
|||
default: uni.$u.props.input.disableDefaultPadding, |
|||
}, |
|||
// 指定focus时光标的位置
|
|||
cursor: { |
|||
type: [String, Number], |
|||
default: uni.$u.props.input.cursor, |
|||
}, |
|||
// 输入框聚焦时底部与键盘的距离
|
|||
cursorSpacing: { |
|||
type: [String, Number], |
|||
default: uni.$u.props.input.cursorSpacing, |
|||
}, |
|||
// 光标起始位置,自动聚集时有效,需与selection-end搭配使用
|
|||
selectionStart: { |
|||
type: [String, Number], |
|||
default: uni.$u.props.input.selectionStart, |
|||
}, |
|||
// 光标结束位置,自动聚集时有效,需与selection-start搭配使用
|
|||
selectionEnd: { |
|||
type: [String, Number], |
|||
default: uni.$u.props.input.selectionEnd, |
|||
}, |
|||
// 键盘弹起时,是否自动上推页面
|
|||
adjustPosition: { |
|||
type: Boolean, |
|||
default: uni.$u.props.input.adjustPosition, |
|||
}, |
|||
// 输入框内容对齐方式,可选值为:left|center|right
|
|||
inputAlign: { |
|||
type: String, |
|||
default: uni.$u.props.input.inputAlign, |
|||
}, |
|||
// 输入框字体的大小
|
|||
fontSize: { |
|||
type: [String, Number], |
|||
default: uni.$u.props.input.fontSize, |
|||
}, |
|||
// 输入框字体颜色
|
|||
color: { |
|||
type: String, |
|||
default: uni.$u.props.input.color, |
|||
}, |
|||
// 输入框前置图标
|
|||
prefixIcon: { |
|||
type: String, |
|||
default: uni.$u.props.input.prefixIcon, |
|||
}, |
|||
// 前置图标样式,对象或字符串
|
|||
prefixIconStyle: { |
|||
type: [String, Object], |
|||
default: uni.$u.props.input.prefixIconStyle, |
|||
}, |
|||
// 输入框后置图标
|
|||
suffixIcon: { |
|||
type: String, |
|||
default: uni.$u.props.input.suffixIcon, |
|||
}, |
|||
// 后置图标样式,对象或字符串
|
|||
suffixIconStyle: { |
|||
type: [String, Object], |
|||
default: uni.$u.props.input.suffixIconStyle, |
|||
}, |
|||
// 边框类型,surround-四周边框,bottom-底部边框,none-无边框
|
|||
border: { |
|||
type: String, |
|||
default: uni.$u.props.input.border, |
|||
}, |
|||
// 是否只读,与disabled不同之处在于disabled会置灰组件,而readonly则不会
|
|||
readonly: { |
|||
type: Boolean, |
|||
default: uni.$u.props.input.readonly, |
|||
}, |
|||
// 输入框形状,circle-圆形,square-方形
|
|||
shape: { |
|||
type: String, |
|||
default: uni.$u.props.input.shape, |
|||
}, |
|||
// 用于处理或者过滤输入框内容的方法
|
|||
formatter: { |
|||
type: [Function, null], |
|||
default: uni.$u.props.input.formatter, |
|||
}, |
|||
// 是否忽略组件内对文本合成系统事件的处理
|
|||
ignoreCompositionEvent: { |
|||
type: Boolean, |
|||
default: true, |
|||
}, |
|||
}, |
|||
}; |
|||
>>>>>>> fb3b4fc780fb389b9972fb75a2a499f29694144b |
|||
@ -0,0 +1,357 @@ |
|||
<<<<<<< HEAD |
|||
======= |
|||
<template> |
|||
<view class="u-input" :class="inputClass" :style="[wrapperStyle]"> |
|||
<view class="u-input__content"> |
|||
<view |
|||
class="u-input__content__prefix-icon" |
|||
v-if="prefixIcon || $slots.prefix" |
|||
> |
|||
<slot name="prefix"> |
|||
<u-icon |
|||
:name="prefixIcon" |
|||
size="18" |
|||
:customStyle="prefixIconStyle" |
|||
></u-icon> |
|||
</slot> |
|||
</view> |
|||
<view class="u-input__content__field-wrapper" @tap="clickHandler"> |
|||
<!-- 根据uni-app的input组件文档,H5和APP中只要声明了password参数(无论true还是false),type均失效,此时 |
|||
为了防止type=number时,又存在password属性,type无效,此时需要设置password为undefined |
|||
--> |
|||
<input |
|||
class="u-input__content__field-wrapper__field" |
|||
:style="[inputStyle]" |
|||
:type="type" |
|||
:focus="focus" |
|||
:cursor="cursor" |
|||
:value="innerValue" |
|||
:auto-blur="autoBlur" |
|||
:disabled="disabled || readonly" |
|||
:maxlength="maxlength" |
|||
:placeholder="placeholder" |
|||
:placeholder-style="placeholderStyle" |
|||
:placeholder-class="placeholderClass" |
|||
:confirm-type="confirmType" |
|||
:confirm-hold="confirmHold" |
|||
:hold-keyboard="holdKeyboard" |
|||
:cursor-spacing="cursorSpacing" |
|||
:adjust-position="adjustPosition" |
|||
:selection-end="selectionEnd" |
|||
:selection-start="selectionStart" |
|||
:password="password || type === 'password' || false" |
|||
:ignoreCompositionEvent="ignoreCompositionEvent" |
|||
@input="onInput" |
|||
@blur="onBlur" |
|||
@focus="onFocus" |
|||
@confirm="onConfirm" |
|||
@keyboardheightchange="onkeyboardheightchange" |
|||
/> |
|||
</view> |
|||
<view |
|||
class="u-input__content__clear" |
|||
v-if="isShowClear" |
|||
@tap="onClear" |
|||
> |
|||
<u-icon |
|||
name="close" |
|||
size="11" |
|||
color="#ffffff" |
|||
customStyle="line-height: 12px" |
|||
></u-icon> |
|||
</view> |
|||
<view |
|||
class="u-input__content__subfix-icon" |
|||
v-if="suffixIcon || $slots.suffix" |
|||
> |
|||
<slot name="suffix"> |
|||
<u-icon |
|||
:name="suffixIcon" |
|||
size="18" |
|||
:customStyle="suffixIconStyle" |
|||
></u-icon> |
|||
</slot> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import props from './props.js'; |
|||
/** |
|||
* Input 输入框 |
|||
* @description 此组件为一个输入框,默认没有边框和样式,是专门为配合表单组件u-form而设计的,利用它可以快速实现表单验证,输入内容,下拉选择等功能。 |
|||
* @tutorial https://uviewui.com/components/input.html |
|||
* @property {String | Number} value 输入的值 |
|||
* @property {String} type 输入框类型,见上方说明 ( 默认 'text' ) |
|||
* @property {Boolean} fixed 如果 textarea 是在一个 position:fixed 的区域,需要显示指定属性 fixed 为 true,兼容性:微信小程序、百度小程序、字节跳动小程序、QQ小程序 ( 默认 false ) |
|||
* @property {Boolean} disabled 是否禁用输入框 ( 默认 false ) |
|||
* @property {String} disabledColor 禁用状态时的背景色( 默认 '#f5f7fa' ) |
|||
* @property {Boolean} clearable 是否显示清除控件 ( 默认 false ) |
|||
* @property {Boolean} password 是否密码类型 ( 默认 false ) |
|||
* @property {String | Number} maxlength 最大输入长度,设置为 -1 的时候不限制最大长度 ( 默认 -1 ) |
|||
* @property {String} placeholder 输入框为空时的占位符 |
|||
* @property {String} placeholderClass 指定placeholder的样式类,注意页面或组件的style中写了scoped时,需要在类名前写::v-deep ( 默认 'input-placeholder' ) |
|||
* @property {String | Object} placeholderStyle 指定placeholder的样式,字符串/对象形式,如"color: red;" |
|||
* @property {Boolean} showWordLimit 是否显示输入字数统计,只在 type ="text"或type ="textarea"时有效 ( 默认 false ) |
|||
* @property {String} confirmType 设置右下角按钮的文字,兼容性详见uni-app文档 ( 默认 'done' ) |
|||
* @property {Boolean} confirmHold 点击键盘右下角按钮时是否保持键盘不收起,H5无效 ( 默认 false ) |
|||
* @property {Boolean} holdKeyboard focus时,点击页面的时候不收起键盘,微信小程序有效 ( 默认 false ) |
|||
* @property {Boolean} focus 自动获取焦点,在 H5 平台能否聚焦以及软键盘是否跟随弹出,取决于当前浏览器本身的实现。nvue 页面不支持,需使用组件的 focus()、blur() 方法控制焦点 ( 默认 false ) |
|||
* @property {Boolean} autoBlur 键盘收起时,是否自动失去焦点,目前仅App3.0.0+有效 ( 默认 false ) |
|||
* @property {Boolean} disableDefaultPadding 是否去掉 iOS 下的默认内边距,仅微信小程序,且type=textarea时有效 ( 默认 false ) |
|||
* @property {String | Number} cursor 指定focus时光标的位置( 默认 -1 ) |
|||
* @property {String | Number} cursorSpacing 输入框聚焦时底部与键盘的距离 ( 默认 30 ) |
|||
* @property {String | Number} selectionStart 光标起始位置,自动聚集时有效,需与selection-end搭配使用 ( 默认 -1 ) |
|||
* @property {String | Number} selectionEnd 光标结束位置,自动聚集时有效,需与selection-start搭配使用 ( 默认 -1 ) |
|||
* @property {Boolean} adjustPosition 键盘弹起时,是否自动上推页面 ( 默认 true ) |
|||
* @property {String} inputAlign 输入框内容对齐方式( 默认 'left' ) |
|||
* @property {String | Number} fontSize 输入框字体的大小 ( 默认 '15px' ) |
|||
* @property {String} color 输入框字体颜色 ( 默认 '#303133' ) |
|||
* @property {Function} formatter 内容式化函数 |
|||
* @property {String} prefixIcon 输入框前置图标 |
|||
* @property {String | Object} prefixIconStyle 前置图标样式,对象或字符串 |
|||
* @property {String} suffixIcon 输入框后置图标 |
|||
* @property {String | Object} suffixIconStyle 后置图标样式,对象或字符串 |
|||
* @property {String} border 边框类型,surround-四周边框,bottom-底部边框,none-无边框 ( 默认 'surround' ) |
|||
* @property {Boolean} readonly 是否只读,与disabled不同之处在于disabled会置灰组件,而readonly则不会 ( 默认 false ) |
|||
* @property {String} shape 输入框形状,circle-圆形,square-方形 ( 默认 'square' ) |
|||
* @property {Object} customStyle 定义需要用到的外部样式 |
|||
* @property {Boolean} ignoreCompositionEvent 是否忽略组件内对文本合成系统事件的处理。 |
|||
* @example <u-input v-model="value" :password="true" suffix-icon="lock-fill" /> |
|||
*/ |
|||
export default { |
|||
name: 'u-input', |
|||
mixins: [uni.$u.mpMixin, uni.$u.mixin, props], |
|||
data() { |
|||
return { |
|||
// 输入框的值 |
|||
innerValue: '', |
|||
// 是否处于获得焦点状态 |
|||
focused: false, |
|||
// value是否第一次变化,在watch中,由于加入immediate属性,会在第一次触发,此时不应该认为value发生了变化 |
|||
firstChange: true, |
|||
// value绑定值的变化是由内部还是外部引起的 |
|||
changeFromInner: false, |
|||
// 过滤处理方法 |
|||
innerFormatter: (value) => value, |
|||
}; |
|||
}, |
|||
watch: { |
|||
value: { |
|||
immediate: true, |
|||
handler(newVal, oldVal) { |
|||
this.innerValue = newVal; |
|||
/* #ifdef H5 */ |
|||
// 在H5中,外部value变化后,修改input中的值,不会触发@input事件,此时手动调用值变化方法 |
|||
if ( |
|||
this.firstChange === false && |
|||
this.changeFromInner === false |
|||
) { |
|||
this.valueChange(); |
|||
} |
|||
/* #endif */ |
|||
this.firstChange = false; |
|||
// 重置changeFromInner的值为false,标识下一次引起默认为外部引起的 |
|||
this.changeFromInner = false; |
|||
}, |
|||
}, |
|||
}, |
|||
computed: { |
|||
// 是否显示清除控件 |
|||
isShowClear() { |
|||
const { clearable, readonly, focused, innerValue } = this; |
|||
return !!clearable && !readonly && !!focused && innerValue !== ''; |
|||
}, |
|||
// 组件的类名 |
|||
inputClass() { |
|||
let classes = [], |
|||
{ border, disabled, shape } = this; |
|||
border === 'surround' && |
|||
(classes = classes.concat(['u-border', 'u-input--radius'])); |
|||
classes.push(`u-input--${shape}`); |
|||
border === 'bottom' && |
|||
(classes = classes.concat([ |
|||
'u-border-bottom', |
|||
'u-input--no-radius', |
|||
])); |
|||
return classes.join(' '); |
|||
}, |
|||
// 组件的样式 |
|||
wrapperStyle() { |
|||
const style = {}; |
|||
// 禁用状态下,被背景色加上对应的样式 |
|||
if (this.disabled) { |
|||
style.backgroundColor = this.disabledColor; |
|||
} |
|||
// 无边框时,去除内边距 |
|||
if (this.border === 'none') { |
|||
style.padding = '0'; |
|||
} else { |
|||
// 由于uni-app的iOS开发者能力有限,导致需要分开写才有效 |
|||
style.paddingTop = '6px'; |
|||
style.paddingBottom = '6px'; |
|||
style.paddingLeft = '9px'; |
|||
style.paddingRight = '9px'; |
|||
} |
|||
return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)); |
|||
}, |
|||
// 输入框的样式 |
|||
inputStyle() { |
|||
const style = { |
|||
color: this.color, |
|||
fontSize: uni.$u.addUnit(this.fontSize), |
|||
textAlign: this.inputAlign, |
|||
}; |
|||
return style; |
|||
}, |
|||
}, |
|||
methods: { |
|||
// 在微信小程序中,不支持将函数当做props参数,故只能通过ref形式调用 |
|||
setFormatter(e) { |
|||
this.innerFormatter = e; |
|||
}, |
|||
// 当键盘输入时,触发input事件 |
|||
onInput(e) { |
|||
let { value = '' } = e.detail || {}; |
|||
// 格式化过滤方法 |
|||
const formatter = this.formatter || this.innerFormatter; |
|||
const formatValue = formatter(value); |
|||
// 为了避免props的单向数据流特性,需要先将innerValue值设置为当前值,再在$nextTick中重新赋予设置后的值才有效 |
|||
this.innerValue = value; |
|||
this.$nextTick(() => { |
|||
this.innerValue = formatValue; |
|||
this.valueChange(); |
|||
}); |
|||
}, |
|||
// 输入框失去焦点时触发 |
|||
onBlur(event) { |
|||
this.$emit('blur', event.detail.value); |
|||
// H5端的blur会先于点击清除控件的点击click事件触发,导致focused |
|||
// 瞬间为false,从而隐藏了清除控件而无法被点击到 |
|||
uni.$u.sleep(50).then(() => { |
|||
this.focused = false; |
|||
}); |
|||
// 尝试调用u-form的验证方法 |
|||
uni.$u.formValidate(this, 'blur'); |
|||
}, |
|||
// 输入框聚焦时触发 |
|||
onFocus(event) { |
|||
this.focused = true; |
|||
this.$emit('focus'); |
|||
}, |
|||
// 点击完成按钮时触发 |
|||
onConfirm(event) { |
|||
this.$emit('confirm', this.innerValue); |
|||
}, |
|||
// 键盘高度发生变化的时候触发此事件 |
|||
// 兼容性:微信小程序2.7.0+、App 3.1.0+ |
|||
onkeyboardheightchange() { |
|||
this.$emit('keyboardheightchange'); |
|||
}, |
|||
// 内容发生变化,进行处理 |
|||
valueChange() { |
|||
const value = this.innerValue; |
|||
this.$nextTick(() => { |
|||
this.$emit('input', value); |
|||
// 标识value值的变化是由内部引起的 |
|||
this.changeFromInner = true; |
|||
this.$emit('change', value); |
|||
// 尝试调用u-form的验证方法 |
|||
uni.$u.formValidate(this, 'change'); |
|||
}); |
|||
}, |
|||
// 点击清除控件 |
|||
onClear() { |
|||
this.innerValue = ''; |
|||
this.$nextTick(() => { |
|||
this.valueChange(); |
|||
this.$emit('clear'); |
|||
}); |
|||
}, |
|||
/** |
|||
* 在安卓nvue上,事件无法冒泡 |
|||
* 在某些时间,我们希望监听u-from-item的点击事件,此时会导致点击u-form-item内的u-input后 |
|||
* 无法触发u-form-item的点击事件,这里通过手动调用u-form-item的方法进行触发 |
|||
*/ |
|||
clickHandler() { |
|||
// #ifdef APP-NVUE |
|||
if (uni.$u.os() === 'android') { |
|||
const formItem = uni.$u.$parent.call(this, 'u-form-item'); |
|||
if (formItem) { |
|||
formItem.clickHandler(); |
|||
} |
|||
} |
|||
// #endif |
|||
}, |
|||
}, |
|||
}; |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import '../../libs/css/components.scss'; |
|||
|
|||
.u-input { |
|||
@include flex(row); |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
flex: 1; |
|||
|
|||
&--radius, |
|||
&--square { |
|||
border-radius: 4px; |
|||
} |
|||
|
|||
&--no-radius { |
|||
border-radius: 0; |
|||
} |
|||
|
|||
&--circle { |
|||
border-radius: 100px; |
|||
} |
|||
|
|||
&__content { |
|||
flex: 1; |
|||
@include flex(row); |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
|
|||
&__field-wrapper { |
|||
position: relative; |
|||
@include flex(row); |
|||
margin: 0; |
|||
flex: 1; |
|||
|
|||
&__field { |
|||
line-height: 26px; |
|||
text-align: left; |
|||
color: $u-main-color; |
|||
height: 24px; |
|||
font-size: 15px; |
|||
flex: 1; |
|||
} |
|||
} |
|||
|
|||
&__clear { |
|||
width: 20px; |
|||
height: 20px; |
|||
border-radius: 100px; |
|||
background-color: #c6c7cb; |
|||
@include flex(row); |
|||
align-items: center; |
|||
justify-content: center; |
|||
transform: scale(0.82); |
|||
margin-left: 4px; |
|||
} |
|||
|
|||
&__subfix-icon { |
|||
margin-left: 4px; |
|||
} |
|||
|
|||
&__prefix-icon { |
|||
margin-right: 4px; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
>>>>>>> fb3b4fc780fb389b9972fb75a2a499f29694144b |
|||
@ -0,0 +1,122 @@ |
|||
<<<<<<< HEAD |
|||
======= |
|||
export default { |
|||
props: { |
|||
// 输入框的内容
|
|||
value: { |
|||
type: [String, Number], |
|||
default: uni.$u.props.textarea.value, |
|||
}, |
|||
// 输入框为空时占位符
|
|||
placeholder: { |
|||
type: [String, Number], |
|||
default: uni.$u.props.textarea.placeholder, |
|||
}, |
|||
// 指定placeholder的样式类,注意页面或组件的style中写了scoped时,需要在类名前写::v-deep
|
|||
placeholderClass: { |
|||
type: String, |
|||
default: uni.$u.props.input.placeholderClass, |
|||
}, |
|||
// 指定placeholder的样式
|
|||
placeholderStyle: { |
|||
type: [String, Object], |
|||
default: uni.$u.props.input.placeholderStyle, |
|||
}, |
|||
// 输入框高度
|
|||
height: { |
|||
type: [String, Number], |
|||
default: uni.$u.props.textarea.height, |
|||
}, |
|||
// 设置键盘右下角按钮的文字,仅微信小程序,App-vue和H5有效
|
|||
confirmType: { |
|||
type: String, |
|||
default: uni.$u.props.textarea.confirmType, |
|||
}, |
|||
// 是否禁用
|
|||
disabled: { |
|||
type: Boolean, |
|||
default: uni.$u.props.textarea.disabled, |
|||
}, |
|||
// 是否显示统计字数
|
|||
count: { |
|||
type: Boolean, |
|||
default: uni.$u.props.textarea.count, |
|||
}, |
|||
// 是否自动获取焦点,nvue不支持,H5取决于浏览器的实现
|
|||
focus: { |
|||
type: Boolean, |
|||
default: uni.$u.props.textarea.focus, |
|||
}, |
|||
// 是否自动增加高度
|
|||
autoHeight: { |
|||
type: Boolean, |
|||
default: uni.$u.props.textarea.autoHeight, |
|||
}, |
|||
// 如果textarea是在一个position:fixed的区域,需要显示指定属性fixed为true
|
|||
fixed: { |
|||
type: Boolean, |
|||
default: uni.$u.props.textarea.fixed, |
|||
}, |
|||
// 指定光标与键盘的距离
|
|||
cursorSpacing: { |
|||
type: Number, |
|||
default: uni.$u.props.textarea.cursorSpacing, |
|||
}, |
|||
// 指定focus时的光标位置
|
|||
cursor: { |
|||
type: [String, Number], |
|||
default: uni.$u.props.textarea.cursor, |
|||
}, |
|||
// 是否显示键盘上方带有”完成“按钮那一栏,
|
|||
showConfirmBar: { |
|||
type: Boolean, |
|||
default: uni.$u.props.textarea.showConfirmBar, |
|||
}, |
|||
// 光标起始位置,自动聚焦时有效,需与selection-end搭配使用
|
|||
selectionStart: { |
|||
type: Number, |
|||
default: uni.$u.props.textarea.selectionStart, |
|||
}, |
|||
// 光标结束位置,自动聚焦时有效,需与selection-start搭配使用
|
|||
selectionEnd: { |
|||
type: Number, |
|||
default: uni.$u.props.textarea.selectionEnd, |
|||
}, |
|||
// 键盘弹起时,是否自动上推页面
|
|||
adjustPosition: { |
|||
type: Boolean, |
|||
default: uni.$u.props.textarea.adjustPosition, |
|||
}, |
|||
// 是否去掉 iOS 下的默认内边距,只微信小程序有效
|
|||
disableDefaultPadding: { |
|||
type: Boolean, |
|||
default: uni.$u.props.textarea.disableDefaultPadding, |
|||
}, |
|||
// focus时,点击页面的时候不收起键盘,只微信小程序有效
|
|||
holdKeyboard: { |
|||
type: Boolean, |
|||
default: uni.$u.props.textarea.holdKeyboard, |
|||
}, |
|||
// 最大输入长度,设置为 -1 的时候不限制最大长度
|
|||
maxlength: { |
|||
type: [String, Number], |
|||
default: uni.$u.props.textarea.maxlength, |
|||
}, |
|||
// 边框类型,surround-四周边框,bottom-底部边框
|
|||
border: { |
|||
type: String, |
|||
default: uni.$u.props.textarea.border, |
|||
}, |
|||
// 用于处理或者过滤输入框内容的方法
|
|||
formatter: { |
|||
type: [Function, null], |
|||
default: uni.$u.props.textarea.formatter, |
|||
}, |
|||
// 是否忽略组件内对文本合成系统事件的处理
|
|||
ignoreCompositionEvent: { |
|||
type: Boolean, |
|||
default: true, |
|||
}, |
|||
}, |
|||
}; |
|||
>>>>>>> fb3b4fc780fb389b9972fb75a2a499f29694144b |
|||
@ -0,0 +1,242 @@ |
|||
<<<<<<< HEAD |
|||
======= |
|||
<template> |
|||
<view class="u-textarea" :class="textareaClass" :style="[textareaStyle]"> |
|||
<textarea |
|||
class="u-textarea__field" |
|||
:value="innerValue" |
|||
:style="{ height: $u.addUnit(height) }" |
|||
:placeholder="placeholder" |
|||
:placeholder-style="$u.addStyle(placeholderStyle, 'string')" |
|||
:placeholder-class="placeholderClass" |
|||
:disabled="disabled" |
|||
:focus="focus" |
|||
:autoHeight="autoHeight" |
|||
:fixed="fixed" |
|||
:cursorSpacing="cursorSpacing" |
|||
:cursor="cursor" |
|||
:showConfirmBar="showConfirmBar" |
|||
:selectionStart="selectionStart" |
|||
:selectionEnd="selectionEnd" |
|||
:adjustPosition="adjustPosition" |
|||
:disableDefaultPadding="disableDefaultPadding" |
|||
:holdKeyboard="holdKeyboard" |
|||
:maxlength="maxlength" |
|||
:confirmType="confirmType" |
|||
:ignoreCompositionEvent="ignoreCompositionEvent" |
|||
@focus="onFocus" |
|||
@blur="onBlur" |
|||
@linechange="onLinechange" |
|||
@input="onInput" |
|||
@confirm="onConfirm" |
|||
@keyboardheightchange="onKeyboardheightchange" |
|||
></textarea> |
|||
<text |
|||
class="u-textarea__count" |
|||
:style="{ |
|||
'background-color': disabled ? 'transparent' : '#fff', |
|||
}" |
|||
v-if="count" |
|||
>{{ innerValue.length }}/{{ maxlength }}</text |
|||
> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import props from './props.js'; |
|||
/** |
|||
* Textarea 文本域 |
|||
* @description 文本域此组件满足了可能出现的表单信息补充,编辑等实际逻辑的功能,内置了字数校验等 |
|||
* @tutorial https://www.uviewui.com/components/textarea.html |
|||
* |
|||
* @property {String | Number} value 输入框的内容 |
|||
* @property {String | Number} placeholder 输入框为空时占位符 |
|||
* @property {String} placeholderClass 指定placeholder的样式类,注意页面或组件的style中写了scoped时,需要在类名前写::v-deep ( 默认 'input-placeholder' ) |
|||
* @property {String | Object} placeholderStyle 指定placeholder的样式,字符串/对象形式,如"color: red;" |
|||
* @property {String | Number} height 输入框高度(默认 70 ) |
|||
* @property {String} confirmType 设置键盘右下角按钮的文字,仅微信小程序,App-vue和H5有效(默认 'done' ) |
|||
* @property {Boolean} disabled 是否禁用(默认 false ) |
|||
* @property {Boolean} count 是否显示统计字数(默认 false ) |
|||
* @property {Boolean} focus 是否自动获取焦点,nvue不支持,H5取决于浏览器的实现(默认 false ) |
|||
* @property {Boolean | Function} autoHeight 是否自动增加高度(默认 false ) |
|||
* @property {Boolean} fixed 如果textarea是在一个position:fixed的区域,需要显示指定属性fixed为true(默认 false ) |
|||
* @property {Number} cursorSpacing 指定光标与键盘的距离(默认 0 ) |
|||
* @property {String | Number} cursor 指定focus时的光标位置 |
|||
* @property {Function} formatter 内容式化函数 |
|||
* @property {Boolean} showConfirmBar 是否显示键盘上方带有”完成“按钮那一栏,(默认 true ) |
|||
* @property {Number} selectionStart 光标起始位置,自动聚焦时有效,需与selection-end搭配使用,(默认 -1 ) |
|||
* @property {Number | Number} selectionEnd 光标结束位置,自动聚焦时有效,需与selection-start搭配使用(默认 -1 ) |
|||
* @property {Boolean} adjustPosition 键盘弹起时,是否自动上推页面(默认 true ) |
|||
* @property {Boolean | Number} disableDefaultPadding 是否去掉 iOS 下的默认内边距,只微信小程序有效(默认 false ) |
|||
* @property {Boolean} holdKeyboard focus时,点击页面的时候不收起键盘,只微信小程序有效(默认 false ) |
|||
* @property {String | Number} maxlength 最大输入长度,设置为 -1 的时候不限制最大长度(默认 140 ) |
|||
* @property {String} border 边框类型,surround-四周边框,none-无边框,bottom-底部边框(默认 'surround' ) |
|||
* @property {Boolean} ignoreCompositionEvent 是否忽略组件内对文本合成系统事件的处理 |
|||
* |
|||
* @event {Function(e)} focus 输入框聚焦时触发,event.detail = { value, height },height 为键盘高度 |
|||
* @event {Function(e)} blur 输入框失去焦点时触发,event.detail = {value, cursor} |
|||
* @event {Function(e)} linechange 输入框行数变化时调用,event.detail = {height: 0, heightRpx: 0, lineCount: 0} |
|||
* @event {Function(e)} input 当键盘输入时,触发 input 事件 |
|||
* @event {Function(e)} confirm 点击完成时, 触发 confirm 事件 |
|||
* @event {Function(e)} keyboardheightchange 键盘高度发生变化的时候触发此事件 |
|||
* @example <u--textarea v-model="value1" placeholder="请输入内容" ></u--textarea> |
|||
*/ |
|||
export default { |
|||
name: 'u-textarea', |
|||
mixins: [uni.$u.mpMixin, uni.$u.mixin, props], |
|||
data() { |
|||
return { |
|||
// 输入框的值 |
|||
innerValue: '', |
|||
// 是否处于获得焦点状态 |
|||
focused: false, |
|||
// value是否第一次变化,在watch中,由于加入immediate属性,会在第一次触发,此时不应该认为value发生了变化 |
|||
firstChange: true, |
|||
// value绑定值的变化是由内部还是外部引起的 |
|||
changeFromInner: false, |
|||
// 过滤处理方法 |
|||
innerFormatter: (value) => value, |
|||
}; |
|||
}, |
|||
watch: { |
|||
value: { |
|||
immediate: true, |
|||
handler(newVal, oldVal) { |
|||
this.innerValue = newVal; |
|||
/* #ifdef H5 */ |
|||
// 在H5中,外部value变化后,修改input中的值,不会触发@input事件,此时手动调用值变化方法 |
|||
if ( |
|||
this.firstChange === false && |
|||
this.changeFromInner === false |
|||
) { |
|||
this.valueChange(); |
|||
} |
|||
/* #endif */ |
|||
this.firstChange = false; |
|||
// 重置changeFromInner的值为false,标识下一次引起默认为外部引起的 |
|||
this.changeFromInner = false; |
|||
}, |
|||
}, |
|||
}, |
|||
computed: { |
|||
// 组件的类名 |
|||
textareaClass() { |
|||
let classes = [], |
|||
{ border, disabled, shape } = this; |
|||
border === 'surround' && |
|||
(classes = classes.concat(['u-border', 'u-textarea--radius'])); |
|||
border === 'bottom' && |
|||
(classes = classes.concat([ |
|||
'u-border-bottom', |
|||
'u-textarea--no-radius', |
|||
])); |
|||
disabled && classes.push('u-textarea--disabled'); |
|||
return classes.join(' '); |
|||
}, |
|||
// 组件的样式 |
|||
textareaStyle() { |
|||
const style = {}; |
|||
// #ifdef APP-NVUE |
|||
// 由于textarea在安卓nvue上的差异性,需要额外再调整其内边距 |
|||
if (uni.$u.os() === 'android') { |
|||
style.paddingTop = '6px'; |
|||
style.paddingLeft = '9px'; |
|||
style.paddingBottom = '3px'; |
|||
style.paddingRight = '6px'; |
|||
} |
|||
// #endif |
|||
return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle)); |
|||
}, |
|||
}, |
|||
methods: { |
|||
// 在微信小程序中,不支持将函数当做props参数,故只能通过ref形式调用 |
|||
setFormatter(e) { |
|||
this.innerFormatter = e; |
|||
}, |
|||
onFocus(e) { |
|||
this.$emit('focus', e); |
|||
}, |
|||
onBlur(e) { |
|||
this.$emit('blur', e); |
|||
// 尝试调用u-form的验证方法 |
|||
uni.$u.formValidate(this, 'blur'); |
|||
}, |
|||
onLinechange(e) { |
|||
this.$emit('linechange', e); |
|||
}, |
|||
onInput(e) { |
|||
let { value = '' } = e.detail || {}; |
|||
// 格式化过滤方法 |
|||
const formatter = this.formatter || this.innerFormatter; |
|||
const formatValue = formatter(value); |
|||
// 为了避免props的单向数据流特性,需要先将innerValue值设置为当前值,再在$nextTick中重新赋予设置后的值才有效 |
|||
this.innerValue = value; |
|||
this.$nextTick(() => { |
|||
this.innerValue = formatValue; |
|||
this.valueChange(); |
|||
}); |
|||
}, |
|||
// 内容发生变化,进行处理 |
|||
valueChange() { |
|||
const value = this.innerValue; |
|||
this.$nextTick(() => { |
|||
this.$emit('input', value); |
|||
// 标识value值的变化是由内部引起的 |
|||
this.changeFromInner = true; |
|||
this.$emit('change', value); |
|||
// 尝试调用u-form的验证方法 |
|||
uni.$u.formValidate(this, 'change'); |
|||
}); |
|||
}, |
|||
onConfirm(e) { |
|||
this.$emit('confirm', e); |
|||
}, |
|||
onKeyboardheightchange(e) { |
|||
this.$emit('keyboardheightchange', e); |
|||
}, |
|||
}, |
|||
}; |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
@import '../../libs/css/components.scss'; |
|||
|
|||
.u-textarea { |
|||
border-radius: 4px; |
|||
background-color: #fff; |
|||
position: relative; |
|||
@include flex; |
|||
flex: 1; |
|||
padding: 9px; |
|||
|
|||
&--radius { |
|||
border-radius: 4px; |
|||
} |
|||
|
|||
&--no-radius { |
|||
border-radius: 0; |
|||
} |
|||
|
|||
&--disabled { |
|||
background-color: #f5f7fa; |
|||
} |
|||
|
|||
&__field { |
|||
flex: 1; |
|||
font-size: 15px; |
|||
color: $u-content-color; |
|||
width: 100%; |
|||
} |
|||
|
|||
&__count { |
|||
position: absolute; |
|||
right: 5px; |
|||
bottom: 2px; |
|||
font-size: 12px; |
|||
color: $u-tips-color; |
|||
background-color: #ffffff; |
|||
padding: 1px 4px; |
|||
} |
|||
} |
|||
</style> |
|||
>>>>>>> fb3b4fc780fb389b9972fb75a2a499f29694144b |
|||