Commit 473fe247 authored by 程新智's avatar 程新智 👽

init

parents
Pipeline #148 canceled with stages
<style lang="scss">
/* 注意要写在第一行,同时给style标签加入lang="scss"属性 */
@import "./kui/components/uview-ui/index.scss";
@import "./kui/style/style.scss";
</style>
<script>
const url = 'http://euzhi.com/pingfang.ttf'
export default {
onLaunch: function () {
console.log('App onLaunch');
},
onShow: function () {
// #ifdef APP-PLUS
this.loadFontFaceFromLocal()
// #endif
},
onHide: function () {
console.log('App Hide')
},
methods: {
loadFontFaceFromWeb() {
uni.loadFontFace({
family: 'PingFang SC',
source: `url("${url}")`
})
},
// #ifdef APP-PLUS
loadFontFaceFromLocal() {
uni.loadFontFace({
family: 'PingFang SC',
// 本地字体路径需转换为平台绝对路径
source: `url(${plus.io.convertLocalFileSystemURL('_www/static/pingfang.ttf')})`,
success() {
console.log('success')
},
fail(e) {
console.log('fail')
}
})
},
async loadFontFaceFromCache() {
let tempFilePath
const savedFilePath = uni.getStorageSync('pingfang')
const [error, res] = await uni.getSavedFileList()
if (!error) {
const fileList = res.fileList
const file = fileList.find(file => file.filePath === savedFilePath)
if (file) {
tempFilePath = file.filePath
}
}
if (!tempFilePath) {
const [error, res] = await uni.downloadFile({
url,
})
if (!error) {
tempFilePath = res.tempFilePath
uni.saveFile({
tempFilePath,
success(res) {
uni.setStorage({
key: 'Pacifico',
data: res.savedFilePath
})
}
})
} else {
console.log('下载失败')
return
}
} else {
console.log('使用缓存资源,跳过下载步骤')
}
uni.loadFontFace({
family: 'PingFang SC',
source: `url("${plus.io.convertLocalFileSystemURL(tempFilePath)}")`
})
}
// #endif
}
}
</script>
<style lang="scss">
@import './kui/iconfont/iconfont.css';
@import './static/iconfont/iconfont.css';
@font-face {
font-family: 'PingFang SC';
src: url('./static/font/pingfang.ttf'); //你的资源目录
font-weight: normal;
font-style: normal;
}
html,body { font-family: PingFang SC, sans-serif; }
html,
body,
uni-page,
uni-page-body {
width: 750upx;
height: 100%;
overflow-x: hidden;
box-sizing: border-box;
background: #f9f9f9;
}
</style>
##成都市气瓶demo项目
此项目用来演示成都市液化石油气钢瓶智慧监管服务平台
\ No newline at end of file
File added
[
{
"qp0429":2,
"aaa413":"刘继旺",
"ntmbh":"",
"is_fenpei":true,
"status": 2,
"is_show":false,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000193",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000193",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000193",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"qp0429":2,
"aaa413":"刘继旺",
"ntmbh":"",
"status": 1,
"is_show":false,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000192",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000192",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000192",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"qp0429":2,
"aaa413":"刘继旺",
"ntmbh":"",
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000188",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000188",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000188",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"qp0429":2,
"aaa413":"刘继旺",
"ntmbh":"",
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000189",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000189",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000189",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"qp0429":2,
"aaa413":"刘继旺",
"ntmbh":"",
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000190",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000190",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000190",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"qp0429":2,
"aaa413":"刘继旺",
"ntmbh":"",
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000191",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000191",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000191",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"qp0429":2,
"aaa413":"刘继旺",
"ntmbh":"",
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000194",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000194",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000194",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"qp0429":2,
"aaa413":"刘继旺",
"ntmbh":"",
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000195",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000195",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000195",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
}
]
\ No newline at end of file
[
{
"id": "1372723948609040385",
"tmbh": "001200000005",
"gyh": "000000000005",
"zcsj":"2021-6-9",
"createUser": "1329661739607797761",
"createDept": "1329661736243965954",
"createTime": "2021-03-19 09:37:47",
"updateUser": "1329661739607797761",
"updateTime": "2021-03-23 17:55:48",
"status": 2,
"isDeleted": 0,
"tenantId": "418114",
"djpc": "DJ_测试-检验202103190054",
"sjdw": "汉源县永平燃气有限责任公司",
"sjrq": "2021-03-19 09:38:12",
"sjgs": 1,
"wjgs": 0,
"yjgs": 1,
"qp0101": "2320",
"djr": "检验员",
"djrId": "1343736553670832130",
"hgs": 1,
"bhgs": 0,
"scPftzs": "0",
"scJybg": "1",
"jybgId": "1318003103861063681",
"pfbgId": "1311203390608363521",
"bgbh": "CSG298271-11",
"pftzsbh": "",
"isUse": 1,
"qp0320": "",
"type": "civil-filling"
}
]
\ No newline at end of file
[{
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000188",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000188",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000188",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000189",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000189",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000188",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000190",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000190",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000188",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000191",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000191",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000188",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000192",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000192",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000188",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000193",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000193",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000188",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000194",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000194",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000188",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
},
{
"status": 1,
"aab001": "915101325826249478",
"aab002": "GI-四川广融压力容器有限公司",
"qp0100": "CY001202104000000000195",
"qp0101": "2320",
"qp0208": "002",
"qp0205": "000000000195",
"qp0204": "2021-04-30",
"qp0235": "测试气瓶",
"qp0106": "8",
"qp0102": "053",
"qp0209": "001",
"qp0210": "6.50",
"qp0104": "12.0",
"qp0105": "2.00",
"qp0212": "3.20",
"qp0103": "2.10",
"qp0218": "2025-04-30",
"qp0219": "2029-04-30",
"qp0220": "110",
"qp0607": "001200000188",
"aab00101": "12510100450756681W",
"aab00201": "颜-民用气瓶充装测试",
"maxFilling": "5.00"
}
]
\ No newline at end of file
import {
http
} from '@/kui/util/service.js'
import $config from '@/kui/config/config.js'
//充装记录
export const fillingList = (current, size, params) => http.request({
url: $config.serveUrl + 'filling/list',
method: 'get',
params: {
current,
size,
...params
}
});
//充装详情
export const fillingDetail = (id) => http.request({
url: $config.serveUrl + 'filling/detail',
method: 'get',
params: {
id
}
});
import {
http
} from '@/kui/util/service.js'
import $config from '@/kui/config/config.js'
//二维码可充装校验
export const fillable = (labelNum) => http.request({
url: $config.serveUrl + 'filling/fillable/'+labelNum,
method: 'get',
});
//根据岗位获取人员下拉选
export const employee = (codeAac007) => http.request({
url: $config.serveUrl + 'blade-user/employee/select',
method: 'get',
params:{
...codeAac007
}
});
//开始充装
export const startFilling = (obj) => http.request({
url: $config.serveUrl + 'filling/startFilling',
method: 'POST',
data:obj
});
//罐装设备下拉选码表
export const equipment = () => http.request({
url: $config.serveUrl + 'setting/equipment/select',
method: 'get',
});
//罐装
export const goFilling = (obj) => http.request({
url: $config.serveUrl + 'filling/goFilling',
method: 'POST',
data:obj
});
import {
http
} from '@/kui/util/service.js'
import $config from '@/kui/config/config.js'
//所有常用不分页
export const findUnitByTypes = (types) => http.request({
url: $config.serveUrl + 'blade-system/deptExpan/findUnitByTypes',
method: 'get',
params: {
types
}
});
//常用制造单位
export const common = (current, size, params) => http.request({
url: $config.serveUrl + 'blade-system/dept/common/page',
method: 'get',
params: {
current,
size,
...params
}
});
//删除企业
export const removeQy = (ids) => http.request({
url: $config.serveUrl + 'blade-system/dept/common/remove',
method: 'POST',
params: {
ids
}
});
//保存
export const submit = (fkDeptId) => http.request({
url: $config.serveUrl + 'blade-system/dept/common/submit',
method: 'POST',
data:fkDeptId
});
\ No newline at end of file
import {http} from '@/kui/util/service.js'
import $config from '@/kui/config/config.js'
export const code = () => http.request({
url: $config.serveUrl + 'blade-system/dict/dictionary?code=QP0208',
method: 'GET',
})
export const getList = (current, size, params) => {
return http.request({
url: $config.serveUrl + 'setting/model/list',
method: 'get',
params: {
...params,
current,
size,
}
})
}
export const remove = (ids) => {
return http.request({
url: $config.serveUrl + 'setting/model/remove',
method: 'post',
params: {
ids,
}
})
}
export const submit = (row) => {
return http.request({
url: $config.serveUrl + 'setting/model/submit',
method: 'post',
data: row
})
}
import {
http
} from '@/kui/util/service.js'
import $config from '@/kui/config/config.js'
/**
* 根据区划名称获取区划code
*/
export const findCodeByName = (params) => http.request({
url: $config.serveUrl + 'blade-system/region-ext/findByName',
method: 'get',
params: {
...params
}
});
/*
附件上传-生成缩略图
*/
export const httpUpload = (file, bucketName) =>
http.request({
url: $config.serveUrl + 'blade-filling/filling/data/put-file',
method: 'UPLOAD',
filePath: file,
name: 'file',
formData: {
'bucketName': bucketName
},
});
/*
获取对应子机构列表
*/
export const unitClist = (params) => http.request({
url: $config.serveUrl + 'blade-system/deptExpan/findChildrenUnitByTypes',
method: 'get',
params: {
...params
}
});
//附件上传
export const putFile = (file, bucketName) =>
http.request({
url: $config.serveUrl + 'blade-resource/oss/endpoint/put-file',
method: 'UPLOAD',
filePath: file,
name: 'file',
formData: {
'bucketName': bucketName
},
});
\ No newline at end of file
import {
http
} from '@/kui/util/service.js'
import $config from '@/kui/config/config.js'
//根据制造编号获取气瓶档案
export const getQp0205 = (qp0205) => http.request({
url: $config.serveUrl + 'label/cylinder/qp0205/'+qp0205,
method: 'get',
});
//标签校验
export const applicability = (labelNum) => http.request({
url: $config.serveUrl + 'label/applicability',
method: 'post',
params: {
...labelNum
}
});
//标签变更
export const submit = (obj) => http.request({
url: $config.serveUrl + 'label/change/submit',
method: 'post',
data:obj
});
//气瓶型号下拉选码表
export const select = () => http.request({
url: $config.serveUrl + 'setting/model/select',
method: 'get',
});
//标签绑定保存
export const save = (obj) => http.request({
url: $config.serveUrl + 'label/cylinder/save',
method: 'post',
data:obj
});
import {
http
} from '@/kui/util/service.js'
import $config from '@/kui/config/config.js'
//标签注册列表
export const list = (current, size, params) => http.request({
url: $config.serveUrl + 'label/list',
method: 'get',
params: {
current,
size,
...params
}
});
//删除标签
export const remove = (ids) => http.request({
url: $config.serveUrl + 'label/remove',
method: 'POST',
params: {
ids
}
});
//标签详情
export const detail = (id) => http.request({
url: $config.serveUrl + 'label/detail',
method: 'get',
params: {
id
}
});
//单个注册
export const sigle = (params) => http.request({
url: $config.serveUrl + 'label/register/sigle',
method: 'POST',
data: params
});
//批量注册
export const multiple = (params) => http.request({
url: $config.serveUrl + 'label/register/multiple',
method: 'POST',
data: params
});
//选择企业列表
export const findUnitByTypesPages = (current, size, params) => http.request({
url: $config.serveUrl + 'blade-system/deptExpan/findUnitByTypesPages',
method: 'get',
params: {
current,
size,
...params
}
});
//所有常用不分页
export const findUnitByTypes = (types) => http.request({
url: $config.serveUrl + 'blade-system/deptExpan/findUnitByTypes',
method: 'get',
params: {
types
}
});
findUnitByTypesPages
//常用制造单位
export const common = (current, size, params) => http.request({
url: $config.serveUrl + 'blade-system/dept/common/page',
method: 'get',
params: {
current,
size,
...params
}
});
import {
http
} from '@/kui/util/service.js'
import $config from '@/kui//config/config.js'
export const loginByUsername = (tenantId, username, password) => http.request({
url: $config.serveUrl + 'blade-auth/oauth/token/',
method: 'POST',
header: {
'Tenant-Id': tenantId,
'Content-Type': 'application/x-www-form-urlencoded',
},
params: {
tenantId,
username,
password,
grant_type: "password",
scope: "all",
}
})
export const code = () => http.request({
url: $config.serveUrl + 'blade-system/dict/dictionary?code=QP0102',
method: 'GET',
})
export const info = (domain) => {
return http.request({
url: $config.serveUrl + 'blade-system/tenant/info',
method: 'get',
params: {
domain
}
})
}
export const logout = () => http.request({
url: $config.serveUrl + 'blade-auth/oauth/logout',
method: 'get'
})
//当前用户所属机构
export const userjg = () => http.request({
url: $config.serveUrl + 'blade-system/user/info',
method: 'get'
})
//修改密码
export const updatePassword = (oldPassword, newPassword, newPassword1) => http.request({
url: $config.serveUrl + 'blade-user/update-password',
method: 'post',
params: {
oldPassword,
newPassword,
newPassword1,
}
})
<template>
<view class="mask" :class="!show?'':'mask-show'" :style="{backgroundColor:show?maskBg:'rgba(0,0,0,0)'}" @tap="tapMask">
<view class="popups" :class="[theme]"
:style="{top: popupsTop ,left: popupsLeft,flexDirection:direction}">
<text :class="dynPlace" :style="{width:'0px',height:'0px'}" v-if="triangle"></text>
<view v-for="(item,index) in popData" :key="index" @tap.stop="tapItem(item)"
class="itemChild view" :class="[direction=='row'?'solid-right':'solid-bottom',item.disabled?'disabledColor':'']">
<image class="image" :src="item.icon" v-if="item.icon"></image>{{item.title}}
</view>
<slot></slot>
</view>
</view>
</template>
<script>
export default{
props:{
maskBg:{
type:String,
default:'rgba(0,0,0,0)'
},
placement:{
type:String,
default:'default' //default top-start top-end bottom-start bottom-end
},
direction:{
type:String,
default:'column' //column row
},
x:{
type:Number,
default:0
},
y:{
type:Number,
default:0
},
value:{
type:Boolean,
default:false
},
popData:{
type:Array,
default:()=>[]
},
theme:{
type:String,
default:'light' //light dark
},
dynamic:{
type:Boolean,
default:false
},
gap:{
type:Number,
default:20
},
triangle:{
type:Boolean,
default:true
}
},
data(){
return{
popupsTop:'0px',
popupsLeft:'0px',
show:false,
dynPlace:''
}
},
mounted() {
this.popupsPosition()
},
methods:{
tapMask(){
this.$emit('input',!this.value)
},
tapItem(item){
if(item.disabled) return
this.$emit('tapPopup',item)
this.$emit('input',!this.value)
},
getStatusBar(){
let promise = new Promise((resolve,reject)=>{
uni.getSystemInfo({
success: function(e) {
let customBar
// #ifdef H5
customBar = e.statusBarHeight + e.windowTop;
// #endif
resolve(customBar)
}
})
})
return promise
},
async popupsPosition(){
let statusBar = await this.getStatusBar()
let promise = new Promise((resolve,reject)=>{
let popupsDom = uni.createSelectorQuery().in(this).select(".popups")
popupsDom.fields({
size: true,
}, (data) => {
let width = data.width
let height = data.height
let y = this.dynamic?this.dynamicGetY(this.y,this.gap):this.transformRpx(this.y)
let x = this.dynamic?this.dynamicGetX(this.x,this.gap):this.transformRpx(this.x)
// #ifdef H5
y = this.dynamic?(this.y+statusBar): this.transformRpx(this.y+statusBar)
// #endif
this.dynPlace = this.placement=='default'?this.getPlacement(x,y):this.placement
switch(this.dynPlace){
case 'top-start':
this.popupsTop = `${y+9}px`
this.popupsLeft = `${x-15}px`
break;
case 'top-end':
this.popupsTop = `${y+9}px`
this.popupsLeft = `${x+15-width}px`
break;
case 'bottom-start':
this.popupsTop = `${y-18-height}px`
this.popupsLeft = `${x-15}px`
break;
case 'bottom-end':
this.popupsTop = `${y-9-height}px`
this.popupsLeft = `${x+15-width}px`
break;
}
resolve()
}).exec();
})
return promise
},
getPlacement(x,y){
let width = uni.getSystemInfoSync().windowWidth
let height = uni.getSystemInfoSync().windowHeight
if(x>width/2&&y>height/2){
return 'bottom-end'
}else if(x<width/2&&y<height/2){
return 'top-start'
}else if(x>width/2&&y<height/2){
return 'top-end'
}else if(x<width/2&&y>height/2){
return 'bottom-start'
}else if(x>width/2){
return 'top-end'
}else{
return 'top-start'
}
},
dynamicGetY(y,gap){
let height = uni.getSystemInfoSync().windowHeight
y = y<gap?gap:y
y = height - y <gap? (height - gap) : y
return y
},
dynamicGetX(x,gap){
let width = uni.getSystemInfoSync().windowWidth
x = x< gap?gap:x
x = width - x <gap? (width - gap) : x
return x
},
transformRpx(params){
return params*uni.getSystemInfoSync().screenWidth/375
}
},
watch:{
value:{
immediate:true,
handler:async function (newVal,oldVal){
if(newVal) await this.popupsPosition()
this.show = newVal
}
},
placement:{
immediate:true,
handler(newVal,oldVal){
this.dynPlace = newVal
}
}
}
}
</script>
<style lang="scss" scoped>
.mask{
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 9999;
transition: background 0.3s ease-in-out;
visibility: hidden;
&.mask-show{
visibility: visible;
}
}
.popups{
position: absolute;
padding: 20rpx;
border-radius: 5px;
display:flex;
.view{
padding: 10rpx;
}
.image{
display: inline-block;
vertical-align: middle;
width: 40rpx;
height: 40rpx;
margin-right: 20rpx;
}
}
.dark{
background-color: #4C4C4C;
color: #fff;
.top-start:after {
content: "";
position: absolute;
top: -18rpx;
left: 10rpx;
border-width: 0 20rpx 20rpx;
border-style: solid;
border-color: transparent transparent #4C4C4C;
}
.top-end:after {
content: "";
position: absolute;
top: -18rpx;
right: 10rpx;
border-width: 0 20rpx 20rpx;
border-style: solid;
border-color: transparent transparent #4C4C4C;
}
.bottom-start:after {
content: "";
position: absolute;
bottom: -18rpx;
left: 10rpx;
border-width: 20rpx 20rpx 0 ;
border-style: solid;
border-color: #4C4C4C transparent transparent ;
}
.bottom-end:after {
content: "";
position: absolute;
bottom: -18rpx;
right: 10rpx;
border-width: 20rpx 20rpx 0 ;
border-style: solid;
border-color: #4C4C4C transparent transparent ;
}
.disabledColor{
color: #c5c8ce;
}
}
.light{
color: #515a6e;
box-shadow: 0upx 0upx 30upx rgba(0,0,0,0.2);
background: #fff;
.top-start:after {
content: "";
position: absolute;
top: -18rpx;
left: 10rpx;
border-width: 0 20rpx 20rpx;
border-style: solid;
border-color: transparent transparent #fff;
}
.top-end:after {
content: "";
position: absolute;
top: -18rpx;
right: 10rpx;
border-width: 0 20rpx 20rpx;
border-style: solid;
border-color: transparent transparent #fff;
}
.bottom-start:after {
content: "";
position: absolute;
bottom: -18rpx;
left: 10rpx;
border-width: 20rpx 20rpx 0 ;
border-style: solid;
border-color: #fff transparent transparent ;
}
.bottom-end:after {
content: "";
position: absolute;
bottom: -18rpx;
right: 10rpx;
border-width: 20rpx 20rpx 0 ;
border-style: solid;
border-color: #fff transparent transparent ;
}
.disabledColor{
color: #c5c8ce;
}
}
.solid-bottom{
border-bottom: 1px solid #ccc;
}
.solid-right{
border-right: 1px solid #ccc;
}
.popups .itemChild:last-child{
border: none;
}
</style>
<template>
<view class="weui-tabbar" :class="extClass">
<view @click="tabChange(index)" v-for="(item, index) in list" :key="index" class="weui-tabbar__item" :class="{'weui-bar__item_on':index === current}">
<view style="position: relative;display:inline-block;"><image :src="current === index ? item.selectedIconPath : item.iconPath" class="weui-tabbar__icon"></image></view>
<view class="weui-tabbar__label">{{ item.text }}</view>
</view>
</view>
</template>
<script>
export default {
props: {
list: {
type: Array,
default: function() {
return []
}
}
},
data() {
return {
extClass: '',
current: 0
};
},
methods: {
tabChange(index) {
if (index === this.current) {
return;
}
this.current = index;
this.$emit('tabChange',index)
}
}
};
</script>
<style lang="scss" scoped >
.weui-tabbar {
display: flex;
position: relative;
z-index: 500;
background-color: #ffffff;
}
.weui-tabbar:before {
content: ' ';
position: absolute;
left: 0;
top: 0;
right: 0;
height: 1px;
border-top: 1rpx solid rgba(0, 0, 0, 0.1);
color: rgba(0, 0, 0, 0.1);
}
.weui-tabbar__item {
display: block;
flex: 1;
padding: 8px 0 4px;
padding-bottom: calc(8px + constant(safe-area-inset-bottom));
padding-bottom: calc(8px + env(safe-area-inset-bottom));
font-size: 0;
color: rgba(0, 0, 0, 0.5);
text-align: center;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.weui-tabbar__item:first-child {
padding-left: constant(safe-area-inset-left);
padding-left: env(safe-area-inset-left);
}
.weui-tabbar__item:last-child {
padding-right: constant(safe-area-inset-right);
padding-right: env(safe-area-inset-right);
}
.weui-tabbar__item.weui-bar__item_on .weui-tabbar__icon,
.weui-tabbar__item.weui-bar__item_on .weui-tabbar__icon > i,
.weui-tabbar__item.weui-bar__item_on .weui-tabbar__label {
color: #5a77ff;
}
.weui-tabbar__icon {
display: inline-block;
width: 32rpx;
height: 32rpx;
margin-bottom: 2px;
}
i.weui-tabbar__icon,
.weui-tabbar__icon > i {
font-size: 24px;
color: rgba(0, 0, 0, 0.5);
}
.weui-tabbar__icon image {
width: 100%;
height: 100%;
}
.weui-tabbar__label {
color: #333;
font-size: 10px;
line-height: 1.4;
}
</style>
<template>
<view class="load-refresh">
<!-- 刷新动画 -->
<view class="refresh hollow-dots-spinner">
<view class="dot" :style="[{animationPlayState: playState}]"></view>
<view class="dot" :style="[{animationPlayState: playState}]"></view>
<view class="dot" :style="[{animationPlayState: playState}]"></view>
</view>
<view class="cover-container" :style="[{
background: backgroundCover,
transform: coverTransform,
transition: coverTransition
}]" @touchstart="coverTouchstart" @touchmove="coverTouchmove" @touchend="coverTouchend">
<scroll-view scroll-y show-scrollbar="true" class="list" :scroll-top="scrollTop" @scrolltolower="loadMore" :style="getHeight">
<!-- 数据集插槽 -->
<slot name="content-list"></slot>
<!-- 上拉加载 -->
<view v-if="isKong" class="load-more">{{loadText}}</view>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
name: 'loadRefresh',
props: {
isKong: {
type: Boolean,
defaule: true
},
isRefresh: {
type: Boolean,
defaule: true
},
refreshTime: {
type: Number,
default: 800
},
heightReduce: {
type: Number,
default: 0
},
backgroundCover: {
type: String,
default: 'white'
},
pageNo: {
type: Number,
default: 0
},
totalPageNo: {
type: Number,
default: 0
}
},
data() {
return {
startY: 0,
moveY: 0,
hasMore: true,
moving: false,
refresh: false,
loading: false,
scrollTop: -1,
coverTransform: 'translateY(0px)',
coverTransition: '0s',
playState: 'paused' // 动画的状态 暂停/开始
}
},
computed: {
// 计算组件所占屏幕高度
getHeight() {
let height = uni.getSystemInfoSync().windowHeight - uni.upx2px(0 + this.heightReduce)
return `height: ${height}px;`
},
// 判断loadText
// 可以根据需求自定义
loadText() {
const {
pageNo,
totalPageNo,
loading
} = this
if (loading) {
return '加载中...'
} else if (pageNo < totalPageNo) {
return '上拉加载更多'
} else {
return '已经到底啦~'
}
}
},
watch: {
// 监听refresh值 避免多次触发@refresh
'refresh'(val) {
if (val) {
this.$emit('refresh')
}
}
},
methods: {
// 根据pageNo和totalPageNo的值来判断 是否触发@loadMore
loadMore() {
const {
pageNo,
totalPageNo
} = this
if (pageNo < totalPageNo) {
this.loading = true
this.$emit('loadMore')
}
},
// 单次加载结束
loadOver() {
this.loading = false
},
// 回弹效果
coverTouchstart(e) {
if (!this.isRefresh) {
return
}
this.coverTransition = 'transform .1s linear'
this.startY = e.touches[0].clientY
},
coverTouchmove(e) {
if (!this.isRefresh || this.refresh) {
return
}
this.moveY = e.touches[0].clientY
let moveDistance = this.moveY - this.startY
if (moveDistance < 0) {
this.moving = false
return
}
this.moving = true
if (moveDistance >= 60) {
this.refresh = true
this.coverTransform = `translateY(60px)`
this.playState = 'running'
}
},
coverTouchend() {
if (!(this.isRefresh && this.refresh)) {
return
}
setTimeout(() => {
if (this.moving === false) {
return
}
this.moving = false
this.refresh = false
this.coverTransition = 'transform 0.3s cubic-bezier(.21,1.93,.53,.64)'
this.coverTransform = 'translateY(0px)'
this.playState = 'paused'
}, this.refreshTime)
},
runRefresh() {
// 开始
this.scrollTop = 0
this.refresh = true
this.coverTransition = 'transform .1s linear'
this.coverTransform = `translateY(60px)`
this.playState = 'running'
// 结束
setTimeout(() => {
this.scrollTop = -1
this.refresh = false
this.coverTransition = 'transform 0.3s cubic-bezier(.21,1.93,.53,.64)'
this.coverTransform = 'translateY(0px)'
this.playState = 'paused'
}, this.refreshTime)
}
}
}
</script>
<style lang="scss" scoped>
.load-refresh {
margin: 0;
padding: 0;
width: 100%;
.refresh {
display: flex;
align-items: center;
justify-content: center;
height: 120rpx;
width: 100%;
}
.hollow-dots-spinner,
.hollow-dots-spinner * {
box-sizing: border-box;
}
.hollow-dots-spinner {
height: 100rpx;
width: 100%;
}
.hollow-dots-spinner .dot {
width: 15px;
height: 15px;
margin: 0 calc(15px / 2);
border: calc(15px / 5) solid #04C4C4;
border-radius: 50%;
float: left;
transform: scale(0);
animation: hollow-dots-spinner-animation 1000ms ease infinite 0ms;
}
.hollow-dots-spinner .dot:nth-child(1) {
animation-delay: calc(300ms * 1);
}
.hollow-dots-spinner .dot:nth-child(2) {
animation-delay: calc(300ms * 2);
}
.hollow-dots-spinner .dot:nth-child(3) {
animation-delay: calc(300ms * 3);
}
@keyframes hollow-dots-spinner-animation {
50% {
transform: scale(1);
opacity: 1;
}
100% {
opacity: 0;
}
}
.cover-container {
width: 100%;
margin-top: -100rpx;
.list {
width: 100%;
.load-more {
font-size: 20rpx;
text-align: center;
color: #AAAAAA;
padding: 16rpx;
}
}
}
}
</style>
<template>
<view class="versionUpgrade" v-if="show">
<view class="versionUpgradeView">
<view class="versionUpgradeViewV1">
<image class="img" src="./icon/upgrade.png" mode="aspectFill"></image>
<text class="v-text">发现新版本啦!</text>
</view>
<view class="versionUpgradeViewV2">
<text class="content-text">{{describe}}</text>
<view class="versionUpgradeViewIs_force0" v-if="is_force==false&&start==false">
<text class="text butClose" @click="close">下次在说</text>
<text class="text download" @click="downUpdate()">立即更新</text>
</view>
<view class="versionUpgradeViewIs_force0" v-if="is_force==true&&start==false">
<text class="downloadIs_force1" @click="downUpdate()">立即更新</text>
</view>
<view class="versionUpgradeViewStartTrue" v-if="start!=false">
<text class="title">下载进度</text>
<progress :percent="start" activeColor="#FF5722" :show-info="true" stroke-width="6" ></progress>
</view>
<view class="versionUpgradeViewStartTrue" v-if="start!=false">
<text class="btn-text downloadStartTrue" v-if="start>=100" @click="install()">立即安装</text>
<text class="btn-text downloadStartFalse" v-else>立即安装</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'luo-version-upgrade',
props: {
version: {
type: String,
default () {
return '1.0.0';
}
},
versionType: {
type: String,
default () {
return 'android';
}
},
url: {
type: String,
default () {
return '';
}
},
describe:{
type: String,
default () {
return '有新版本出现~为了给您带来更好的体验,我们建议您现在进行升级!';
}
},
is_force:{
type: Boolean,
default () {
return false;
}
}
},
data() {
return {
show:false,
start:false,
installPath:''
};
},
watch:{
'version': {
handler (newVal) {
if(newVal!='1.0.0'){
this.getVerison();
}
},
deep: true,
immediate: true,
}
},
computed:{
versionTypes(){
return this.getPlatform(); //版本获取
}
},
methods:{
/* 版本比较是否需要更新 */
getVerison:function(){
if(this.version=='1.0.0'||this.url==''){return;}
//ios端判断
if(this.versionType=='ios'||this.versionTypes=='ios'){
plus.nativeUI.alert('无法进行在线升级,请到AppStore进行升级..','提示');
return;
}
if(this.versionType=='android'&&this.versionTypes=='android'){this.update();}
},
// 升级检测
update:function() {
let self = this;
/* 5+环境锁定屏幕方向 */
plus.screen.lockOrientation('portrait-primary'); //锁定
//客户端信息
plus.runtime.getProperty(plus.runtime.appid,function(res){
let isupdate = self.isUpdate(res.version, self.version);
if (isupdate) {self.versionShow();return;}
})
},
/**
* 比较版本大小,如果新版本nv大于旧版本ov则返回true,否则返回false
* @param {String} ov
* @param {String} nv
* @return {Boolean}
*/
isUpdate:function(ov, nv) {
if (!ov || !nv || ov == "" || nv == "") {return false;}
var b = false,
ova = ov.replace("V", "").replace("v", "").replace(" ", '').split(".", 4),
nva = nv.replace("V", "").replace("v", "").replace(" ", '').split(".", 4);
for (var i = 0; i < ova.length && i < nva.length; i++) {
var so = ova[i],
no = parseInt(so),
sn = nva[i],
nn = parseInt(sn);
if (nn > no || sn.length > so.length) {
return true;
} else if (nn < no) {
return false;
}
}
if (nva.length > ova.length && 0 == nv.indexOf(ov)) {
return true;
} else {return false;}
},
/* 获取版本类别 android/ios */
getPlatform:function(){
return uni.getSystemInfoSync().platform.toLowerCase();
},
/* 开启升级 */
versionShow:function(){
this.show = true;
uni.hideTabBar();
},
/* 取消升级 */
close:function(){
this.show = false;
uni.showTabBar();
},
downUpdate:function() {
//平台判断
if (this.versionTypes=='ios') {
plus.nativeUI.alert('无法进行在线升级,请到AppStore进行升级..','提示');
this.close();
return;
}
//检测是否下载过更新
let self = this;
self.installPath = uni.getStorageSync('update_path');
plus.io.resolveLocalFileSystemURL(
self.installPath,
function(entry) {self.install();return;},
function(err) {
const dtask = plus.downloader.createDownload(self.url,{filename: '_downloads/'});
dtask.addEventListener("statechanged", onStateChanged, false);
dtask.start();
}
);
//下载状态
function onStateChanged(download, status){
let totalSize = download.totalSize;
let useSize = download.downloadedSize;
self.start = (useSize/totalSize*100).toFixed(0);
// 下载完成
if(download.state == 4 && status == 200){
self.installPath = download.filename;
uni.setStorageSync('update_path', self.installPath);
//需要用户点击立即安装才能安装去掉注释掉self.install();
//self.install();
}
}
},
//安装提示
install:function() {
this.close();
plus.nativeUI.showWaiting('安装中,请稍后...');
plus.runtime.install(this.installPath,{},(res)=>{
plus.nativeUI.closeWaiting();
plus.runtime.restart();
uni.removeStorageSync("update_path");
},(err)=>{
plus.nativeUI.closeWaiting();
plus.nativeUI.alert('error '+err.code,'','提示');
});
}
}
}
</script>
<style lang="scss" scoped>
.versionUpgrade{
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 999999;
background: rgba(0, 0, 0, 0.3);
.versionUpgradeView{
z-index: 9999999;
margin: 500rpx 60rpx 0 60rpx;
min-height: 200rpx;
max-height: 800rpx;
background: #FFFFFF;
border-radius: 30rpx;
display: flex;
flex-direction: column !important;
//padding: 30rpx;
overflow: hidden;
.versionUpgradeViewV1{
display: flex;
flex-direction: row !important;
justify-content: center;
align-items: center;
background: #FF5722;
padding: 10rpx 0;
color: #FFFFFF;
.img{
width: 60rpx;
height: 60rpx;
}
.v-text{font-size: 16px;margin-left: 10rpx;}
}
.versionUpgradeViewV2{
display: flex;
flex-direction: column !important;
padding: 30upx;
.content-text{
font-size: 14px;
color: #626262;
}
.versionUpgradeViewIs_force0{
display: flex;
flex-direction: row !important;
justify-content: space-between;
padding: 30rpx 0 0 0;
.text{
padding: 10rpx 70rpx;
border-radius: 30rpx;
font-size: 16px;
color: #FFFFFF;
}
.butClose{
background: #e2e2e2;
}
.download{
background: #FF5722;
}
.downloadIs_force1{
width: 100%;
display: flex;
justify-content: center;
align-items: center;
padding: 10rpx 0;
border-radius: 30rpx;
font-size: 16px;
color: #FFFFFF;
background: #FF5722;
}
}
.versionUpgradeViewStartTrue{
display: flex;
flex-direction: column !important;
padding: 30rpx 0 0 0;
.title{
font-size: 14px;
color: #626262;
padding: 10rpx 0;
}
.btn-text{
width: 100%;
display: flex;
justify-content: center;
align-items: center;
padding: 10rpx 0;
border-radius: 30rpx;
font-size: 16px;
color: #FFFFFF;
}
.downloadStartTrue{background: #FF5722;}
.downloadStartFalse{background: #e2e2e2;}
}
}
}
}
</style>
<template>
<div>
<list :data='data' :page='page' :option='option' />
</div>
</template>
<script>
import list from './list'
export default {
components: {
list
},
data() {
return {
option: {
column: [{
label: '调入单位',
prop: 'aaa305',
width: '100%',
search: true,
},
{
label: '调出单位',
prop: 'aaa304',
width: '100%',
search: true,
},
{
label: '运输时间',
prop: 'aaa303',
width: '100%',
search: true,
},
{
label: '运输车辆',
prop: 'abg001',
width: '50%'
},
{
label: '配送人员',
prop: 'sjName',
width: '50%'
},
{
label: '签收状态',
prop: 'signStatus',
width: '50%',
type:"select",
dicData: [{
label: "未签收",
value: 0
},
{
label: "签收中",
value: 1
},
{
label: "已签收",
value: 2
}
],
},
{
label: '重瓶数量',
prop: 'aaa306Nums',
width: '50%'
},
{
label: '空瓶数量',
prop: 'aaa307Nums',
width: '50%'
},
{
label: '已签重瓶',
prop: 'aaa306Signed',
width: '50%'
},
{
label: '已签空瓶',
prop: 'aaa307Signed',
width: '50%'
},
]
},
data: [],
page: {
pageSize: 10,
currentPage: 1,
total: 0,
}
}
},
}
</script>
<style lang="scss" scoped>
</style>
This diff is collapsed.
MIT License
Copyright (c) 2020 www.uviewui.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
<p align="center">
<img alt="logo" src="https://uviewui.com/common/logo.png" width="120" height="120" style="margin-bottom: 10px;">
</p>
<h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uView</h3>
<h3 align="center">多平台快速开发的UI框架</h3>
## 说明
uView UI,是[uni-app](https://uniapp.dcloud.io/)生态优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水
## 特性
- 兼容安卓,iOS,微信小程序,H5,QQ小程序,百度小程序,支付宝小程序,头条小程序
- 60+精选组件,功能丰富,多端兼容,让您快速集成,开箱即用
- 众多贴心的JS利器,让您飞镖在手,召之即来,百步穿杨
- 众多的常用页面和布局,让您专注逻辑,事半功倍
- 详尽的文档支持,现代化的演示效果
- 按需引入,精简打包体积
## 安装
```bash
# npm方式安装
npm i uview-ui
```
## 快速上手
1. `main.js`引入uView库
```js
// main.js
import uView from 'uview-ui';
Vue.use(uView);
```
2. `App.vue`引入基础样式(注意style标签需声明scss属性支持)
```css
/* App.vue */
<style lang="scss">
@import "uview-ui/index.scss";
</style>
```
3. `uni.scss`引入全局scss变量文件
```css
/* uni.scss */
@import "uview-ui/theme.scss";
```
4. `pages.json`配置easycom规则(按需引入)
```js
// pages.json
{
"easycom": {
// npm安装的方式不需要前面的"@/",下载安装的方式需要"@/"
// npm安装方式
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
// 下载安装方式
// "^u-(.*)": "@/uview-ui/components/u-$1/u-$1.vue"
},
// 此为本身已有的内容
"pages": [
// ......
]
}
```
请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容
## 使用方法
配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。
```html
<template>
<u-button>按钮</u-button>
</template>
```
请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容
## 链接
- [官方文档](https://uviewui.com/)
- [更新日志](https://uviewui.com/components/changelog.html)
- [升级指南](https://uviewui.com/components/changelog.html)
- [关于我们](https://uviewui.com/cooperation/about.html)
## 预览
您可以通过**微信**扫码,查看最佳的演示效果。
<br>
<br>
<img src="https://uviewui.com/common/weixin_mini_qrcode.png" width="220" height="220" >
<!-- ## 捐赠uView的研发
uView文档和源码全部开源免费,如果您认为uView帮到了您的开发工作,您可以捐赠uView的研发工作,捐赠无门槛,哪怕是一杯可乐也好(相信这比打赏主播更有意义)。
<img src="https://uviewui.com/common/wechat.png" width="220" >
<img style="margin-left: 100px;" src="https://uviewui.com/common/alipay.png" width="220" >
-->
## 版权信息
uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。
<template>
<u-popup mode="bottom" :border-radius="borderRadius" :popup="false" v-model="value" :maskCloseAble="maskCloseAble"
length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="popupClose" :z-index="uZIndex">
<view class="u-tips u-border-bottom" v-if="tips.text" :style="[tipsStyle]">
{{tips.text}}
</view>
<block v-for="(item, index) in list" :key="index">
<view
@touchmove.stop.prevent
@tap="itemClick(index)"
:style="[itemStyle(index)]"
class="u-action-sheet-item u-line-1"
:class="[index < list.length - 1 ? 'u-border-bottom' : '']"
:hover-stay-time="150"
>
<text>{{item.text}}</text>
<text class="u-action-sheet-item__subtext u-line-1" v-if="item.subText">{{item.subText}}</text>
</view>
</block>
<view class="u-gab" v-if="cancelBtn">
</view>
<view @touchmove.stop.prevent class="u-actionsheet-cancel u-action-sheet-item" hover-class="u-hover-class"
:hover-stay-time="150" v-if="cancelBtn" @tap="close">{{cancelText}}</view>
</u-popup>
</template>
<script>
/**
* actionSheet 操作菜单
* @description 本组件用于从底部弹出一个操作菜单,供用户选择并返回结果。本组件功能类似于uni的uni.showActionSheetAPI,配置更加灵活,所有平台都表现一致。
* @tutorial https://www.uviewui.com/components/actionSheet.html
* @property {Array<Object>} list 按钮的文字数组,见官方文档示例
* @property {Object} tips 顶部的提示文字,见官方文档示例
* @property {String} cancel-text 取消按钮的提示文字
* @property {Boolean} cancel-btn 是否显示底部的取消按钮(默认true)
* @property {Number String} border-radius 弹出部分顶部左右的圆角值,单位rpx(默认0)
* @property {Boolean} mask-close-able 点击遮罩是否可以关闭(默认true)
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配(默认false)
* @property {Number String} z-index z-index值(默认1075)
* @property {String} cancel-text 取消按钮的提示文字
* @event {Function} click 点击ActionSheet列表项时触发
* @event {Function} close 点击取消按钮时触发
* @example <u-action-sheet :list="list" @click="click" v-model="show"></u-action-sheet>
*/
export default {
name: "u-action-sheet",
props: {
// 点击遮罩是否可以关闭actionsheet
maskCloseAble: {
type: Boolean,
default: true
},
// 按钮的文字数组,可以自定义颜色和字体大小,字体单位为rpx
list: {
type: Array,
default () {
// 如下
// return [{
// text: '确定',
// color: '',
// fontSize: ''
// }]
return [];
}
},
// 顶部的提示文字
tips: {
type: Object,
default () {
return {
text: '',
color: '',
fontSize: '26'
}
}
},
// 底部的取消按钮
cancelBtn: {
type: Boolean,
default: true
},
// 是否开启底部安全区适配,开启的话,会在iPhoneX机型底部添加一定的内边距
safeAreaInsetBottom: {
type: Boolean,
default: false
},
// 通过双向绑定控制组件的弹出与收起
value: {
type: Boolean,
default: false
},
// 弹出的顶部圆角值
borderRadius: {
type: [String, Number],
default: 0
},
// 弹出的z-index值
zIndex: {
type: [String, Number],
default: 0
},
// 取消按钮的文字提示
cancelText: {
type: String,
default: '取消'
}
},
computed: {
// 顶部提示的样式
tipsStyle() {
let style = {};
if (this.tips.color) style.color = this.tips.color;
if (this.tips.fontSize) style.fontSize = this.tips.fontSize + 'rpx';
return style;
},
// 操作项目的样式
itemStyle() {
return (index) => {
let style = {};
if (this.list[index].color) style.color = this.list[index].color;
if (this.list[index].fontSize) style.fontSize = this.list[index].fontSize + 'rpx';
// 选项被禁用的样式
if (this.list[index].disabled) style.color = '#c0c4cc';
return style;
}
},
uZIndex() {
// 如果用户有传递z-index值,优先使用
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
methods: {
// 点击取消按钮
close() {
// 发送input事件,并不会作用于父组件,而是要设置组件内部通过props传递的value参数
// 这是一个vue发送事件的特殊用法
this.popupClose();
this.$emit('close');
},
// 弹窗关闭
popupClose() {
this.$emit('input', false);
},
// 点击某一个item
itemClick(index) {
// disabled的项禁止点击
if(this.list[index].disabled) return;
this.$emit('click', index);
this.$emit('input', false);
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-tips {
font-size: 26rpx;
text-align: center;
padding: 34rpx 0;
line-height: 1;
color: $u-tips-color;
}
.u-action-sheet-item {
@include vue-flex;;
line-height: 1;
justify-content: center;
align-items: center;
font-size: 32rpx;
padding: 34rpx 0;
flex-direction: column;
}
.u-action-sheet-item__subtext {
font-size: 24rpx;
color: $u-tips-color;
margin-top: 20rpx;
}
.u-gab {
height: 12rpx;
background-color: rgb(234, 234, 236);
}
.u-actionsheet-cancel {
color: $u-main-color;
}
</style>
<template>
<view class="u-alert-tips" v-if="show" :class="[
!show ? 'u-close-alert-tips': '',
type ? 'u-alert-tips--bg--' + type + '-light' : '',
type ? 'u-alert-tips--border--' + type + '-disabled' : '',
]" :style="{
backgroundColor: bgColor,
borderColor: borderColor
}">
<view class="u-icon-wrap">
<u-icon v-if="showIcon" :name="uIcon" :size="description ? 40 : 32" class="u-icon" :color="uIconType" :custom-style="iconStyle"></u-icon>
</view>
<view class="u-alert-content" @tap.stop="click">
<view class="u-alert-title" :style="[uTitleStyle]">
{{title}}
</view>
<view v-if="description" class="u-alert-desc" :style="[descStyle]">
{{description}}
</view>
</view>
<view class="u-icon-wrap">
<u-icon @click="close" v-if="closeAble && !closeText" hoverClass="u-type-error-hover-color" name="close" color="#c0c4cc"
:size="22" class="u-close-icon" :style="{
top: description ? '18rpx' : '24rpx'
}"></u-icon>
</view>
<text v-if="closeAble && closeText" class="u-close-text" :style="{
top: description ? '18rpx' : '24rpx'
}">{{closeText}}</text>
</view>
</template>
<script>
/**
* alertTips 警告提示
* @description 警告提示,展现需要关注的信息
* @tutorial https://uviewui.com/components/alertTips.html
* @property {String} title 显示的标题文字
* @property {String} description 辅助性文字,颜色比title浅一点,字号也小一点,可选
* @property {String} type 关闭按钮(默认为叉号icon图标)
* @property {String} icon 图标名称
* @property {Object} icon-style 图标的样式,对象形式
* @property {Object} title-style 标题的样式,对象形式
* @property {Object} desc-style 描述的样式,对象形式
* @property {String} close-able 用文字替代关闭图标,close-able为true时有效
* @property {Boolean} show-icon 是否显示左边的辅助图标
* @property {Boolean} show 显示或隐藏组件
* @event {Function} click 点击组件时触发
* @event {Function} close 点击关闭按钮时触发
*/
export default {
name: 'u-alert-tips',
props: {
// 显示文字
title: {
type: String,
default: ''
},
// 主题,success/warning/info/error
type: {
type: String,
default: 'warning'
},
// 辅助性文字
description: {
type: String,
default: ''
},
// 是否可关闭
closeAble: {
type: Boolean,
default: false
},
// 关闭按钮自定义文本
closeText: {
type: String,
default: ''
},
// 是否显示图标
showIcon: {
type: Boolean,
default: false
},
// 文字颜色,如果定义了color值,icon会失效
color: {
type: String,
default: ''
},
// 背景颜色
bgColor: {
type: String,
default: ''
},
// 边框颜色
borderColor: {
type: String,
default: ''
},
// 是否显示
show: {
type: Boolean,
default: true
},
// 左边显示的icon
icon: {
type: String,
default: ''
},
// icon的样式
iconStyle: {
type: Object,
default() {
return {}
}
},
// 标题的样式
titleStyle: {
type: Object,
default() {
return {}
}
},
// 描述文字的样式
descStyle: {
type: Object,
default() {
return {}
}
},
},
data() {
return {
}
},
computed: {
uTitleStyle() {
let style = {};
// 如果有描述文字的话,标题进行加粗
style.fontWeight = this.description ? 500 : 'normal';
// 将用户传入样式对象和style合并,传入的优先级比style高,同属性会被覆盖
return this.$u.deepMerge(style, this.titleStyle);
},
uIcon() {
// 如果有设置icon名称就使用,否则根据type主题,推定一个默认的图标
return this.icon ? this.icon : this.$u.type2icon(this.type);
},
uIconType() {
// 如果有设置图标的样式,优先使用,没有的话,则用type的样式
return Object.keys(this.iconStyle).length ? '' : this.type;
}
},
methods: {
// 点击内容
click() {
this.$emit('click');
},
// 点击关闭按钮
close() {
this.$emit('close');
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-alert-tips {
@include vue-flex;
align-items: center;
padding: 16rpx 30rpx;
border-radius: 8rpx;
position: relative;
transition: all 0.3s linear;
border: 1px solid #fff;
&--bg--primary-light {
background-color: $u-type-primary-light;
}
&--bg--info-light {
background-color: $u-type-info-light;
}
&--bg--success-light {
background-color: $u-type-success-light;
}
&--bg--warning-light {
background-color: $u-type-warning-light;
}
&--bg--error-light {
background-color: $u-type-error-light;
}
&--border--primary-disabled {
border-color: $u-type-primary-disabled;
}
&--border--success-disabled {
border-color: $u-type-success-disabled;
}
&--border--error-disabled {
border-color: $u-type-error-disabled;
}
&--border--warning-disabled {
border-color: $u-type-warning-disabled;
}
&--border--info-disabled {
border-color: $u-type-info-disabled;
}
}
.u-close-alert-tips {
opacity: 0;
visibility: hidden;
}
.u-icon {
margin-right: 16rpx;
}
.u-alert-title {
font-size: 28rpx;
color: $u-main-color;
}
.u-alert-desc {
font-size: 26rpx;
text-align: left;
color: $u-content-color;
}
.u-close-icon {
position: absolute;
top: 20rpx;
right: 20rpx;
}
.u-close-hover {
color: red;
}
.u-close-text {
font-size: 24rpx;
color: $u-tips-color;
position: absolute;
top: 20rpx;
right: 20rpx;
line-height: 1;
}
</style>
<template>
<view class="content">
<view class="cropper-wrapper" :style="{ height: cropperOpt.height + 'px' }">
<canvas
class="cropper"
:disable-scroll="true"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
:style="{ width: cropperOpt.width, height: cropperOpt.height, backgroundColor: 'rgba(0, 0, 0, 0.8)' }"
canvas-id="cropper"
id="cropper"
></canvas>
<canvas
class="cropper"
:disable-scroll="true"
:style="{
position: 'fixed',
top: `-${cropperOpt.width * cropperOpt.pixelRatio}px`,
left: `-${cropperOpt.height * cropperOpt.pixelRatio}px`,
width: `${cropperOpt.width * cropperOpt.pixelRatio}px`,
height: `${cropperOpt.height * cropperOpt.pixelRatio}`
}"
canvas-id="targetId"
id="targetId"
></canvas>
</view>
<view class="cropper-buttons safe-area-padding" :style="{ height: bottomNavHeight + 'px' }">
<!-- #ifdef H5 -->
<view class="upload" @tap="uploadTap">选择图片</view>
<!-- #endif -->
<!-- #ifndef H5 -->
<view class="upload" @tap="uploadTap">重新选择</view>
<!-- #endif -->
<view class="getCropperImage" @tap="getCropperImage(false)">确定</view>
</view>
</view>
</template>
<script>
import WeCropper from './weCropper.js';
export default {
props: {
// 裁剪矩形框的样式,其中可包含的属性为lineWidth-边框宽度(单位rpx),color: 边框颜色,
// mask-遮罩颜色,一般设置为一个rgba的透明度,如"rgba(0, 0, 0, 0.35)"
boundStyle: {
type: Object,
default() {
return {
lineWidth: 4,
borderColor: 'rgb(245, 245, 245)',
mask: 'rgba(0, 0, 0, 0.35)'
};
}
}
// // 裁剪框宽度,单位rpx
// rectWidth: {
// type: [String, Number],
// default: 400
// },
// // 裁剪框高度,单位rpx
// rectHeight: {
// type: [String, Number],
// default: 400
// },
// // 输出图片宽度,单位rpx
// destWidth: {
// type: [String, Number],
// default: 400
// },
// // 输出图片高度,单位rpx
// destHeight: {
// type: [String, Number],
// default: 400
// },
// // 输出的图片类型,如果发现裁剪的图片很大,可能是因为设置为了"png",改成"jpg"即可
// fileType: {
// type: String,
// default: 'jpg',
// },
// // 生成的图片质量
// // H5上无效,目前不考虑使用此参数
// quality: {
// type: [Number, String],
// default: 1
// }
},
data() {
return {
// 底部导航的高度
bottomNavHeight: 50,
originWidth: 200,
width: 0,
height: 0,
cropperOpt: {
id: 'cropper',
targetId: 'targetCropper',
pixelRatio: 1,
width: 0,
height: 0,
scale: 2.5,
zoom: 8,
cut: {
x: (this.width - this.originWidth) / 2,
y: (this.height - this.originWidth) / 2,
width: this.originWidth,
height: this.originWidth
},
boundStyle: {
lineWidth: uni.upx2px(this.boundStyle.lineWidth),
mask: this.boundStyle.mask,
color: this.boundStyle.borderColor
}
},
// 裁剪框和输出图片的尺寸,高度默认等于宽度
// 输出图片宽度,单位px
destWidth: 200,
// 裁剪框宽度,单位px
rectWidth: 200,
// 输出的图片类型,如果'png'类型发现裁剪的图片太大,改成"jpg"即可
fileType: 'jpg',
src: '', // 选择的图片路径,用于在点击确定时,判断是否选择了图片
};
},
onLoad(option) {
let rectInfo = uni.getSystemInfoSync();
this.width = rectInfo.windowWidth;
this.height = rectInfo.windowHeight - this.bottomNavHeight;
this.cropperOpt.width = this.width;
this.cropperOpt.height = this.height;
this.cropperOpt.pixelRatio = rectInfo.pixelRatio;
if (option.destWidth) this.destWidth = option.destWidth;
if (option.rectWidth) {
let rectWidth = Number(option.rectWidth);
this.cropperOpt.cut = {
x: (this.width - rectWidth) / 2,
y: (this.height - rectWidth) / 2,
width: rectWidth,
height: rectWidth
};
}
this.rectWidth = option.rectWidth;
if (option.fileType) this.fileType = option.fileType;
// 初始化
this.cropper = new WeCropper(this.cropperOpt)
.on('ready', ctx => {
// wecropper is ready for work!
})
.on('beforeImageLoad', ctx => {
// before picture loaded, i can do something
})
.on('imageLoad', ctx => {
// picture loaded
})
.on('beforeDraw', (ctx, instance) => {
// before canvas draw,i can do something
});
// 设置导航栏样式,以免用户在page.json中没有设置为黑色背景
uni.setNavigationBarColor({
frontColor: '#ffffff',
backgroundColor: '#000000'
});
uni.chooseImage({
count: 1, // 默认9
sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: res => {
this.src = res.tempFilePaths[0];
// 获取裁剪图片资源后,给data添加src属性及其值
this.cropper.pushOrign(this.src);
}
});
},
methods: {
touchStart(e) {
this.cropper.touchStart(e);
},
touchMove(e) {
this.cropper.touchMove(e);
},
touchEnd(e) {
this.cropper.touchEnd(e);
},
getCropperImage(isPre = false) {
if(!this.src) return this.$u.toast('请先选择图片再裁剪');
let cropper_opt = {
destHeight: Number(this.destWidth), // uni.canvasToTempFilePath要求这些参数为数值
destWidth: Number(this.destWidth),
fileType: this.fileType
};
this.cropper.getCropperImage(cropper_opt, (path, err) => {
if (err) {
uni.showModal({
title: '温馨提示',
content: err.message
});
} else {
if (isPre) {
uni.previewImage({
current: '', // 当前显示图片的 http 链接
urls: [path] // 需要预览的图片 http 链接列表
});
} else {
uni.$emit('uAvatarCropper', path);
this.$u.route({
type: 'back'
});
}
}
});
},
uploadTap() {
const self = this;
uni.chooseImage({
count: 1, // 默认9
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: (res) => {
self.src = res.tempFilePaths[0];
// 获取裁剪图片资源后,给data添加src属性及其值
self.cropper.pushOrign(this.src);
}
});
}
}
};
</script>
<style scoped lang="scss">
@import '../../libs/css/style.components.scss';
.content {
background: rgba(255, 255, 255, 1);
}
.cropper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 11;
}
.cropper-buttons {
background-color: #000000;
color: #eee;
}
.cropper-wrapper {
position: relative;
@include vue-flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
background-color: #000;
}
.cropper-buttons {
width: 100vw;
@include vue-flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
position: fixed;
bottom: 0;
left: 0;
font-size: 28rpx;
}
.cropper-buttons .upload,
.cropper-buttons .getCropperImage {
width: 50%;
text-align: center;
}
.cropper-buttons .upload {
text-align: left;
padding-left: 50rpx;
}
.cropper-buttons .getCropperImage {
text-align: right;
padding-right: 50rpx;
}
</style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<template>
<view class="u-cell-box">
<view class="u-cell-title" v-if="title" :style="[titleStyle]">
{{title}}
</view>
<view class="u-cell-item-box" :class="{'u-border-bottom u-border-top': border}">
<slot />
</view>
</view>
</template>
<script>
/**
* cellGroup 单元格父组件Group
* @description cell单元格一般用于一组列表的情况,比如个人中心页,设置页等。搭配u-cell-item
* @tutorial https://www.uviewui.com/components/cell.html
* @property {String} title 分组标题
* @property {Boolean} border 是否显示外边框(默认true)
* @property {Object} title-style 分组标题的的样式,对象形式,如{'font-size': '24rpx'} 或 {'fontSize': '24rpx'}
* @example <u-cell-group title="设置喜好">
*/
export default {
name: "u-cell-group",
props: {
// 分组标题
title: {
type: String,
default: ''
},
// 是否显示分组list上下边框
border: {
type: Boolean,
default: true
},
// 分组标题的样式,对象形式,注意驼峰属性写法
// 类似 {'font-size': '24rpx'} 和 {'fontSize': '24rpx'}
titleStyle: {
type: Object,
default () {
return {};
}
}
},
data() {
return {
index: 0,
}
},
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/style.components.scss";
.u-cell-box {
width: 100%;
}
.u-cell-title {
padding: 30rpx 32rpx 10rpx 32rpx;
font-size: 30rpx;
text-align: left;
color: $u-tips-color;
}
.u-cell-item-box {
background-color: #FFFFFF;
flex-direction: row;
}
</style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<template>
<u-modal v-model="show" :show-cancel-button="true" confirm-text="升级" title="发现新版本" @cancel="cancel" @confirm="confirm">
<view class="u-update-content">
<rich-text :nodes="content"></rich-text>
</view>
</u-modal>
</template>
<script>
export default {
data() {
return {
show: false,
content: `
1. 修复badge组件的size参数无效问题<br>
2. 新增Modal模态框组件<br>
3. 新增压窗屏组件,可以在APP上以弹窗的形式遮盖导航栏和底部tabbar<br>
4. 修复键盘组件在微信小程序上遮罩无效的问题
`,
}
},
onReady() {
this.show = true;
},
methods: {
cancel() {
this.closeModal();
},
confirm() {
this.closeModal();
},
closeModal() {
uni.navigateBack();
}
}
}
</script>
<style scoped lang="scss">
@import "../../libs/css/style.components.scss";
.u-full-content {
background-color: #00C777;
}
.u-update-content {
font-size: 26rpx;
color: $u-content-color;
line-height: 1.7;
padding: 30rpx;
}
</style>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment