Compare commits
22 Commits
main
...
feat/meeti
Author | SHA1 | Date |
---|---|---|
|
b5139d1869 | 8 months ago |
|
b5ec88ba76 | 8 months ago |
|
a7d4d4fc42 | 8 months ago |
|
452f8764a2 | 8 months ago |
|
4f9587a7ec | 8 months ago |
|
15b627ed8f | 8 months ago |
|
e436f05b55 | 8 months ago |
|
498a83aa7e | 8 months ago |
|
f9ec02c188 | 8 months ago |
|
a1a6390215 | 8 months ago |
|
bdf783850e | 8 months ago |
|
0f5a93a600 | 8 months ago |
|
a52421b800 | 8 months ago |
|
c0f75ff293 | 8 months ago |
|
a5d2418d35 | 8 months ago |
|
7b70fd7cc9 | 8 months ago |
|
6c5a05ff97 | 8 months ago |
|
139f7fce79 | 8 months ago |
|
48201ebff7 | 9 months ago |
|
a37992d6d7 | 9 months ago |
|
da7392e320 | 9 months ago |
|
f9be0928dd | 9 months ago |
@ -0,0 +1,67 @@ |
|||||||
|
|
||||||
|
/** |
||||||
|
* 页面跳转 |
||||||
|
* @author 深圳前海万联科技有限公司 <www.wanlshop.com> |
||||||
|
* |
||||||
|
* @param {Object} url 需要跳转的应用内非 tabBar 的页面的路径 |
||||||
|
* @param {Object} animationType 窗口显示的动画效果 |
||||||
|
* @param {Object} animationDuration 窗口动画持续时间,单位为 ms |
||||||
|
*/ |
||||||
|
export const to = (url, animationType = 'pop-in', animationDuration = 300) => { |
||||||
|
on(url); |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* 打开任意链接 |
||||||
|
* @author 深圳前海万联科技有限公司 <www.wanlshop.com> |
||||||
|
* |
||||||
|
* @param {Object} url 页面地址 |
||||||
|
*/ |
||||||
|
export const on = (url, replace = false, reLaunch = false) => { |
||||||
|
// url = decodeURIComponent(url);
|
||||||
|
console.log('onnnnn', url); |
||||||
|
if (url.indexOf('pages') === 0) { |
||||||
|
url = `/${url}`; |
||||||
|
} |
||||||
|
if (!/^\/?pages/.test(url) && url.indexOf('./') === -1) { |
||||||
|
url = `./${url}`; |
||||||
|
} |
||||||
|
// const in_tabar = PAGES_JSON.tabBar.list.find((v, idx, obj) => {
|
||||||
|
// return url.replace('/pages', 'pages') == v.pagePath;
|
||||||
|
// });
|
||||||
|
// 关闭所有页面,跳转链接
|
||||||
|
console.log(in_tabar, url); |
||||||
|
const in_tabar =false |
||||||
|
if (in_tabar) { |
||||||
|
uni.switchTab({ |
||||||
|
url: url, |
||||||
|
}); |
||||||
|
} else { |
||||||
|
const animationType = 'pop-in'; |
||||||
|
const animationDuration = 300; |
||||||
|
|
||||||
|
let param = { |
||||||
|
url, |
||||||
|
animationType, |
||||||
|
animationDuration, |
||||||
|
success: function (res) { |
||||||
|
// wanlshop_config.debug ? console.log(res) : '';
|
||||||
|
}, |
||||||
|
fail: function (e) { |
||||||
|
// wanlshop_config.debug ? console.log(e) : '';
|
||||||
|
}, |
||||||
|
}; |
||||||
|
if (replace) { |
||||||
|
uni.redirectTo(param); |
||||||
|
} else if (reLaunch) { |
||||||
|
uni.reLaunch(param); |
||||||
|
} else { |
||||||
|
uni.navigateTo(param); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
export default { |
||||||
|
to, |
||||||
|
on, |
||||||
|
} |
@ -0,0 +1,163 @@ |
|||||||
|
<template> |
||||||
|
<view |
||||||
|
class="top-nav" |
||||||
|
:class="[isFixed ? 'pf' : 'p-relative']" |
||||||
|
:style="{ |
||||||
|
backgroundColor: backgroundColor, |
||||||
|
}" |
||||||
|
> |
||||||
|
<!-- 顶部 --> |
||||||
|
<view class="nav" :style="{ height: navHeight + 'px' }"> |
||||||
|
<view |
||||||
|
:style="{ |
||||||
|
paddingTop: statusHeight + 'px', |
||||||
|
color: color, |
||||||
|
}" |
||||||
|
class="title" |
||||||
|
> |
||||||
|
<view class="content"> |
||||||
|
<!-- <image |
||||||
|
v-if="iconType == 1" |
||||||
|
class="left-jiantou" |
||||||
|
:src="$metaCommon.static_url('left_back01.png')" |
||||||
|
mode="aspectFill" |
||||||
|
@click="goBack" |
||||||
|
/> |
||||||
|
<image |
||||||
|
v-if="iconType == 2" |
||||||
|
class="left-jiantou" |
||||||
|
:src="$metaCommon.static_url('left_back02.png')" |
||||||
|
mode="aspectFill" |
||||||
|
@click="goBack" |
||||||
|
/> |
||||||
|
<image |
||||||
|
v-if="iconType == 3" |
||||||
|
class="left-jiantou" |
||||||
|
:src="$metaCommon.static_url('left_back03.png')" |
||||||
|
mode="aspectFill" |
||||||
|
@click="goBack" |
||||||
|
/> --> |
||||||
|
<text v-if="iconType == 1" class="left-jiantou">1</text> |
||||||
|
<text v-if="iconType == 2" class="left-jiantou">2</text> |
||||||
|
<text v-if="iconType == 3" class="left-jiantou">3</text> |
||||||
|
|
||||||
|
</view> |
||||||
|
<view |
||||||
|
class="font-700 font-size-34rpx" |
||||||
|
:style="{ |
||||||
|
lineHeight: titleHeight + 'px', |
||||||
|
}" |
||||||
|
> |
||||||
|
{{ title }} |
||||||
|
<slot></slot> |
||||||
|
</view> |
||||||
|
<view class="right-content"> |
||||||
|
<slot name="right"></slot> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
/** |
||||||
|
* shoproEmpty- 数据为空页 |
||||||
|
* @property {String} title - 标题 |
||||||
|
* @property {String} color - 标题颜色 |
||||||
|
* @property {String} iconType - 返回箭头的类型选择 (1==透明 2==黑色) |
||||||
|
* @property {String} delta - 返回的层级 |
||||||
|
* @property {Boolean} status - 是否启用自定义事件 |
||||||
|
* @property {Boolean} isFixed - 是否启用顶部固定定位 |
||||||
|
*/ |
||||||
|
|
||||||
|
import { sysInfo } from "../../meeting/utils/systeminfo" |
||||||
|
export default { |
||||||
|
name: "", |
||||||
|
data() { |
||||||
|
return { |
||||||
|
navHeight: sysInfo.customBarHeight, |
||||||
|
statusHeight: sysInfo.statusBarHeight, |
||||||
|
titleHeight: sysInfo.titleBarHeight, |
||||||
|
}; |
||||||
|
}, |
||||||
|
props: { |
||||||
|
title: { |
||||||
|
type: String, |
||||||
|
default: "", |
||||||
|
}, |
||||||
|
color: { |
||||||
|
type: String, |
||||||
|
default: "", |
||||||
|
}, |
||||||
|
iconType: { |
||||||
|
type: [String, Number], |
||||||
|
default: 1, |
||||||
|
}, |
||||||
|
delta: { |
||||||
|
type: [Number, String], |
||||||
|
default: 1, |
||||||
|
}, |
||||||
|
status: { |
||||||
|
type: Boolean, |
||||||
|
default: true, |
||||||
|
}, |
||||||
|
isFixed: { |
||||||
|
type: Boolean, |
||||||
|
default: true, |
||||||
|
}, |
||||||
|
backgroundColor: { |
||||||
|
type: String, |
||||||
|
default: "none", |
||||||
|
}, |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
goBack() { |
||||||
|
if (this.status) { |
||||||
|
uni.navigateBack({ |
||||||
|
delta: Number(this.delta), |
||||||
|
}); |
||||||
|
} else { |
||||||
|
this.$emit("goBack"); |
||||||
|
} |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.content { |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
|
||||||
|
.left-jiantou { |
||||||
|
position: absolute; |
||||||
|
width: 48rpx; |
||||||
|
height: 48rpx; |
||||||
|
left: 24rpx; |
||||||
|
top: 20rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.top-nav { |
||||||
|
width: 100%; |
||||||
|
// position: fixed; |
||||||
|
z-index: 100001; |
||||||
|
box-sizing: border-box; |
||||||
|
} |
||||||
|
|
||||||
|
.pf { |
||||||
|
position: fixed; |
||||||
|
} |
||||||
|
|
||||||
|
.p-relative { |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
|
||||||
|
.title { |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
.right-content { |
||||||
|
position: absolute; |
||||||
|
right: 24rpx; |
||||||
|
top: 20rpx; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,165 @@ |
|||||||
|
<template> |
||||||
|
<view class="mask" v-if="dialogShow" @click="handleHide"> |
||||||
|
<view class="content"> |
||||||
|
<view class="bg"> |
||||||
|
<view class="title">{{ dialogTitle }}</view> |
||||||
|
<rich-text |
||||||
|
class="text-[#4B4C50] text-[28rpx]" |
||||||
|
:nodes="dialogContent" |
||||||
|
:style="{ |
||||||
|
textAlign: textAlign, |
||||||
|
}" |
||||||
|
></rich-text> |
||||||
|
</view> |
||||||
|
<slot></slot> |
||||||
|
<view |
||||||
|
v-if="btnType == 1" |
||||||
|
class="bg-[#D6B184] text-[#24272A] text-center rounded-md h-[80rpx] leading-[80rpx] font-bold mt-[48rpx]" |
||||||
|
@click="handleHide" |
||||||
|
>确定</view |
||||||
|
> |
||||||
|
<view class="flex justify-between pt-44" v-if="btnType == 2"> |
||||||
|
<view class="btn cancel-btn" @click="handleCancel"> |
||||||
|
{{ CancelText }}</view |
||||||
|
> |
||||||
|
<view |
||||||
|
class="btn" |
||||||
|
:style="{ |
||||||
|
background: backgroundColor, |
||||||
|
color: color, |
||||||
|
}" |
||||||
|
@click="handleConfirm" |
||||||
|
> |
||||||
|
{{ ConfirmText }}</view |
||||||
|
> |
||||||
|
</view> |
||||||
|
<!-- 登陆弹框 --> |
||||||
|
<view class="flex justify-between mt-[50rpx]" v-if="btnType == 3"> |
||||||
|
<button |
||||||
|
class="w-[226rpx] h-[80rpx] rounded-xl text-[30rpx] font-bold text-center leading-[80rpx]" |
||||||
|
:style="{ |
||||||
|
background: backgroundColor, |
||||||
|
color: color, |
||||||
|
}" |
||||||
|
open-type="getPhoneNumber" |
||||||
|
@getphonenumber="getUserPhone" |
||||||
|
> |
||||||
|
确认 |
||||||
|
</button> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
props: { |
||||||
|
dialogShow: { |
||||||
|
type: Boolean, |
||||||
|
default: false, |
||||||
|
}, |
||||||
|
dialogTitle: { |
||||||
|
type: String, |
||||||
|
default: "", |
||||||
|
}, |
||||||
|
dialogContent: { |
||||||
|
type: String, |
||||||
|
default: "", |
||||||
|
}, |
||||||
|
btnType: { |
||||||
|
type: Number, |
||||||
|
default: 1, |
||||||
|
}, |
||||||
|
CancelText: { |
||||||
|
type: String, |
||||||
|
default: "取消", |
||||||
|
}, |
||||||
|
ConfirmText: { |
||||||
|
type: String, |
||||||
|
default: "确定", |
||||||
|
}, |
||||||
|
backgroundColor: { |
||||||
|
type: String, |
||||||
|
default: "#1467FF", |
||||||
|
}, |
||||||
|
color: { |
||||||
|
type: String, |
||||||
|
default: "#fff", |
||||||
|
}, |
||||||
|
textAlign: { |
||||||
|
type: String, |
||||||
|
default: "left", |
||||||
|
}, |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return {}; |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
handleHide() { |
||||||
|
this.$emit("handleHide"); |
||||||
|
}, |
||||||
|
handleCancel() { |
||||||
|
this.$emit("handleCancel"); |
||||||
|
}, |
||||||
|
handleConfirm() { |
||||||
|
this.$emit("handleConfirm"); |
||||||
|
}, |
||||||
|
getUserPhone(e) { |
||||||
|
this.$emit("getUserPhone", e); |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
@import "../../meeting/common.scss"; |
||||||
|
.title { |
||||||
|
// text-[#202124] text-[30rpx] font-bold text-center mb-[32rpx] |
||||||
|
color: #23262b; |
||||||
|
font-size: 30rpx; |
||||||
|
font-weight: bold; |
||||||
|
text-align: center; |
||||||
|
margin-bottom: 32rpx; |
||||||
|
} |
||||||
|
.btn { |
||||||
|
width: 226rpx; |
||||||
|
height: 80rpx; |
||||||
|
line-height: 80rpx; |
||||||
|
text-align: center; |
||||||
|
font-weight: 700; |
||||||
|
font-size: 30rpx; |
||||||
|
border-radius: 16rpx; |
||||||
|
box-sizing: border-box; |
||||||
|
} |
||||||
|
.cancel-btn { |
||||||
|
border: 4rpx solid #1467ff; |
||||||
|
color: #1467ff; |
||||||
|
} |
||||||
|
.mask { |
||||||
|
position: fixed; |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
background: rgba(0, 0, 0, 0.5); |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
z-index: 100002; |
||||||
|
|
||||||
|
.content { |
||||||
|
width: 600rpx; |
||||||
|
border-radius: 24rpx; |
||||||
|
background: #fff; |
||||||
|
box-sizing: border-box; |
||||||
|
padding: 48rpx 60rpx 32rpx; |
||||||
|
// background-image: url(#{$uni-base-url}icon28.png); |
||||||
|
background-size: 100% 214rpx; |
||||||
|
background-position: top; |
||||||
|
background-repeat: no-repeat; |
||||||
|
margin: 0 auto; |
||||||
|
margin-top: 500rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.borderColor { |
||||||
|
border: 2rpx solid #d6b184; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,37 @@ |
|||||||
|
|
||||||
|
<template> |
||||||
|
<u-sticky :customNavHeight="0"> |
||||||
|
<view |
||||||
|
:style="{ |
||||||
|
background: bg, |
||||||
|
}" |
||||||
|
:class="isPadding ? 'px-[24rpx]' : ''" |
||||||
|
class="mb-[20rpx]" |
||||||
|
> |
||||||
|
<slot></slot> |
||||||
|
</view> |
||||||
|
</u-sticky> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: "", |
||||||
|
data() { |
||||||
|
return {}; |
||||||
|
}, |
||||||
|
props: { |
||||||
|
bg: { |
||||||
|
type: String, |
||||||
|
default: "transparent", |
||||||
|
}, |
||||||
|
isPadding: { |
||||||
|
type: Boolean, |
||||||
|
default: true, |
||||||
|
}, |
||||||
|
}, |
||||||
|
onLoad(options) {}, |
||||||
|
methods: {}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,42 @@ |
|||||||
|
.mb-20{ |
||||||
|
margin-bottom: 20rpx; |
||||||
|
} |
||||||
|
.mb-24{ |
||||||
|
margin-bottom: 24rpx; |
||||||
|
} |
||||||
|
.mb-30{ |
||||||
|
margin-bottom: 30rpx; |
||||||
|
} |
||||||
|
.mb-40{ |
||||||
|
margin-bottom: 40rpx; |
||||||
|
} |
||||||
|
.mb-48{ |
||||||
|
margin-bottom: 48rpx; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
.pt-44{ |
||||||
|
padding-top: 44rpx; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/* ========布局========== */ |
||||||
|
.flex{ |
||||||
|
display: flex; |
||||||
|
} |
||||||
|
.justify-center{ |
||||||
|
justify-content: center; |
||||||
|
} |
||||||
|
.justify-between{ |
||||||
|
justify-content: space-between; |
||||||
|
} |
||||||
|
.items-center{ |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
/* -=======背景======= */ |
||||||
|
// .bg{ |
||||||
|
// min-height: 100vh; |
||||||
|
// background-image: url('/static/image/bg.png'); |
||||||
|
// background-repeat: no-repeat; |
||||||
|
// background-size: cover; |
||||||
|
// } |
@ -0,0 +1,96 @@ |
|||||||
|
<template> |
||||||
|
<view> |
||||||
|
<view class="record-item mb-24"> |
||||||
|
<view class="flex justify-between items-center"> |
||||||
|
<view class="mb-20 title"> |
||||||
|
这是一个标题 |
||||||
|
<text class="status" :class="status[1]"> 这是状态 </text> |
||||||
|
</view> |
||||||
|
<view @click.stop="upMask"> 1111 </view> |
||||||
|
</view> |
||||||
|
<view class="flex justify-between items-center txt"> |
||||||
|
<view> 这是时间 </view> |
||||||
|
<view class="">这是时长</view> |
||||||
|
</view> |
||||||
|
<view class="mask" v-if="popup"> |
||||||
|
<view>导出</view> |
||||||
|
<view>重命名</view> |
||||||
|
<view>删除</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
status: ["wait", "success"], |
||||||
|
popup: false, |
||||||
|
}; |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
upMask() { |
||||||
|
this.popup = !this.popup; |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
@import "../common.scss"; |
||||||
|
|
||||||
|
.status { |
||||||
|
// line-height: 40rpx; |
||||||
|
padding: 4rpx 16rpx; |
||||||
|
border: 1rpx solid; |
||||||
|
border-radius: 8rpx; |
||||||
|
margin-left: 12rpx; |
||||||
|
font-weight: 400; |
||||||
|
font-size: 24rpx; |
||||||
|
} |
||||||
|
.wait { |
||||||
|
border: #1467ff 1rpx solid; |
||||||
|
color: #1467ff; |
||||||
|
background-color: #1466ff11; |
||||||
|
} |
||||||
|
.success { |
||||||
|
border: #1eb066 1rpx solid; |
||||||
|
color: #1eb066; |
||||||
|
background-color: #1eb06611; |
||||||
|
} |
||||||
|
.mask { |
||||||
|
position: absolute; |
||||||
|
width: 168rpx; |
||||||
|
height: 232rpx; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 16rpx; |
||||||
|
top: 80rpx; |
||||||
|
right: 16rpx; |
||||||
|
padding: 24rpx; |
||||||
|
box-sizing: border-box; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: space-around; |
||||||
|
} |
||||||
|
|
||||||
|
.record-item { |
||||||
|
position: relative; |
||||||
|
// height: 168rpx; |
||||||
|
border-radius: 24rpx; |
||||||
|
border: 2rpx #fff solid; |
||||||
|
padding: 32rpx 24rpx; |
||||||
|
padding-bottom: 36rpx; |
||||||
|
.title { |
||||||
|
font-weight: 700; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #23262b; |
||||||
|
line-height: 40rpx; |
||||||
|
} |
||||||
|
.txt { |
||||||
|
font-weight: 400; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #4b5158; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,32 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<meet-navbar title="Ai会议助手" :isFixed="false"></meet-navbar> |
||||||
|
|
||||||
|
<div> |
||||||
|
<u-button :customStyle="customStyle1">立即开始会议</u-button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
|
||||||
|
data() { |
||||||
|
return { |
||||||
|
customStyle1: { |
||||||
|
width: "558rpx", |
||||||
|
height: "80rpx", |
||||||
|
borderRadius: "16rpx", |
||||||
|
backgroundColor: "#1467FF", |
||||||
|
color: '#fff', |
||||||
|
fontSize: "30rpx", |
||||||
|
fontWeight: "700", |
||||||
|
}, |
||||||
|
}; |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,176 @@ |
|||||||
|
<template> |
||||||
|
<view class="bg container"> |
||||||
|
<meet-sticky :bg="bg"> |
||||||
|
<meet-navbar title="" :isFixed="false"></meet-navbar> |
||||||
|
</meet-sticky> |
||||||
|
<view class="content"> |
||||||
|
<view v-if="type == 1"> |
||||||
|
<view class="text-1">密码登录</view> |
||||||
|
<view class="input-1"> |
||||||
|
<image class="img" src="/static/image/login/icon1.png"></image> |
||||||
|
<u--input placeholder="请输入手机号" border="surround" v-model="mobile" clearable></u--input> |
||||||
|
</view> |
||||||
|
<view class="input-1"> |
||||||
|
<image class="img" src="/static/image/login/icon2.png"></image> |
||||||
|
<u--input placeholder="请输入密码" border="surround" v-model="mobile" clearable></u--input> |
||||||
|
</view> |
||||||
|
<view class="loginBtn">登陆</view> |
||||||
|
<view class="text-2">验证码登录</view> |
||||||
|
</view> |
||||||
|
<view v-if="type == 2"> |
||||||
|
<view class="text-1 mb-16">验证码登录</view> |
||||||
|
<view class="text-4">若手机号未注册,我们将为您自动注册</view> |
||||||
|
<view class="input-1"> |
||||||
|
<image class="img" src="/static/image/login/icon1.png"></image> |
||||||
|
<u--input placeholder="请输入手机号" border="surround" v-model="mobile" clearable></u--input> |
||||||
|
</view> |
||||||
|
<view class="input-1"> |
||||||
|
<image class="img" src="/static/image/login/icon6.png"></image> |
||||||
|
<u--input placeholder="请输入验证码" border="surround" v-model="mobile" clearable></u--input> |
||||||
|
<view class="text-3">获取验证码</view> |
||||||
|
</view> |
||||||
|
<view class="loginBtn">登陆</view> |
||||||
|
<view class="text-2">密码登录</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<!-- footer --> |
||||||
|
<view class="footer"> |
||||||
|
<image class="img01" src="/static/image/login/icon3.png"></image> |
||||||
|
<view class="footer-text">使用微信登录</view> |
||||||
|
<view class="footer-icon"> |
||||||
|
<image class="img02" src="/static/image/login/icon4.png"></image> |
||||||
|
<view class="footer-text-1">已阅读并接受《AI会议助手隐私用户协议》</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
bg: "", |
||||||
|
mobile: "", |
||||||
|
type: 2,//1密码 2验证码 |
||||||
|
}; |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
|
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
@import "../common.scss"; |
||||||
|
|
||||||
|
.container { |
||||||
|
min-height: 100vh; |
||||||
|
background-color: #d1dcfe; |
||||||
|
padding: 20rpx 0; |
||||||
|
|
||||||
|
.content { |
||||||
|
box-sizing: border-box; |
||||||
|
padding: 0 64rpx; |
||||||
|
padding-top: 100rpx; |
||||||
|
|
||||||
|
.text-1 { |
||||||
|
font-size: 40rpx; |
||||||
|
font-weight: bold; |
||||||
|
color: #23262B; |
||||||
|
margin-bottom: 48rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.input-1 { |
||||||
|
border: 1px solid #fff; |
||||||
|
border-radius: 24rpx; |
||||||
|
height: 88rpx; |
||||||
|
background: #F0F7FF; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
box-sizing: border-box; |
||||||
|
padding: 0 32rpx; |
||||||
|
margin-bottom: 32rpx; |
||||||
|
|
||||||
|
.img { |
||||||
|
width: 36rpx; |
||||||
|
height: 36rpx; |
||||||
|
} |
||||||
|
|
||||||
|
::v-deep .u-input { |
||||||
|
border: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.text-3 { |
||||||
|
color: #1467FF; |
||||||
|
font-size: 28rpx; |
||||||
|
width: 150rpx; |
||||||
|
display: block; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.text-4 { |
||||||
|
color: #4B5158; |
||||||
|
font-size: 28rpx; |
||||||
|
margin-bottom: 48rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.mb-16 { |
||||||
|
margin-bottom: 16rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.loginBtn { |
||||||
|
background: #1467FF; |
||||||
|
border-radius: 16rpx; |
||||||
|
height: 80rpx; |
||||||
|
line-height: 80rpx; |
||||||
|
text-align: center; |
||||||
|
color: #fff; |
||||||
|
font-size: 30rpx; |
||||||
|
margin-top: 88rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.text-2 { |
||||||
|
text-align: center; |
||||||
|
color: #1467FF; |
||||||
|
font-size: 28rpx; |
||||||
|
margin-top: 40rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.footer { |
||||||
|
position: fixed; |
||||||
|
bottom: 100rpx; |
||||||
|
width: 100%; |
||||||
|
box-sizing: border-box; |
||||||
|
.img01 { |
||||||
|
width: 64rpx; |
||||||
|
height: 64rpx; |
||||||
|
display: block; |
||||||
|
margin: 0 auto; |
||||||
|
} |
||||||
|
|
||||||
|
.footer-text { |
||||||
|
text-align: center; |
||||||
|
margin-top: 6rpx; |
||||||
|
color: #4B5158; |
||||||
|
font-size: 28rpx; |
||||||
|
} |
||||||
|
.footer-icon{ |
||||||
|
padding: 0 64rpx; |
||||||
|
display: flex; |
||||||
|
box-sizing: border-box; |
||||||
|
align-items: center; |
||||||
|
margin-top: 40rpx; |
||||||
|
.img02{ |
||||||
|
width: 32rpx; |
||||||
|
height: 32rpx; |
||||||
|
margin-right: 16rpx; |
||||||
|
} |
||||||
|
.footer-text-1{ |
||||||
|
color: #4B5158; |
||||||
|
font-size: 28rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,263 @@ |
|||||||
|
<template> |
||||||
|
<div class="container"> |
||||||
|
<meet-sticky :bg="bg"> |
||||||
|
<meet-navbar title="会议中" :isFixed="false"></meet-navbar> |
||||||
|
</meet-sticky> |
||||||
|
<view class="list" v-for="(item, index) in 10"> |
||||||
|
<view class="flex-left color-1">1</view> |
||||||
|
<view class="flex-child"> |
||||||
|
<view class="flex-center">我公司碳中和具体的应用场景包括以下几方面:1.碳丝路APP-全民低碳场景的数据收集 碳普惠应用。 2.全国性碳交易平台数据。</view> |
||||||
|
<view class="flex-right">5"</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="footer"> |
||||||
|
<image class="icon01" src="/static/image/online/online.gif"></image> |
||||||
|
<view class="footer-center"> |
||||||
|
<view class="text-1">正在录音中</view> |
||||||
|
<view class="text-2"><span>00:12</span>/02:00:00</view> |
||||||
|
</view> |
||||||
|
<view class="footer-icon" @click="startRecord()" v-if="isRecording == false"> |
||||||
|
<image class="img" src="/static/image/online/play.png"></image> |
||||||
|
<view class="text-1">开始</view> |
||||||
|
</view> |
||||||
|
<view class="footer-icon" @click="endRecord()" v-if="isRecording == true"> |
||||||
|
<image class="img" src="/static/image/online/pause.png"></image> |
||||||
|
<view class="text-1">结束</view> |
||||||
|
</view> |
||||||
|
<view class="footer-icon"> |
||||||
|
<image class="img" src="/static/image/online/stop.png"></image> |
||||||
|
<view class="text-1">结束</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<!-- 弹框 --> |
||||||
|
<meet-pop :dialogShow="popConfig.show" :btnType="popConfig.btnType" :dialogTitle="popConfig.title" |
||||||
|
:CancelText="popConfig.CancelText" :ConfirmText="popConfig.ConfirmText" @handleConfirm="confirm" |
||||||
|
@handleCancel="cancel"> |
||||||
|
<view class="popClass"> |
||||||
|
结束后无法在本记录继续录音 |
||||||
|
</view> |
||||||
|
</meet-pop> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
const recorderManager = uni.getRecorderManager(); |
||||||
|
const innerAudioContext = uni.createInnerAudioContext(); |
||||||
|
innerAudioContext.autoplay = true; |
||||||
|
export default { |
||||||
|
components: { |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
list: [], |
||||||
|
popConfig: { |
||||||
|
show: false, |
||||||
|
btnType: 2, |
||||||
|
title: "确定结束录音吗?", |
||||||
|
CancelText: "在考虑下", |
||||||
|
ConfirmText: "结束录音" |
||||||
|
}, |
||||||
|
//录音 |
||||||
|
recorderManager: null, |
||||||
|
innerAudioContext: {}, |
||||||
|
isRecording: false, |
||||||
|
ws: null, |
||||||
|
webSocketUrl: "", |
||||||
|
VITE_APP_WS: "wss://u140106-8027-537a5c07.westx.seetacloud.com:8443/api/stt/service" |
||||||
|
}; |
||||||
|
}, |
||||||
|
onLoad() { |
||||||
|
// this.recorderManager = uni.getRecorderManager(); |
||||||
|
// console.log('recorderManager', this.recorderManager); |
||||||
|
// innerAudioContext.autoplay = true; |
||||||
|
// console.log("uni.getRecorderManager()", uni.getRecorderManager()) |
||||||
|
// console.log("uni.createInnerAudioContext()", uni.createInnerAudioContext()) |
||||||
|
// let self = this; |
||||||
|
// recorderManager.onStop(function (res) { |
||||||
|
// console.log('recorder stop' + JSON.stringify(res)); |
||||||
|
// self.voicePath = res.tempFilePath; |
||||||
|
// }); |
||||||
|
this.initWebSocket(); |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
async initWebSocket() { |
||||||
|
let url = this.VITE_APP_WS; |
||||||
|
var audio_type = "mic_stream"; |
||||||
|
var hot_words = "碳丝路 元梦空间"; |
||||||
|
var hot_words2 = "碳丝路元梦空间"; |
||||||
|
var language = "zh"; |
||||||
|
var sample_rate = "16000"; |
||||||
|
var timestamp = Math.floor(Date.now() / 1000); |
||||||
|
var api_key = "AT_syAHhLp3vqOA!@+T9Cocxc0^6z@^9"; |
||||||
|
var auth = `api_key=${api_key}&audio_type=${audio_type}&hot_words=${hot_words2}&language=${language}&sample_rate=${sample_rate}&stream=True×tamp=${timestamp}`; |
||||||
|
const sign = await this.sha256(auth); |
||||||
|
url = `${url}?audio_type=${audio_type}&hot_words=${encodeURIComponent(hot_words)}&language=${language}&sample_rate=${sample_rate}×tamp=${timestamp}&api_key=${encodeURIComponent(api_key)}&auth=${sign}`; |
||||||
|
createdWebSocket(url); |
||||||
|
}, |
||||||
|
async sha256(str) { |
||||||
|
// 将输入字符串转换为二进制数据 |
||||||
|
const encoder = new TextEncoder(); |
||||||
|
const data = encoder.encode(str); |
||||||
|
// 调用原生的SubtleCrypto API计算SHA-256哈希 |
||||||
|
return crypto.subtle.digest("SHA-256", data).then(buffer => { |
||||||
|
// 将哈希结果转换为十六进制字符串 |
||||||
|
const hexArray = Array.from(new Uint8Array(buffer)); |
||||||
|
const hexString = hexArray |
||||||
|
.map(byte => byte.toString(16).padStart(2, "0")) |
||||||
|
.join(""); |
||||||
|
return hexString; |
||||||
|
}); |
||||||
|
}, |
||||||
|
confirm() { |
||||||
|
this.popConfig.show = false; |
||||||
|
}, |
||||||
|
cancel() { |
||||||
|
this.popConfig.show = false; |
||||||
|
}, |
||||||
|
startRecord() { |
||||||
|
console.log('开始录音'); |
||||||
|
if (this.isRecording) return; |
||||||
|
this.isRecording = true; |
||||||
|
// const recorderManager = this.recorderManager; |
||||||
|
const options = { |
||||||
|
duration: 60000, // 录音的最大时长,单位 ms |
||||||
|
sampleRate: 8000, // 采样率 |
||||||
|
numberOfChannels: 1, // 录音的 channel 数量 |
||||||
|
encodeBitRate: 44100, // 编码码率 |
||||||
|
format: 'mp3', // 音频格式,支持 'aac' 或 'mp3' |
||||||
|
frameSize: 20 |
||||||
|
}; |
||||||
|
recorderManager.start(options); |
||||||
|
recorderManager.onStart(() => { |
||||||
|
console.log('录音开始'); |
||||||
|
}); |
||||||
|
|
||||||
|
recorderManager.onFrameRecorded((res) => { |
||||||
|
// 实时获取录音进度回调 |
||||||
|
const { frameBuffer } = res; |
||||||
|
console.log(frameBuffer); |
||||||
|
}); |
||||||
|
|
||||||
|
}, |
||||||
|
endRecord() { |
||||||
|
this.isRecording = false; |
||||||
|
// const recorderManager = this.recorderManager; |
||||||
|
recorderManager.onStop((res) => { |
||||||
|
console.log('录音结束', res.tempFilePath); |
||||||
|
}); |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
@import "../common.scss"; |
||||||
|
|
||||||
|
.container { |
||||||
|
min-height: 100vh; |
||||||
|
background-color: #d1dcfe; |
||||||
|
padding: 20rpx 0; |
||||||
|
padding-bottom: 200rpx; |
||||||
|
|
||||||
|
.list { |
||||||
|
display: flex; |
||||||
|
margin-top: 36rpx; |
||||||
|
padding: 0 24rpx; |
||||||
|
|
||||||
|
.flex-left { |
||||||
|
width: 56rpx; |
||||||
|
height: 56rpx; |
||||||
|
font-size: 36rpx; |
||||||
|
line-height: 56rpx; |
||||||
|
text-align: center; |
||||||
|
border-radius: 50%; |
||||||
|
color: #fff; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
|
||||||
|
.color-1 { |
||||||
|
background-color: #70CD9E; |
||||||
|
} |
||||||
|
|
||||||
|
.flex-child { |
||||||
|
display: flex; |
||||||
|
align-items: flex-end; |
||||||
|
flex: 1; |
||||||
|
|
||||||
|
.flex-center { |
||||||
|
|
||||||
|
margin: 0 16rpx 0 16rpx; |
||||||
|
border: 1px solid #fff; |
||||||
|
background-color: rbga(255, 255, 255, 0.5); |
||||||
|
border-radius: 16rpx; |
||||||
|
box-sizing: border-box; |
||||||
|
padding: 16rpx 24rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.flex-right { |
||||||
|
color: #23262B; |
||||||
|
font-size: 28rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
.footer { |
||||||
|
background: rgba(255, 255, 255, 1); |
||||||
|
border-top-right-radius: 40rpx; |
||||||
|
border-top-left-radius: 40rpx; |
||||||
|
position: fixed; |
||||||
|
bottom: 0; |
||||||
|
width: 100%; |
||||||
|
height: 180rpx; |
||||||
|
display: flex; |
||||||
|
box-sizing: border-box; |
||||||
|
padding: 12rpx 24rpx; |
||||||
|
|
||||||
|
.icon01 { |
||||||
|
width: 88rpx; |
||||||
|
height: 88rpx; |
||||||
|
border-radius: 24rpx; |
||||||
|
margin-right: 24rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.footer-center { |
||||||
|
flex: 1; |
||||||
|
|
||||||
|
.text-1 { |
||||||
|
color: #23262B; |
||||||
|
font-size: 28rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.text-2 { |
||||||
|
color: #93999F; |
||||||
|
font-size: 24rpx; |
||||||
|
|
||||||
|
span { |
||||||
|
color: #23262B; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.footer-icon { |
||||||
|
margin-right: 56rpx; |
||||||
|
|
||||||
|
.img { |
||||||
|
width: 48rpx; |
||||||
|
height: 48rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.text-1 { |
||||||
|
color: #23262B; |
||||||
|
font-size: 22rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.popClass { |
||||||
|
text-align: center; |
||||||
|
color: #4B5158; |
||||||
|
font-size: 28rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,157 @@ |
|||||||
|
<template> |
||||||
|
<div class="container"> |
||||||
|
<meet-sticky :bg="bg"> |
||||||
|
<meet-navbar title="会议中" :isFixed="false"></meet-navbar> |
||||||
|
</meet-sticky> |
||||||
|
<view class="list" v-for="(item, index) in 10" @click=""> |
||||||
|
<view class="flex-left color-1">1</view> |
||||||
|
<view class="flex-child"> |
||||||
|
<view class="flex-center">我公司碳中和具体的应用场景包括以下几方面:1.碳丝路APP-全民低碳场景的数据收集 碳普惠应用。 2.全国性碳交易平台数据。</view> |
||||||
|
<view class="flex-right">5"</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<view class="footer"> |
||||||
|
<view class="flex-1"> |
||||||
|
<image class="img" src="/static/image/onlineDetails/list.png"></image> |
||||||
|
<view class="text">会议总结</view> |
||||||
|
<image class="img-top" src="/static/image/onlineDetails/ai.png"></image> |
||||||
|
<view class="time">00:05/01:55</view> |
||||||
|
</view> |
||||||
|
<image class="img01" src="/static/image/onlineDetails/prev.png"></image> |
||||||
|
<image class="img02" src="/static/image/onlineDetails/play.png"></image> |
||||||
|
<image class="img01" src="/static/image/onlineDetails/next.png"></image> |
||||||
|
<view class="flex-1"> |
||||||
|
<image class="img" src="/static/image/onlineDetails/upload.png"></image> |
||||||
|
<view class="text">导出</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
components: { |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
list: [], |
||||||
|
}; |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
|
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
@import "../common.scss"; |
||||||
|
|
||||||
|
.container { |
||||||
|
min-height: 100vh; |
||||||
|
background-color: #d1dcfe; |
||||||
|
padding: 20rpx 0; |
||||||
|
padding-bottom: 200rpx; |
||||||
|
|
||||||
|
.list { |
||||||
|
display: flex; |
||||||
|
margin-top: 36rpx; |
||||||
|
padding: 0 24rpx; |
||||||
|
|
||||||
|
.flex-left { |
||||||
|
width: 56rpx; |
||||||
|
height: 56rpx; |
||||||
|
font-size: 36rpx; |
||||||
|
line-height: 56rpx; |
||||||
|
text-align: center; |
||||||
|
border-radius: 50%; |
||||||
|
color: #fff; |
||||||
|
font-weight: bold; |
||||||
|
} |
||||||
|
|
||||||
|
.color-1 { |
||||||
|
background-color: #70CD9E; |
||||||
|
} |
||||||
|
|
||||||
|
.flex-child { |
||||||
|
display: flex; |
||||||
|
align-items: flex-end; |
||||||
|
flex: 1; |
||||||
|
|
||||||
|
.flex-center { |
||||||
|
|
||||||
|
margin: 0 16rpx 0 16rpx; |
||||||
|
border: 1px solid #fff; |
||||||
|
background-color: rbga(255, 255, 255, 0.5); |
||||||
|
border-radius: 16rpx; |
||||||
|
box-sizing: border-box; |
||||||
|
padding: 16rpx 24rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.flex-right { |
||||||
|
color: #23262B; |
||||||
|
font-size: 28rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
.footer { |
||||||
|
background: rgba(255, 255, 255, 1); |
||||||
|
border-top-right-radius: 40rpx; |
||||||
|
border-top-left-radius: 40rpx; |
||||||
|
position: fixed; |
||||||
|
bottom: 0; |
||||||
|
width: 100%; |
||||||
|
height: 180rpx; |
||||||
|
display: flex; |
||||||
|
box-sizing: border-box; |
||||||
|
padding: 12rpx 48rpx; |
||||||
|
align-items: center; |
||||||
|
justify-content:space-between; |
||||||
|
.flex-1{ |
||||||
|
position: relative; |
||||||
|
.img{ |
||||||
|
width: 48rpx; |
||||||
|
height: 48rpx; |
||||||
|
display: block; |
||||||
|
margin: 0 auto; |
||||||
|
} |
||||||
|
.img-top{ |
||||||
|
position: absolute; |
||||||
|
top: -30rpx; |
||||||
|
right: -50rpx; |
||||||
|
width: 84rpx; |
||||||
|
height: 34rpx; |
||||||
|
} |
||||||
|
.time{ |
||||||
|
position: absolute; |
||||||
|
box-sizing: border-box; |
||||||
|
padding: 8rpx 20rpx; |
||||||
|
text-align: center; |
||||||
|
color: #23262B; |
||||||
|
font-size: 24rpx; |
||||||
|
border: 1px solid #fff; |
||||||
|
background: #E9EBF4; |
||||||
|
border-top-left-radius: 16rpx; |
||||||
|
border-top-right-radius: 16rpx; |
||||||
|
top: -100rpx; |
||||||
|
right: -90rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.img01{ |
||||||
|
width:48rpx ; |
||||||
|
height: 48rpx; |
||||||
|
} |
||||||
|
.img02{ |
||||||
|
width: 80rpx; |
||||||
|
height: 80rpx; |
||||||
|
} |
||||||
|
.text{ |
||||||
|
color: #23262B; |
||||||
|
font-weight: bold; |
||||||
|
font-size: 22rpx; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,43 @@ |
|||||||
|
<template> |
||||||
|
<div class="container"> |
||||||
|
<meet-sticky :bg="bg"> |
||||||
|
<meet-navbar title="会议记录" :isFixed="false"></meet-navbar> |
||||||
|
</meet-sticky> |
||||||
|
<div> |
||||||
|
<div class="mb-30"> |
||||||
|
<u-search |
||||||
|
placeholder="日照香炉生紫烟" |
||||||
|
v-model="keyword" |
||||||
|
:showAction="false" |
||||||
|
></u-search> |
||||||
|
</div> |
||||||
|
<view> |
||||||
|
<record-item v-for="item in 1" :key="item"></record-item> |
||||||
|
</view> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import recordItem from "../components/record.vue"; |
||||||
|
export default { |
||||||
|
components: { |
||||||
|
recordItem, |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
keyword: "遥看瀑布挂前川", |
||||||
|
bg: "", |
||||||
|
}; |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
@import "../common.scss"; |
||||||
|
.container { |
||||||
|
min-height: 100vh; |
||||||
|
background-color: #d1dcfe; |
||||||
|
padding: 20rpx 24rpx; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,266 @@ |
|||||||
|
<template> |
||||||
|
<view class="bg container"> |
||||||
|
<meet-sticky :bg="bg"> |
||||||
|
<meet-navbar title="会议总结" :isFixed="false"></meet-navbar> |
||||||
|
</meet-sticky> |
||||||
|
<view class="content"> |
||||||
|
<!-- 会议标题 --> |
||||||
|
<view class="border-item"> |
||||||
|
<image |
||||||
|
src="/static/image/summary/meet_title.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="img-item" |
||||||
|
/> |
||||||
|
<view class="title"> 00 </view> |
||||||
|
</view> |
||||||
|
<!-- 关键词 --> |
||||||
|
<view class="border-item"> |
||||||
|
<image |
||||||
|
src="/static/image/summary/key_word.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="img-item" |
||||||
|
/> |
||||||
|
<view class="flex key-box"> |
||||||
|
<view class="key-item flex items-center"> |
||||||
|
<view>蔡徐坤</view> |
||||||
|
<image |
||||||
|
src="/static/image/summary/close.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="close" |
||||||
|
/> |
||||||
|
</view> |
||||||
|
<image |
||||||
|
src="/static/image/summary/add.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="add" |
||||||
|
@click="add" |
||||||
|
/> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<!-- 参会人 --> |
||||||
|
<view class="border-item"> |
||||||
|
<image |
||||||
|
src="/static/image/summary/attendee .png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="img-item" |
||||||
|
/> |
||||||
|
<view class="flex key-box"> |
||||||
|
<view class="key-item flex items-center"> |
||||||
|
<view>蔡徐坤</view> |
||||||
|
<image |
||||||
|
src="/static/image/summary/edit.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="close" |
||||||
|
@click="edit" |
||||||
|
/> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<!-- 会议总结 --> |
||||||
|
<view class="border-item"> |
||||||
|
<image |
||||||
|
src="/static/image/summary/summary.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="img-item" |
||||||
|
/> |
||||||
|
<view class="title"> |
||||||
|
AI会议、智能助手、需求评审会、AI会议、智能助手、需求评审会、AI会议、智能助手、需求评审会、AI会议、智能助手、需求评审会。 |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<!-- 会议摘要 --> |
||||||
|
<view class="border-item"> |
||||||
|
<image |
||||||
|
src="/static/image/summary/abstract.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="img-item" |
||||||
|
/> |
||||||
|
<view class="title"> |
||||||
|
AI会议、智能助手、需求评审会、AI会议、智能助手、需求评审会、AI会议、智能助手、需求评审会、AI会议、智能助手、需求评审会。 |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<!-- 会议要点--> |
||||||
|
<view class="border-item"> |
||||||
|
<image |
||||||
|
src="/static/image/summary/points.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="img-item" |
||||||
|
/> |
||||||
|
<view class="title"> |
||||||
|
AI会议、智能助手、需求评审会、AI会议、智能助手、需求评审会、AI会议、智能助手、需求评审会、AI会议、智能助手、需求评审会。 |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<!-- 底部 --> |
||||||
|
<view class="footer flex"> |
||||||
|
<view class="btn push"> |
||||||
|
<image |
||||||
|
src="/static/image/summary/upcloud.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="icon" |
||||||
|
/> |
||||||
|
<view>导出</view> |
||||||
|
</view> |
||||||
|
<view class="btn op"> |
||||||
|
<image |
||||||
|
src="/static/image/summary/op.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="icon" |
||||||
|
/> |
||||||
|
<view>格式优化</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<!-- 弹窗 --> |
||||||
|
<meet-pop |
||||||
|
:dialogShow="popConfig.show" |
||||||
|
:btnType="popConfig.btnType" |
||||||
|
:dialogTitle="popConfig.title" |
||||||
|
@handleConfirm="confirm" |
||||||
|
@handleCancel="cancel" |
||||||
|
> |
||||||
|
<view> |
||||||
|
<u-input v-model="popConfig.value"></u-input> |
||||||
|
</view> |
||||||
|
</meet-pop> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
bg: "", |
||||||
|
meetData: {}, |
||||||
|
popConfig: { |
||||||
|
show: false, |
||||||
|
title: "编辑参会人", |
||||||
|
btnType: 2, |
||||||
|
value: "", |
||||||
|
}, |
||||||
|
}; |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
add() { |
||||||
|
this.popConfig.show = true; |
||||||
|
this.popConfig.title = "编辑参会人"; |
||||||
|
}, |
||||||
|
edit() { |
||||||
|
this.popConfig.show = true; |
||||||
|
this.popConfig.title = "添加关键词"; |
||||||
|
}, |
||||||
|
confirm() { |
||||||
|
this.popConfig.show = false; |
||||||
|
}, |
||||||
|
cancel() { |
||||||
|
this.popConfig.show = false; |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
@import "../common.scss"; |
||||||
|
|
||||||
|
.footer { |
||||||
|
height: 180rpx; |
||||||
|
width: 100%; |
||||||
|
position: fixed; |
||||||
|
bottom: 0; |
||||||
|
left: 0; |
||||||
|
background-color: #f2f7fe; |
||||||
|
border-top: 4rpx #fff solid; |
||||||
|
box-sizing: border-box; |
||||||
|
padding: 0 24rpx; |
||||||
|
padding-top: 16rpx; |
||||||
|
.btn { |
||||||
|
height: 80rpx; |
||||||
|
line-height: 80rpx; |
||||||
|
font-weight: 700; |
||||||
|
font-size: 30rpx; |
||||||
|
box-sizing: border-box; |
||||||
|
display: flex; |
||||||
|
align-content: center; |
||||||
|
border-radius: 20rpx; |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
.push { |
||||||
|
margin-right: 20rpx; |
||||||
|
color: #1467ff; |
||||||
|
width: 248rpx; |
||||||
|
border: 2rpx solid #1467ff; |
||||||
|
} |
||||||
|
.op { |
||||||
|
background-color: #1467ff; |
||||||
|
width: 434rpx; |
||||||
|
color: #fff; |
||||||
|
} |
||||||
|
.icon { |
||||||
|
width: 40rpx; |
||||||
|
height: 40rpx; |
||||||
|
margin-right: 12rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.content { |
||||||
|
padding-bottom: 200rpx; |
||||||
|
} |
||||||
|
.container { |
||||||
|
padding: 24rpx; |
||||||
|
background-color: #e3edfe; |
||||||
|
} |
||||||
|
.add { |
||||||
|
width: 148rpx; |
||||||
|
height: 72rpx; |
||||||
|
} |
||||||
|
.key-box { |
||||||
|
flex-wrap: wrap; |
||||||
|
} |
||||||
|
.key-item { |
||||||
|
padding: 16rpx 24rpx; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 12rpx; |
||||||
|
margin-right: 16rpx; |
||||||
|
} |
||||||
|
.close { |
||||||
|
width: 32rpx; |
||||||
|
height: 32rpx; |
||||||
|
margin-left: 16rpx; |
||||||
|
} |
||||||
|
.border-item { |
||||||
|
padding: 24rpx; |
||||||
|
border: 2rpx solid #fff; |
||||||
|
border-radius: 24rpx; |
||||||
|
background: linear-gradient( |
||||||
|
180deg, |
||||||
|
rgba(255, 255, 255, 0.4) 0%, |
||||||
|
rgba(255, 255, 255, 0.6) 100% |
||||||
|
); |
||||||
|
margin-bottom: 20rpx; |
||||||
|
.title { |
||||||
|
padding: 20rpx; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 20rpx; |
||||||
|
line-height: 1.6; |
||||||
|
} |
||||||
|
} |
||||||
|
.img-item { |
||||||
|
width: 164rpx; |
||||||
|
height: 40rpx; |
||||||
|
margin-bottom: 16rpx; |
||||||
|
} |
||||||
|
::v-deep .u-border { |
||||||
|
border-style: none !important; |
||||||
|
height: 80rpx; |
||||||
|
background-color: #e9f1fd; |
||||||
|
border-radius: 16rpx; |
||||||
|
font-weight: 400; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #93999f; |
||||||
|
box-sizing: border-box; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,105 @@ |
|||||||
|
<template> |
||||||
|
<view> |
||||||
|
<meet-navbar title="关于我们" :isFixed="false" :iconType="2"></meet-navbar> |
||||||
|
<view class="content"> |
||||||
|
<image |
||||||
|
src="/static/image/user/shear.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="icon" |
||||||
|
/> |
||||||
|
<view class="mb-48"> |
||||||
|
<view class="title">title</view> |
||||||
|
<view class="num">版本号:444545</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<view class="menu"> |
||||||
|
<view class="flex items-center menu-item" @click="toTxt(1)"> |
||||||
|
<view class="name">隐私政策</view> |
||||||
|
<image |
||||||
|
src="/static/image/user/right.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="right" |
||||||
|
/> |
||||||
|
</view> |
||||||
|
<view class="flex items-center menu-item" @click="toTxt(1)"> |
||||||
|
<view class="name">用户协议</view> |
||||||
|
<image |
||||||
|
src="/static/image/user/right.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="right" |
||||||
|
/> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
|
||||||
|
export default { |
||||||
|
data(){ |
||||||
|
return{ |
||||||
|
|
||||||
|
} |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
toTxt(){ |
||||||
|
this.$meeting_common.to('/meeting/user/txt') |
||||||
|
}, |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
@import "../common.scss"; |
||||||
|
|
||||||
|
.num { |
||||||
|
font-weight: 400; |
||||||
|
font-size: 24rpx; |
||||||
|
color: #4b5158; |
||||||
|
line-height: 2; |
||||||
|
} |
||||||
|
.title { |
||||||
|
font-weight: 700; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #23262b; |
||||||
|
} |
||||||
|
.content { |
||||||
|
text-align: center; |
||||||
|
padding: 24rpx; |
||||||
|
padding-top: 80rpx; |
||||||
|
} |
||||||
|
.icon { |
||||||
|
width: 176rpx; |
||||||
|
height: 176rpx; |
||||||
|
border-radius: 40rpx; |
||||||
|
margin-bottom: 24rpx; |
||||||
|
} |
||||||
|
|
||||||
|
.menu { |
||||||
|
background-color: #eef7fe; |
||||||
|
border: 4rpx solid #fff; |
||||||
|
border-radius: 24rpx; |
||||||
|
padding: 0 24rpx; |
||||||
|
padding-top: 48rpx; |
||||||
|
.right { |
||||||
|
width: 36rpx; |
||||||
|
height: 36rpx; |
||||||
|
} |
||||||
|
.name { |
||||||
|
font-weight: 400; |
||||||
|
font-size: 30rpx; |
||||||
|
color: #23262b; |
||||||
|
flex: 1; |
||||||
|
text-align: left; |
||||||
|
} |
||||||
|
.icon { |
||||||
|
width: 36rpx; |
||||||
|
height: 36rpx; |
||||||
|
margin-right: 24rpx; |
||||||
|
} |
||||||
|
.menu-item { |
||||||
|
margin-bottom: 48rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,95 @@ |
|||||||
|
<template> |
||||||
|
<view> |
||||||
|
<meet-sticky :bg="bg"> |
||||||
|
<meet-navbar title="帮助文档" :isFixed="false"></meet-navbar> |
||||||
|
</meet-sticky> |
||||||
|
<view class="container"> |
||||||
|
<view class="title"> 问题反馈 </view> |
||||||
|
<view class="content"> |
||||||
|
<u-collapse accordion> |
||||||
|
<u-collapse-item |
||||||
|
:title="item.title" |
||||||
|
v-for="(item, index) in docList" |
||||||
|
:key="index" |
||||||
|
> |
||||||
|
<view class="collapse-item"> |
||||||
|
<view v-for="(t, i) in item.explain" :key="i"> |
||||||
|
<view>{{ t }}</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</u-collapse-item> |
||||||
|
</u-collapse> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
docList: [ |
||||||
|
{ |
||||||
|
title: "1.文字处理时间", |
||||||
|
explain: ["11111111111", "222222222222"], |
||||||
|
}, |
||||||
|
{ |
||||||
|
title: "2.支持的语言", |
||||||
|
explain: ["11111111111", "222222222222"], |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.collapse-item { |
||||||
|
background: #ffffff; |
||||||
|
border-radius: 16rpx 16rpx 16rpx 16rpx; |
||||||
|
padding: 20rpx; |
||||||
|
line-height: 1.8; |
||||||
|
} |
||||||
|
.content { |
||||||
|
background: #f4f7ff; |
||||||
|
border-radius: 24rpx 24rpx 24rpx 24rpx; |
||||||
|
border: 2rpx solid #ffffff; |
||||||
|
flex: 1; |
||||||
|
} |
||||||
|
.container { |
||||||
|
padding: 24rpx; |
||||||
|
height: 85vh; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
} |
||||||
|
.u-page { |
||||||
|
padding: 0; |
||||||
|
|
||||||
|
&__item { |
||||||
|
&__title { |
||||||
|
color: $u-tips-color; |
||||||
|
background-color: $u-bg-color; |
||||||
|
padding: 15px; |
||||||
|
font-size: 15px; |
||||||
|
|
||||||
|
&__slot-title { |
||||||
|
color: $u-primary; |
||||||
|
font-size: 14px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.title { |
||||||
|
font-weight: 700; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #23262b; |
||||||
|
margin-bottom: 24rpx; |
||||||
|
} |
||||||
|
.u-collapse-content { |
||||||
|
color: $u-tips-color; |
||||||
|
font-size: 14px; |
||||||
|
} |
||||||
|
::v-deep .u-line { |
||||||
|
border-bottom-style: none !important; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,128 @@ |
|||||||
|
<template> |
||||||
|
<div class="container"> |
||||||
|
<meet-sticky :bg="bg"> |
||||||
|
<meet-navbar title="会议记录" :isFixed="false"></meet-navbar> |
||||||
|
</meet-sticky> |
||||||
|
<div> |
||||||
|
<div class="mb-30"> |
||||||
|
<u-search |
||||||
|
placeholder="日照香炉生紫烟" |
||||||
|
v-model="keyword" |
||||||
|
:showAction="false" |
||||||
|
:customStyle="customStyle1" |
||||||
|
></u-search> |
||||||
|
</div> |
||||||
|
<view> |
||||||
|
<view class="record-item mb-24"> |
||||||
|
<view class="flex justify-between items-center"> |
||||||
|
<view class="title"> 这是一个标题 </view> |
||||||
|
<view> |
||||||
|
<image |
||||||
|
src="/static/image/user/share.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="icon" |
||||||
|
/> |
||||||
|
<image |
||||||
|
src="/static/image/user/more.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="icon" |
||||||
|
@click.stop="upMask" |
||||||
|
/> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
|
||||||
|
<view class="mask" v-if="popup"> |
||||||
|
<view>导出</view> |
||||||
|
<view>重命名</view> |
||||||
|
<view>删除</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
keyword: "遥看瀑布挂前川", |
||||||
|
bg: "", |
||||||
|
popup: false, |
||||||
|
customStyle1: { |
||||||
|
background: |
||||||
|
"linear-gradient( 180deg, rgba(255,255,255,0.4) 0%, rgba(255,255,255,0.6) 100%)", |
||||||
|
borderRadius: "40rpx", |
||||||
|
border: " 2rpx solid #FFFFFF", |
||||||
|
}, |
||||||
|
}; |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
upMask() { |
||||||
|
this.popup = !this.popup; |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
@import "../common.scss"; |
||||||
|
.icon { |
||||||
|
width: 40rpx; |
||||||
|
height: 40rpx; |
||||||
|
margin-left: 16rpx; |
||||||
|
} |
||||||
|
.mask { |
||||||
|
position: absolute; |
||||||
|
width: 168rpx; |
||||||
|
height: 232rpx; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 16rpx; |
||||||
|
top: 80rpx; |
||||||
|
right: 16rpx; |
||||||
|
padding: 24rpx; |
||||||
|
box-sizing: border-box; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: space-around; |
||||||
|
} |
||||||
|
|
||||||
|
.record-item { |
||||||
|
position: relative; |
||||||
|
// height: 168rpx; |
||||||
|
border-radius: 24rpx; |
||||||
|
border: 2rpx #fff solid; |
||||||
|
padding: 32rpx 24rpx; |
||||||
|
// padding-bottom: 36rpx; |
||||||
|
background: linear-gradient( |
||||||
|
180deg, |
||||||
|
rgba(255, 255, 255, 0.4) 0%, |
||||||
|
rgba(255, 255, 255, 0.6) 100% |
||||||
|
); |
||||||
|
.title { |
||||||
|
font-weight: 700; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #23262b; |
||||||
|
// line-height: 40rpx; |
||||||
|
} |
||||||
|
} |
||||||
|
.container { |
||||||
|
min-height: 100vh; |
||||||
|
background-color: #d1dcfe; |
||||||
|
padding: 20rpx 24rpx; |
||||||
|
} |
||||||
|
::v-deep .u-search__content { |
||||||
|
background-color: linear-gradient( |
||||||
|
180deg, |
||||||
|
rgba(255, 255, 255, 0.4) 0%, |
||||||
|
rgba(255, 255, 255, 0.6) 100% |
||||||
|
) !important; |
||||||
|
} |
||||||
|
::v-deep .u-search__content__input { |
||||||
|
background-color: linear-gradient( |
||||||
|
180deg, |
||||||
|
rgba(255, 255, 255, 0.4) 0%, |
||||||
|
rgba(255, 255, 255, 0.6) 100% |
||||||
|
) !important; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,134 @@ |
|||||||
|
<template> |
||||||
|
<view class="container"> |
||||||
|
<meet-navbar title="我的" :isFixed="false" :iconType="0"></meet-navbar> |
||||||
|
<view> |
||||||
|
<!-- touxiang --> |
||||||
|
<view class="flex items-center mb-40"> |
||||||
|
<view class="avatar-box"> |
||||||
|
<image src="/static/image/bg.png" mode="scaleToFill" class="avatar" /> |
||||||
|
</view> |
||||||
|
<view> |
||||||
|
<view class="nickname">用户名</view> |
||||||
|
<view class="status">未登录</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
<!-- 分享 --> |
||||||
|
<view> |
||||||
|
<image |
||||||
|
src="/static/image/user/shear.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="shear" |
||||||
|
/> |
||||||
|
</view> |
||||||
|
<!-- menu --> |
||||||
|
<view class="menu"> |
||||||
|
<view class="flex items-center menu-item" v-for="item in menuList" :key="item"> |
||||||
|
<image :src="item.icon" mode="scaleToFill" class="icon" /> |
||||||
|
<view class="name">{{ item.n }}</view> |
||||||
|
<image |
||||||
|
src="/static/image/user/right.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="right" |
||||||
|
/> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
menuList: [ |
||||||
|
{ |
||||||
|
icon: "/static/image/user/flie.png", |
||||||
|
n: "我的附件", |
||||||
|
url: "", |
||||||
|
}, |
||||||
|
{ |
||||||
|
icon: "/static/image/user/edit.png", |
||||||
|
n: "意见反馈", |
||||||
|
url: "", |
||||||
|
}, |
||||||
|
{ |
||||||
|
icon: "/static/image/user/doc.png", |
||||||
|
n: "帮助文档", |
||||||
|
url: "", |
||||||
|
}, |
||||||
|
{ |
||||||
|
icon: "/static/image/user/alert-circle.png", |
||||||
|
n: "帮助文档", |
||||||
|
url: "", |
||||||
|
}, |
||||||
|
], |
||||||
|
}; |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
@import "../common.scss"; |
||||||
|
.menu { |
||||||
|
background-color: #EEF7FE; |
||||||
|
border: 4rpx solid #fff; |
||||||
|
border-radius: 24rpx; |
||||||
|
padding: 0 24rpx; |
||||||
|
padding-top: 48rpx; |
||||||
|
.right { |
||||||
|
width: 36rpx; |
||||||
|
height: 36rpx; |
||||||
|
} |
||||||
|
.name { |
||||||
|
font-weight: 400; |
||||||
|
font-size: 30rpx; |
||||||
|
color: #23262b; |
||||||
|
flex: 1; |
||||||
|
} |
||||||
|
.icon { |
||||||
|
width: 36rpx; |
||||||
|
height: 36rpx; |
||||||
|
margin-right: 24rpx; |
||||||
|
} |
||||||
|
.menu-item{ |
||||||
|
margin-bottom: 48rpx; |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
.shear { |
||||||
|
width: 100%; |
||||||
|
height: 160rpx; |
||||||
|
margin-bottom: 24rpx; |
||||||
|
} |
||||||
|
.status { |
||||||
|
font-weight: 400; |
||||||
|
font-size: 28rpx; |
||||||
|
color: #93999f; |
||||||
|
} |
||||||
|
.nickname { |
||||||
|
font-weight: 700; |
||||||
|
font-size: 36rpx; |
||||||
|
color: #23262b; |
||||||
|
line-height: 1.8; |
||||||
|
} |
||||||
|
.avatar { |
||||||
|
width: 144rpx; |
||||||
|
height: 144rpx; |
||||||
|
border-radius: 26rpx; |
||||||
|
} |
||||||
|
.avatar-box { |
||||||
|
width: 176rpx; |
||||||
|
height: 176rpx; |
||||||
|
padding: 16rpx; |
||||||
|
border-radius: 26rpx; |
||||||
|
background-color: #fff; |
||||||
|
box-sizing: border-box; |
||||||
|
margin-right: 24rpx; |
||||||
|
} |
||||||
|
.container { |
||||||
|
min-height: 100vh; |
||||||
|
background-color: #d1dcfe; |
||||||
|
padding: 20rpx 24rpx; |
||||||
|
box-sizing: border-box; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,166 @@ |
|||||||
|
<template> |
||||||
|
<view class="container"> |
||||||
|
<meet-sticky :bg="bg"> |
||||||
|
<meet-navbar title="意见反馈" :isFixed="false"></meet-navbar> |
||||||
|
</meet-sticky> |
||||||
|
<view class="content"> |
||||||
|
<view class="title"> 问题反馈 </view> |
||||||
|
<view class="mb-24"> |
||||||
|
<u--textarea |
||||||
|
v-model="value2" |
||||||
|
placeholder="请输入内容" |
||||||
|
count |
||||||
|
:maxlength="150" |
||||||
|
:height="215" |
||||||
|
:border="border" |
||||||
|
></u--textarea> |
||||||
|
</view> |
||||||
|
<view class="mb-48"> |
||||||
|
<u-upload |
||||||
|
:fileList="fileList6" |
||||||
|
@afterRead="afterRead" |
||||||
|
@delete="deletePic" |
||||||
|
name="6" |
||||||
|
multiple |
||||||
|
:maxCount="1" |
||||||
|
width="156" |
||||||
|
height="156" |
||||||
|
> |
||||||
|
<view class="push"> |
||||||
|
<image |
||||||
|
src="/static/image/user/push.png" |
||||||
|
mode="scaleToFill" |
||||||
|
class="icon" |
||||||
|
/> |
||||||
|
<view class="txt">添加截图</view> |
||||||
|
</view> |
||||||
|
</u-upload> |
||||||
|
</view> |
||||||
|
<view class="title"> 联系方式 </view> |
||||||
|
<view> |
||||||
|
<u--input |
||||||
|
placeholder="请输入手机号" |
||||||
|
border="surround" |
||||||
|
v-model="value" |
||||||
|
clearable |
||||||
|
></u--input> |
||||||
|
</view> |
||||||
|
<!-- <view class="mb-30"> |
||||||
|
<u-search |
||||||
|
placeholder="日照香炉生紫烟" |
||||||
|
v-model="keyword" |
||||||
|
:showAction="false" |
||||||
|
:bgColor="bgColor" |
||||||
|
borderColor="#fff" |
||||||
|
></u-search> |
||||||
|
</view> --> |
||||||
|
</view> |
||||||
|
</view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
value2: "", |
||||||
|
value: "", |
||||||
|
border: "none", |
||||||
|
keyword: "遥看瀑布挂前川", |
||||||
|
bg: "", |
||||||
|
popup: false, |
||||||
|
bgColor: "#eef8fe05", |
||||||
|
fileList6: [], |
||||||
|
}; |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
upMask() { |
||||||
|
this.popup = !this.popup; |
||||||
|
}, |
||||||
|
afterRead(e) { |
||||||
|
console.log(e); |
||||||
|
}, |
||||||
|
deletePic(e) { |
||||||
|
console.log(e); |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
@import "../common.scss"; |
||||||
|
.push { |
||||||
|
width: 156rpx; |
||||||
|
height: 156rpx; |
||||||
|
background: linear-gradient( |
||||||
|
180deg, |
||||||
|
rgba(255, 255, 255, 0.4) 0%, |
||||||
|
rgba(255, 255, 255, 0.6) 100% |
||||||
|
); |
||||||
|
border: 2rpx solid #ffffff; |
||||||
|
border-radius: 24rpx; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
.txt { |
||||||
|
font-weight: 400; |
||||||
|
font-size: 24rpx; |
||||||
|
color: #93999f; |
||||||
|
} |
||||||
|
} |
||||||
|
.title { |
||||||
|
font-weight: 700; |
||||||
|
font-size: 32rpx; |
||||||
|
color: #23262b; |
||||||
|
margin-bottom: 24rpx; |
||||||
|
} |
||||||
|
.icon { |
||||||
|
width: 40rpx; |
||||||
|
height: 40rpx; |
||||||
|
} |
||||||
|
.content { |
||||||
|
padding: 0 24rpx; |
||||||
|
} |
||||||
|
.container { |
||||||
|
min-height: 100vh; |
||||||
|
background-color: #d1dcfe; |
||||||
|
padding: 20rpx 0; |
||||||
|
} |
||||||
|
::v-deep .u-search__content { |
||||||
|
background-color: linear-gradient( |
||||||
|
180deg, |
||||||
|
rgba(255, 255, 255, 0.4) 0%, |
||||||
|
rgba(255, 255, 255, 0.6) 100% |
||||||
|
) !important; |
||||||
|
} |
||||||
|
::v-deep .u-search__content__input { |
||||||
|
background-color: linear-gradient( |
||||||
|
180deg, |
||||||
|
rgba(255, 255, 255, 0.4) 0%, |
||||||
|
rgba(255, 255, 255, 0.6) 100% |
||||||
|
) !important; |
||||||
|
} |
||||||
|
::v-deep .u-textarea { |
||||||
|
border-radius: 24rpx !important; |
||||||
|
background: linear-gradient( |
||||||
|
180deg, |
||||||
|
rgba(255, 255, 255, 0.4) 0%, |
||||||
|
rgba(255, 255, 255, 0.6) 100% |
||||||
|
) !important; |
||||||
|
border: 2rpx solid #ffffff; |
||||||
|
} |
||||||
|
::v-deep .u-textarea__count { |
||||||
|
background-color: transparent !important; |
||||||
|
} |
||||||
|
::v-deep .u-input { |
||||||
|
background: linear-gradient( |
||||||
|
180deg, |
||||||
|
rgba(255, 255, 255, 0.4) 0%, |
||||||
|
rgba(255, 255, 255, 0.6) 100% |
||||||
|
) !important; |
||||||
|
border-radius: 24rpx !important; |
||||||
|
border: 2rpx solid #ffffff !important; |
||||||
|
height: 96rpx !important; |
||||||
|
box-sizing: border-box !important; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,33 @@ |
|||||||
|
<template> |
||||||
|
<view class="container"> |
||||||
|
<meet-sticky :bg="bg"> |
||||||
|
<meet-navbar title="title" :isFixed="false"></meet-navbar> |
||||||
|
</meet-sticky> |
||||||
|
<view class="content"> </view> |
||||||
|
</view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
bg: "", |
||||||
|
}; |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.container{ |
||||||
|
height: 100%; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
|
||||||
|
} |
||||||
|
.content { |
||||||
|
padding: 24rpx; |
||||||
|
background-color: #fff; |
||||||
|
border-radius: 24rpx 24rpx 0 0; |
||||||
|
flex: 1; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,30 @@ |
|||||||
|
let _sysInfo = uni.getSystemInfoSync(); |
||||||
|
let statusBarHeight = 0; //状态栏高度
|
||||||
|
let titleBarHeight = 0; //导航栏高度
|
||||||
|
let customBarHeight = 0; //导航栏高度+导航栏高度
|
||||||
|
|
||||||
|
statusBarHeight = _sysInfo.statusBarHeight; |
||||||
|
// #ifndef MP
|
||||||
|
if (_sysInfo.platform == 'android') { |
||||||
|
titleBarHeight = 50; |
||||||
|
} else { |
||||||
|
titleBarHeight = 45; |
||||||
|
} |
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
let custom = wx.getMenuButtonBoundingClientRect(); |
||||||
|
// 导航栏高度(标题栏高度) = 胶囊高度 + (顶部距离 - 状态栏高度) * 2
|
||||||
|
titleBarHeight = custom.height + (custom.top - _sysInfo.statusBarHeight) * 2; |
||||||
|
// customBarHeight = custom.bottom + custom.top - statusBarHeight;
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-ALIPAY
|
||||||
|
titleBarHeight = _sysInfo.titleBarHeight; |
||||||
|
// #endif
|
||||||
|
customBarHeight = statusBarHeight + titleBarHeight; |
||||||
|
|
||||||
|
_sysInfo.titleBarHeight = titleBarHeight; |
||||||
|
_sysInfo.statusBarHeight = statusBarHeight; |
||||||
|
_sysInfo.customBarHeight = customBarHeight; |
||||||
|
|
||||||
|
export const sysInfo = _sysInfo; |
@ -0,0 +1,20 @@ |
|||||||
|
// 引入 request 文件
|
||||||
|
import request from './index.js' |
||||||
|
|
||||||
|
// GET
|
||||||
|
export const getDemo = (params) => { |
||||||
|
return request({ |
||||||
|
url: `/getDemo?id=${id}`, |
||||||
|
method: 'get', |
||||||
|
data: params, |
||||||
|
header: {} // 自定义
|
||||||
|
}) |
||||||
|
} |
||||||
|
// POST
|
||||||
|
export const PostDemo = (data) => { |
||||||
|
return request({ |
||||||
|
url: `/postDemo`, |
||||||
|
method: 'post', |
||||||
|
data:data, |
||||||
|
}) |
||||||
|
} |
@ -0,0 +1,101 @@ |
|||||||
|
// 全局请求封装 请求地址
|
||||||
|
const base_url = 'http://localhost:996' |
||||||
|
// 请求超出时间
|
||||||
|
const timeout = 5000 |
||||||
|
|
||||||
|
// 需要修改token,和根据实际修改请求头
|
||||||
|
export default (params) => { |
||||||
|
let url = params.url; |
||||||
|
let method = params.method || "get"; |
||||||
|
let data = params.data || {}; |
||||||
|
let header = { |
||||||
|
'Token': uni.getStorageSync('token') || '', |
||||||
|
// 'Content-Type': 'application/json;charset=UTF-8',
|
||||||
|
// 'Authorization': 'Basic c2FiZXI6c2FiZXJfc2VjcmV0',
|
||||||
|
// 'Tenant-Id': uni.getStorageSync('tenantId') || 'xxx', // avue配置相关
|
||||||
|
...params.header |
||||||
|
} |
||||||
|
if (method == "post") { |
||||||
|
header = { |
||||||
|
'Content-Type': 'application/json' |
||||||
|
}; |
||||||
|
} |
||||||
|
return new Promise((resolve, reject) => { |
||||||
|
uni.request({ |
||||||
|
url: base_url + url, |
||||||
|
method: method, |
||||||
|
header: header, |
||||||
|
data: data, |
||||||
|
timeout, |
||||||
|
success(response) { |
||||||
|
const res = response |
||||||
|
// 根据返回的状态码做出对应的操作
|
||||||
|
//获取成功
|
||||||
|
// console.log(res.statusCode);
|
||||||
|
if (res.statusCode == 200) { |
||||||
|
resolve(res.data); |
||||||
|
} else { |
||||||
|
uni.clearStorageSync() |
||||||
|
switch (res.statusCode) { |
||||||
|
case 401: |
||||||
|
uni.showModal({ |
||||||
|
title: "提示", |
||||||
|
content: "请登录", |
||||||
|
showCancel: false, |
||||||
|
success() { |
||||||
|
setTimeout(() => { |
||||||
|
uni.navigateTo({ |
||||||
|
url: "/pages/login/index", |
||||||
|
}) |
||||||
|
}, 1000); |
||||||
|
}, |
||||||
|
}); |
||||||
|
break; |
||||||
|
case 404: |
||||||
|
uni.showToast({ |
||||||
|
title: '请求地址不存在...', |
||||||
|
duration: 2000, |
||||||
|
}) |
||||||
|
break; |
||||||
|
default: |
||||||
|
uni.showToast({ |
||||||
|
title: '请重试...', |
||||||
|
duration: 2000, |
||||||
|
}) |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
fail(err) { |
||||||
|
console.log(err) |
||||||
|
if (err.errMsg.indexOf('request:fail') !== -1) { |
||||||
|
uni.showToast({ |
||||||
|
title: '网络异常', |
||||||
|
icon: "error", |
||||||
|
duration: 2000 |
||||||
|
}) |
||||||
|
} else { |
||||||
|
uni.showToast({ |
||||||
|
title: '未知异常', |
||||||
|
duration: 2000 |
||||||
|
}) |
||||||
|
} |
||||||
|
reject(err); |
||||||
|
|
||||||
|
}, |
||||||
|
complete() { |
||||||
|
// 不管成功还是失败都会执行
|
||||||
|
uni.hideLoading(); |
||||||
|
uni.hideToast(); |
||||||
|
} |
||||||
|
}); |
||||||
|
}).catch(() => { }); |
||||||
|
}; |
||||||
|
// 使用方法
|
||||||
|
// import { pageStudyInfo } from '@/request/api.js'
|
||||||
|
// // 获取学习列表详情信息
|
||||||
|
// pageStudyInfo (data).then((res) => {
|
||||||
|
// console.log('成功', res);
|
||||||
|
// }).catch((err) => {
|
||||||
|
// console.error('失败', err);
|
||||||
|
// });
|
@ -0,0 +1,161 @@ |
|||||||
|
function pickJsonObj(value) { |
||||||
|
try { |
||||||
|
return JSON.parse(value) |
||||||
|
} catch (e) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
class WebSocketClient { |
||||||
|
constructor(url) { |
||||||
|
this.url = url; |
||||||
|
this.socket = null; |
||||||
|
this.isReconnecting = false; |
||||||
|
this.reconnectInterval = 3000; // 重连间隔,单位毫秒
|
||||||
|
this.heartBeatInterval = 5000; // 心跳间隔,单位毫秒
|
||||||
|
this.pingTimeoutDuration = 1000; // 超过这个时间,后端没有返回pong,则判定后端断线了。
|
||||||
|
this.heartBeatTimer = null; |
||||||
|
this.destroy = false; // 是否销毁
|
||||||
|
} |
||||||
|
|
||||||
|
connect() { |
||||||
|
this.socket = uni.connectSocket({ |
||||||
|
url: this.url, |
||||||
|
complete: () => { } |
||||||
|
}); |
||||||
|
this.initEventListeners(); |
||||||
|
} |
||||||
|
|
||||||
|
initEventListeners() { |
||||||
|
this.socket.onOpen(() => { |
||||||
|
// WebSocket连接已打开
|
||||||
|
this.onConnected(); |
||||||
|
this.startHeartBeat(); |
||||||
|
}); |
||||||
|
|
||||||
|
this.socket.onMessage((res) => { |
||||||
|
const obj = pickJsonObj(res.data); |
||||||
|
if (obj.type === 'pong') { |
||||||
|
// 收到pong消息,心跳正常,无需处理
|
||||||
|
this.resetPingTimeout(); // 重置计时
|
||||||
|
} else { |
||||||
|
// 处理其他消息
|
||||||
|
this.onMessage(res.data); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
this.socket.onClose((res) => { |
||||||
|
// WebSocket连接已关闭
|
||||||
|
if (this.destroy) { |
||||||
|
this.onClosed() |
||||||
|
return; |
||||||
|
} |
||||||
|
this.stopHeartBeat(); |
||||||
|
if (!this.isReconnecting) { |
||||||
|
this.reconnect(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
sendMessage(message) { |
||||||
|
if (this.socket) { |
||||||
|
this.socket.send({ |
||||||
|
data: message |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
onMessage(message) { |
||||||
|
// 处理收到的消息
|
||||||
|
console.log('message:', message) |
||||||
|
} |
||||||
|
|
||||||
|
startHeartBeat() { |
||||||
|
this.heartBeatTimer = setInterval(() => { |
||||||
|
this.sendMessage(JSON.stringify({ |
||||||
|
type: 'ping' |
||||||
|
})); // 发送ping消息
|
||||||
|
this.pingTimeout = setTimeout(() => { |
||||||
|
// 未收到pong消息,尝试重连...
|
||||||
|
this.reconnect(); |
||||||
|
}, this.pingTimeoutDuration); |
||||||
|
}, this.heartBeatInterval); |
||||||
|
} |
||||||
|
|
||||||
|
stopHeartBeat() { |
||||||
|
if (this.heartBeatTimer) { |
||||||
|
clearInterval(this.heartBeatTimer); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
reconnect() { |
||||||
|
this.isReconnecting = true; |
||||||
|
setTimeout(() => { |
||||||
|
this.onReconnect(); |
||||||
|
this.connect(); |
||||||
|
this.isReconnecting = false; |
||||||
|
}, this.reconnectInterval); |
||||||
|
} |
||||||
|
|
||||||
|
resetPingTimeout() { |
||||||
|
clearTimeout(this.pingTimeout); // 重置计时
|
||||||
|
} |
||||||
|
|
||||||
|
close() { |
||||||
|
this.destroy = true; |
||||||
|
this.stopHeartBeat(); |
||||||
|
if (this.socket) { |
||||||
|
this.socket.close(); |
||||||
|
this.socket = null; |
||||||
|
} |
||||||
|
} |
||||||
|
/** |
||||||
|
* 重连时触发 |
||||||
|
*/ |
||||||
|
onReconnect() { |
||||||
|
console.log('尝试重连...') |
||||||
|
} |
||||||
|
/** |
||||||
|
* 连接成功时触发 |
||||||
|
*/ |
||||||
|
onConnected() { |
||||||
|
console.log('WebSocket连接已打开'); |
||||||
|
} |
||||||
|
/** |
||||||
|
* 断开时触发 |
||||||
|
*/ |
||||||
|
onClosed() { |
||||||
|
console.log('已断开连接') |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
export default WebSocketClient; |
||||||
|
|
||||||
|
// websocket 使用
|
||||||
|
// import WebSocketClient from '@/utils/websocket.js'
|
||||||
|
// // 创建WebSocket实例
|
||||||
|
// ws.value = new WebSocketClient('ws://这里填写你的服务地址');
|
||||||
|
// // 连接WebSocket
|
||||||
|
// ws.value.connect();
|
||||||
|
// // 接收消息时触发
|
||||||
|
// ws.value.onMessage = (value) => {
|
||||||
|
// const obj = JSON.parse(value)
|
||||||
|
// if (obj.type === 'message') {
|
||||||
|
// list.value.push({
|
||||||
|
// time: new Date().toLocaleString(),
|
||||||
|
// value: obj.value
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // 重连时触发
|
||||||
|
// ws.value.onReconnect = () => {
|
||||||
|
// netStatus.value = 2;
|
||||||
|
// }
|
||||||
|
// // 连接成功后触发
|
||||||
|
// ws.value.onConnected = () => {
|
||||||
|
// netStatus.value = 1;
|
||||||
|
// }
|
||||||
|
// // 关闭后触发(直接销毁了,不会继续重连)
|
||||||
|
// ws.value.onClosed = () => {
|
||||||
|
// netStatus.value = 0;
|
||||||
|
// }
|
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 515 B |
After Width: | Height: | Size: 815 B |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 392 KiB |
After Width: | Height: | Size: 336 B |
After Width: | Height: | Size: 822 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 322 B |
After Width: | Height: | Size: 559 B |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 620 B |
After Width: | Height: | Size: 644 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 639 B |
After Width: | Height: | Size: 346 B |
After Width: | Height: | Size: 273 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 19 KiB |