first commit
This commit is contained in:
commit
314efc7ff3
27
.gitignore
vendored
Normal file
27
.gitignore
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules
|
||||||
|
/dist
|
||||||
|
/build
|
||||||
|
/logs
|
||||||
|
|
||||||
|
# sign
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw*
|
||||||
|
.ide
|
||||||
|
.preview.json
|
||||||
6
.prettierignore
Normal file
6
.prettierignore
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package.json
|
||||||
|
manifest.json
|
||||||
|
README.md
|
||||||
|
|
||||||
|
# assets/js
|
||||||
|
src/assets/js/*.js
|
||||||
36
README.md
Normal file
36
README.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# 手表示例模版
|
||||||
|
|
||||||
|
## 文件结构
|
||||||
|
|
||||||
|
```
|
||||||
|
├── sign # 存储 rpk 包签名模块(须自行生成);
|
||||||
|
│ ├── certificate.pem # 证书文件
|
||||||
|
│ └── private.pem # 私钥文件
|
||||||
|
└── src
|
||||||
|
│ ├── assets # 公用的资源(images/styles/字体...)
|
||||||
|
│ │ ├──images # 存储 png/jpg/svg 等公共图片资源
|
||||||
|
│ │ └──styles # 存放 less/css/sass 等公共样式资源
|
||||||
|
│ ├── pages # 统一存放项目页面级代码
|
||||||
|
│ ├── app.ux # 应用程序代码的入口文件
|
||||||
|
│ ├── manifest.json # 配置蓝河应用基本信息
|
||||||
|
│ └── components # 存放蓝河应用组件
|
||||||
|
└── package.json # 定义项目需要的各种模块及配置信息
|
||||||
|
```
|
||||||
|
|
||||||
|
### 模版说明
|
||||||
|
|
||||||
|
- `Demo` 页面:示例页面;
|
||||||
|
- `DemoDetail`页面:详情页面;
|
||||||
|
|
||||||
|
## 如何使用
|
||||||
|
|
||||||
|
- **内置样式处理方案**;「蓝河应用」支持 `sass` 的预编译;这里采取 [dart sass](https://sass-lang.com/documentation) 方案,并内置了部分变量,以及常用混合方法,使得可以轻松开启样式编写、复用、修改等;
|
||||||
|
- **添加新增页面命令脚本**;如果需要新建页面,只需运行:`yarn gen YourPageName` ,当然,也可以根据需要,自行定定制模板:*/command/gen/template.ux*;
|
||||||
|
- **集成 [Prettier](https://prettier.io/)**;在检测代码中潜在问题的同时,统一团队代码规范、风格(`js`,`less`,`scss`等),从而促使写出高质量代码,以提升工作效率(尤其针对团队开发);
|
||||||
|
|
||||||
|
## 内置命令
|
||||||
|
|
||||||
|
| 命令 | 描述 | 备注 |
|
||||||
|
|---|---|---|
|
||||||
|
| `yarn gen ` | 新增「蓝河应用」页面 | 助你高效生成页面,模版可自定义,推荐 ✓|
|
||||||
|
| `yarn prettier` | 一键美化代码(js/css/less/ux) | 实在是团队开发好帮手,推荐 ✓ |
|
||||||
17
jsconfig.json
Normal file
17
jsconfig.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"checkJs": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
41
package.json
Normal file
41
package.json
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"name": "talk",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"packageManager": "pnpm@7.1.0",
|
||||||
|
"description": "Watch Template",
|
||||||
|
"scripts": {
|
||||||
|
"gen": "node ./scripts/gen/index.js",
|
||||||
|
"precommit-msg": "echo '🚧 start pre-commit checks ...' && exit 0",
|
||||||
|
"prettier": "node ./scripts/selfCloseInputTag.js && prettier --write \"src/**/*.{js,ux,less,scss,css}\""
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"colors": "^1.4.0",
|
||||||
|
"husky": "^4.3.0",
|
||||||
|
"lint-staged": "^10.5.1",
|
||||||
|
"prettier": "^1.15.3",
|
||||||
|
"prettier-plugin-ux": "^0.3.0"
|
||||||
|
},
|
||||||
|
"prettier": {
|
||||||
|
"singleQuote": true,
|
||||||
|
"semi": false,
|
||||||
|
"printWidth": 80,
|
||||||
|
"proseWrap": "never",
|
||||||
|
"tabWidth": 2
|
||||||
|
},
|
||||||
|
"husky": {
|
||||||
|
"hooks": {
|
||||||
|
"pre-commit": "yarn run precommit-msg && lint-staged"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"**/**.{ux,js,json,pcss,md,vue}": [
|
||||||
|
"prettier --write",
|
||||||
|
"git add"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"多终端应用",
|
||||||
|
"手表示例",
|
||||||
|
"手表模版"
|
||||||
|
]
|
||||||
|
}
|
||||||
1013
pnpm-lock.yaml
generated
Normal file
1013
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
87
scripts/gen/index.js
Normal file
87
scripts/gen/index.js
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* @desc: gen script command,make a new page generated by one click.
|
||||||
|
* @author: nicejade
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
const colors = require('colors')
|
||||||
|
|
||||||
|
const newFolderName = process.argv[2]
|
||||||
|
|
||||||
|
String.prototype.firstUpperCase = function() {
|
||||||
|
return this.replace(/\b(\w)/g, $1 => {
|
||||||
|
return $1.toLowerCase()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const resolve = dir => {
|
||||||
|
return path.join(__dirname, '../..', dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
const successExecPrint = msg => {
|
||||||
|
console.log(
|
||||||
|
colors.green(`✓ `) +
|
||||||
|
colors.cyan(`${msg} `) +
|
||||||
|
colors.green('task has been successfully executed.')
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function createNewPage(newFolderPath) {
|
||||||
|
const mReg = new RegExp('@PAGE_CLASS_NAME', 'g')
|
||||||
|
const pageContent = fs.readFileSync(`${__dirname}/template.ux`, 'UTF-8')
|
||||||
|
const rootClassName = newFolderName
|
||||||
|
.firstUpperCase()
|
||||||
|
.replace(/([A-Z])/g, '-$1')
|
||||||
|
.toLowerCase()
|
||||||
|
const newContent = pageContent.replace(mReg, rootClassName)
|
||||||
|
|
||||||
|
fs.mkdirSync(newFolderPath, 0777)
|
||||||
|
fs.writeFile(`${newFolderPath}/index.ux`, newContent, error => {
|
||||||
|
if (error) throw `Something went wrong: ${error}`
|
||||||
|
})
|
||||||
|
successExecPrint('Create New Page')
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveRouter2Manifest() {
|
||||||
|
const manifestPath = resolve('/src/manifest.json')
|
||||||
|
let manifestConf = fs.readFileSync(manifestPath, 'UTF-8')
|
||||||
|
manifestConf = JSON.parse(manifestConf)
|
||||||
|
const routerPages = manifestConf.router.pages
|
||||||
|
routerPages[`pages/${newFolderName}`] = {
|
||||||
|
component: 'index'
|
||||||
|
}
|
||||||
|
manifestConf = JSON.stringify(manifestConf, null, 2)
|
||||||
|
fs.writeFile(manifestPath, manifestConf, error => {
|
||||||
|
if (error) throw `Something went wrong[@saveRouter2Manifest]: ${error}`
|
||||||
|
})
|
||||||
|
successExecPrint('Save Router Into Manifest')
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
if (!newFolderName) {
|
||||||
|
return console.warn(
|
||||||
|
`⚠️ Please enter the name of the page you want to create.`.underline.red
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const folderNameReg = /^[A-Z][[A-Za-z0-9]+$/
|
||||||
|
if (!folderNameReg.test(newFolderName)) {
|
||||||
|
return console.warn(
|
||||||
|
`⚠️ Please enter the standard Folder name. Eg: XyzAbcde.`.underline.red
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const newFolderPath = path.join(__dirname, `../../src/pages/${newFolderName}`)
|
||||||
|
const isExist = fs.existsSync(newFolderPath)
|
||||||
|
|
||||||
|
if (isExist) {
|
||||||
|
return console.warn(
|
||||||
|
`⚠️ ${newFolderName} already exists in the /src/pages/ directory.`
|
||||||
|
.underline.red
|
||||||
|
)
|
||||||
|
}
|
||||||
|
createNewPage(newFolderPath)
|
||||||
|
saveRouter2Manifest()
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
27
scripts/gen/template.ux
Normal file
27
scripts/gen/template.ux
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<template>
|
||||||
|
<div class="wrapper">
|
||||||
|
<text class="title">{{ title }}</text>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data: {
|
||||||
|
title: '欢迎体验多终端应用开发'
|
||||||
|
},
|
||||||
|
|
||||||
|
onInit() {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import './../../assets/styles/style.scss';
|
||||||
|
.wrapper {
|
||||||
|
@include flex-box-mixins(column, center, center);
|
||||||
|
.title {
|
||||||
|
font-size: 8 * $size-factor;
|
||||||
|
text-align: center;
|
||||||
|
color: $black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
36
scripts/selfCloseInputTag.js
Normal file
36
scripts/selfCloseInputTag.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* @file: selfCloseInputTag.js
|
||||||
|
* @desc: 遍历指定目录下 .ux 文件,将其中 input 标签由 <input **></input> 转换为 <input ** />
|
||||||
|
* @date: 2019-01-23
|
||||||
|
*/
|
||||||
|
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const codePath = './src/'
|
||||||
|
|
||||||
|
const main = codePath => {
|
||||||
|
const traversing = cpath => {
|
||||||
|
const files = fs.readdirSync(cpath)
|
||||||
|
files.forEach(fileName => {
|
||||||
|
const fPath = path.join(cpath, fileName)
|
||||||
|
const stats = fs.statSync(fPath)
|
||||||
|
stats.isDirectory() && traversing(fPath)
|
||||||
|
stats.isFile() && fPath.endsWith('.ux') && matchAndReplace(fPath)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
traversing(codePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
const matchAndReplace = path => {
|
||||||
|
const pageContent = fs.readFileSync(path, 'UTF-8')
|
||||||
|
const newContent = pageContent.replace(
|
||||||
|
/(<)([\s]*?)(input\b[^\/]*?)>[\s\S]*?<\/input>/gm,
|
||||||
|
'$1$3 />'
|
||||||
|
)
|
||||||
|
fs.writeFile(path, newContent, error => {
|
||||||
|
if (error) throw `Something went wrong: ${error}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
main(codePath)
|
||||||
9
src/app.ux
Normal file
9
src/app.ux
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* 应用级别的配置,供所有页面公用
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default {
|
||||||
|
onCreate() {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
BIN
src/assets/images/logo.png
Normal file
BIN
src/assets/images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/assets/images/message-arrow.png
Normal file
BIN
src/assets/images/message-arrow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 426 KiB |
BIN
src/assets/images/up.bin.png
Normal file
BIN
src/assets/images/up.bin.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 348 B |
5
src/assets/styles/mixins.scss
Normal file
5
src/assets/styles/mixins.scss
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
@mixin flex-box-mixins($direction: row, $justify: center, $align-items: center) {
|
||||||
|
flex-direction: $direction;
|
||||||
|
justify-content: $justify;
|
||||||
|
align-items: $align-items;
|
||||||
|
}
|
||||||
2
src/assets/styles/style.scss
Normal file
2
src/assets/styles/style.scss
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
@import './variables.scss';
|
||||||
|
@import './mixins.scss';
|
||||||
9
src/assets/styles/variables.scss
Normal file
9
src/assets/styles/variables.scss
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
$brand: #09ba07;
|
||||||
|
|
||||||
|
$white: #ffffff;
|
||||||
|
$black: #000000;
|
||||||
|
$grey: #9393aa;
|
||||||
|
$red: #fa0101;
|
||||||
|
$green: #ffff00;
|
||||||
|
|
||||||
|
$size-factor: 5px;
|
||||||
36
src/manifest.json
Normal file
36
src/manifest.json
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"package": "com.chorblack.talk",
|
||||||
|
"name": "talk",
|
||||||
|
"versionName": "1.0.0",
|
||||||
|
"versionCode": 1,
|
||||||
|
"appCategory": [
|
||||||
|
"other"
|
||||||
|
],
|
||||||
|
"icon": "/assets/images/logo.png",
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"name": "blueos.app.appmanager.router"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"deviceTypeList": [
|
||||||
|
"watch",
|
||||||
|
"watch-square"
|
||||||
|
],
|
||||||
|
"config": {
|
||||||
|
"designWidth": 466
|
||||||
|
},
|
||||||
|
"router": {
|
||||||
|
"entry": "pages/Demo",
|
||||||
|
"pages": {
|
||||||
|
"pages/Demo": {
|
||||||
|
"component": "index"
|
||||||
|
},
|
||||||
|
"pages/DemoDetail": {
|
||||||
|
"component": "index"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"display": {
|
||||||
|
"backgroundColor": "#ffffff"
|
||||||
|
}
|
||||||
|
}
|
||||||
411
src/pages/Demo/index.ux
Normal file
411
src/pages/Demo/index.ux
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
<template>
|
||||||
|
<scroll
|
||||||
|
class="wrapper"
|
||||||
|
scrollbar="{{true}}"
|
||||||
|
bounces="{{true}}"
|
||||||
|
scroll-y="{{true}}"
|
||||||
|
id="wrapperbox">
|
||||||
|
<scroll
|
||||||
|
id="msgbox"
|
||||||
|
bounces="false"
|
||||||
|
scroll-y="true"
|
||||||
|
@scrolltop="scrolltopHandler"
|
||||||
|
@scrollbottom="scrollbottomHandler"
|
||||||
|
scroll-bottom="{{scrollbottom}}"
|
||||||
|
class="message-pannel">
|
||||||
|
<div
|
||||||
|
class="loading-wrap"
|
||||||
|
if="{{showLoading}}"
|
||||||
|
style="height:{{loadingHeight}}px">
|
||||||
|
<vw-loading size="48" class="loading"></vw-loading>
|
||||||
|
</div>
|
||||||
|
<div class="message" for="{{msgList}}">
|
||||||
|
<div class="message-item our" if="{{$item.side==='our'}}">
|
||||||
|
<text class="txt txt-our" if="{{$item.message}}">
|
||||||
|
{{ $item.message }}
|
||||||
|
</text>
|
||||||
|
<image class="img our" if="{{$item.img}}" src="{{$item.img}}"></image>
|
||||||
|
</div>
|
||||||
|
<div class="message-item other" else>
|
||||||
|
<text class="txt txt-other" if="{{$item.message}}">
|
||||||
|
{{ $item.message }}
|
||||||
|
</text>
|
||||||
|
<image
|
||||||
|
class="img other"
|
||||||
|
if="{{$item.img}}"
|
||||||
|
src="{{$item.img}}"></image>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="item-arrow" class="message-item-arrow" style="height: 184px">
|
||||||
|
<image
|
||||||
|
src="../../assets/images/message-arrow.png"
|
||||||
|
class="message-arrow"></image>
|
||||||
|
</div>
|
||||||
|
</scroll>
|
||||||
|
<scroll scroll-y="true" class="reply-pannel">
|
||||||
|
<div class="message-item-arrow" style="height: 124px">
|
||||||
|
<image
|
||||||
|
src="../../assets/images/reply-arrow.png"
|
||||||
|
class="reply-arrow"></image>
|
||||||
|
</div>
|
||||||
|
<div class="input-box">
|
||||||
|
<input
|
||||||
|
for="{{replyMsg}}"
|
||||||
|
class="btn"
|
||||||
|
type="button"
|
||||||
|
value="{{$item.value}}"
|
||||||
|
@click="reply($item.text)" />
|
||||||
|
</div>
|
||||||
|
</scroll>
|
||||||
|
</scroll>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
let num = 1
|
||||||
|
let a, b, c
|
||||||
|
export const listenMsg = (callback) => {
|
||||||
|
a = setInterval(() => {
|
||||||
|
const msg = '对方发来消息' + num++
|
||||||
|
console.log('msg', msg)
|
||||||
|
callback && callback(msg)
|
||||||
|
}, 5000)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
let histroy = [
|
||||||
|
{
|
||||||
|
side: 'other',
|
||||||
|
message: `借我500块钱!`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'other',
|
||||||
|
message: '急用!',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'other',
|
||||||
|
message: '收到回复!',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'our',
|
||||||
|
message: '🧧请查收',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'other',
|
||||||
|
message: '我们来念诗吧',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'our',
|
||||||
|
message: '好啊',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'other',
|
||||||
|
message: '天苍苍,野茫茫,风吹草地,现牛羊',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'our',
|
||||||
|
message: '床前明月光,疑是地上霜,举头望明月,低头思故乡',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const getHistroyMsg = (callback) => {
|
||||||
|
const arr = histroy.splice(0, 4)
|
||||||
|
c = setTimeout(() => {
|
||||||
|
callback(arr)
|
||||||
|
}, 1000)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fastReplyMsg = [
|
||||||
|
{
|
||||||
|
value: '语音',
|
||||||
|
text: '((( 15s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '表情',
|
||||||
|
text: '😄',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'OK',
|
||||||
|
text: 'OK',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '好的',
|
||||||
|
text: '好的',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '是的',
|
||||||
|
text: '是的',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '我在路上',
|
||||||
|
text: '我在路上',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '我到了',
|
||||||
|
text: '我到了',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '现在忙',
|
||||||
|
text: '现在忙,过会儿回复',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
export const msgList = [
|
||||||
|
{
|
||||||
|
side: 'our',
|
||||||
|
message: '新年快乐😄',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'other',
|
||||||
|
message: '新年快乐!',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'our',
|
||||||
|
message: '开工大吉',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'other',
|
||||||
|
message: '开工大吉!!',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'our',
|
||||||
|
message: '最近怎么样了啊',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'other',
|
||||||
|
message: '最近很好',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'our',
|
||||||
|
message: '那就好',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'our',
|
||||||
|
message: '好的',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
side: 'our',
|
||||||
|
message: '你借我的钱什么时候还',
|
||||||
|
},
|
||||||
|
{ side: 'other', img: '../../assets/images/message-arrow.png' },
|
||||||
|
{
|
||||||
|
side: 'our',
|
||||||
|
message: '还在吗😊',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
let loadHistroyMsgTimeId = -1
|
||||||
|
let listenMsgTimeId = -1
|
||||||
|
let getHistroyMsgTimeId = -1
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data: {
|
||||||
|
showLoading: false,
|
||||||
|
scrollbottom: '0',
|
||||||
|
clientHeight: 750,
|
||||||
|
loadingHeight: 100,
|
||||||
|
msgListRectHeight: -1,
|
||||||
|
msgList: msgList,
|
||||||
|
replyMsg: fastReplyMsg,
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
//listenMsgTimeId = listenMsg(this.otherPushMsg)
|
||||||
|
},
|
||||||
|
onDestroy() {
|
||||||
|
clearTimeout(loadHistroyMsgTimeId)
|
||||||
|
clearTimeout(getHistroyMsgTimeId)
|
||||||
|
clearInterval(listenMsgTimeId)
|
||||||
|
clearInterval(a)
|
||||||
|
clearTimeout(b)
|
||||||
|
clearTimeout(c)
|
||||||
|
},
|
||||||
|
async otherPushMsg(msg) {
|
||||||
|
const bFlag = await this.isArrowBottom()
|
||||||
|
this.pushMsg(msg, 'other')
|
||||||
|
this.nextTick(() => {
|
||||||
|
if (bFlag) {
|
||||||
|
this.$element('msgbox').scrollBy({
|
||||||
|
top: 10000,
|
||||||
|
left: 0,
|
||||||
|
behavior: 'smooth',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 模拟 nextTick 功能
|
||||||
|
*/
|
||||||
|
async nextTick(callBack) {
|
||||||
|
const height = await this.getRect()
|
||||||
|
if (height != this.msgListRectHeight) {
|
||||||
|
callBack && callBack()
|
||||||
|
} else {
|
||||||
|
b = setTimeout(() => {
|
||||||
|
this.nextTick(callBack)
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isArrowBottom() {
|
||||||
|
return new Promise((reslove) => {
|
||||||
|
this.$element('item-arrow').getBoundingClientRect({
|
||||||
|
success: (data) => {
|
||||||
|
reslove(data.bottom <= this.clientHeight)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async scrolltopHandler() {
|
||||||
|
if (this.showLoading) return
|
||||||
|
const oldHeight = await this.getRect()
|
||||||
|
this.showLoading = true
|
||||||
|
getHistroyMsgTimeId = getHistroyMsg((msgs) => {
|
||||||
|
this.msgList = [...msgs, ...this.msgList]
|
||||||
|
this.scrollbottom = `${oldHeight - this.clientHeight}`
|
||||||
|
this.showLoading = false
|
||||||
|
this.scrollbottom = `${
|
||||||
|
parseFloat(this.scrollbottom) + this.loadingHeight
|
||||||
|
}`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getRect() {
|
||||||
|
return new Promise((reslove) => {
|
||||||
|
this.$element('msgbox').getScrollRect({
|
||||||
|
success({ height }) {
|
||||||
|
reslove(height)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
reply(message) {
|
||||||
|
this.pushMsg(message, 'our')
|
||||||
|
this.nextTick(() => {
|
||||||
|
this.$element('msgbox').scrollBy({
|
||||||
|
top: 10000,
|
||||||
|
left: 0,
|
||||||
|
behavior: 'smooth',
|
||||||
|
})
|
||||||
|
this.$element('wrapperbox').scrollTo({
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
behavior: 'smooth',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async pushMsg(message, side) {
|
||||||
|
this.msgListRectHeight = await this.getRect()
|
||||||
|
this.msgList.push({
|
||||||
|
side,
|
||||||
|
message,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.wrapper {
|
||||||
|
width: 466px;
|
||||||
|
height: 100%;
|
||||||
|
flex-direction: column;
|
||||||
|
scroll-snap-type: y mandatory;
|
||||||
|
background-color: #000000;
|
||||||
|
}
|
||||||
|
.loading-wrap {
|
||||||
|
justify-content: center;
|
||||||
|
width: 466px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
@keyframes Rotate {
|
||||||
|
from {
|
||||||
|
transform: rotate(0);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.loading {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
/* 单个动画 */
|
||||||
|
animation-name: Rotate;
|
||||||
|
animation-fill-mode: forwards;
|
||||||
|
animation-duration: 1000ms;
|
||||||
|
}
|
||||||
|
.message-pannel {
|
||||||
|
width: 466px;
|
||||||
|
height: 100%;
|
||||||
|
scroll-snap-align: end;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.message {
|
||||||
|
width: 466px;
|
||||||
|
border: 1px solid #000;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.message-item {
|
||||||
|
width: 466px;
|
||||||
|
padding: 0 60px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.our {
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
.other {
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
.img {
|
||||||
|
object-fit: contain;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
.txt {
|
||||||
|
color: #f0f8ff;
|
||||||
|
padding: 20px;
|
||||||
|
max-width: 350px;
|
||||||
|
background-color: #405eff;
|
||||||
|
}
|
||||||
|
.txt-our {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.txt-other {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.reply-pannel {
|
||||||
|
width: 466px;
|
||||||
|
height: 100%;
|
||||||
|
scroll-snap-align: start;
|
||||||
|
}
|
||||||
|
.message-item-arrow {
|
||||||
|
width: 466px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.message-arrow {
|
||||||
|
height: 32px;
|
||||||
|
margin-bottom: 82px;
|
||||||
|
width: 32px;
|
||||||
|
}
|
||||||
|
.reply-arrow {
|
||||||
|
height: 32px;
|
||||||
|
width: 32px;
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
.input-box {
|
||||||
|
width: 466px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
width: 300px;
|
||||||
|
height: 80px;
|
||||||
|
padding-left: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
background-color: #405eff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
27
src/pages/DemoDetail/index.ux
Normal file
27
src/pages/DemoDetail/index.ux
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<template>
|
||||||
|
<div class="wrapper">
|
||||||
|
<text class="title">{{ text }}</text>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data: {
|
||||||
|
text: '你好,世界'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import './../../assets/styles/style.scss';
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
@include flex-box-mixins(column, center, center);
|
||||||
|
margin: 0 10 * $size-factor;
|
||||||
|
.title {
|
||||||
|
font-size: 8 * $size-factor;
|
||||||
|
text-align: center;
|
||||||
|
color: $black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
x
Reference in New Issue
Block a user