创建版本

This commit is contained in:
2021-02-22 12:17:00 +08:00
commit af555f49c3
2332 changed files with 369202 additions and 0 deletions
+30
View File
@@ -0,0 +1,30 @@
<script>
export default {
onLaunch: function() {
console.log('App Launch');
/*
setTimeout(() => {
uni.setTabBarBadge({
index: 1,
text: '9'
});
uni.showTabBarRedDot({
index: 3
});
}, 1000);
*/
},
onShow: function() {
console.log('App Show');
},
onHide: function() {
console.log('App Hide');
}
};
</script>
<style>
@import './static/uni.css';
/*每个页面公共css */
@import './static/iconfont/iconfont.css';
</style>
+276
View File
@@ -0,0 +1,276 @@
let baseURL = "";
if (process.env.NODE_ENV === 'development') {
// 开发环境
baseURL = 'http://wedev2.gdoooa.com';
} else {
// 生产环境
baseURL = 'http://wedev2.gdoooa.com';
}
console.log(baseURL);
//post 封装
function post(url, data) {
var promise = new Promise((resolve, reject) => {
var me = this;
var params = data;
uni.showLoading({
mask: true,
title: '数据处理中...'
});
uni.request({
url: baseURL + '/' + url,
data: params,
method: 'POST',
header: {
//'content-type': 'application/json',
"accept": "application/json",
'content-type': 'application/x-www-form-urlencoded',
'x-auth-token': uni.getStorageSync('token')
},
success: function(res) {
resolve(res.data);
},
error: function(error) {
reject(error.data);
},
complete: function() {
uni.hideLoading();
return;
}
})
})
return promise;
}
//get 封装
function get(url, data) {
var promise = new Promise((resolve, reject) => {
var me = this;
var params = data;
uni.request({
url: baseURL + '/' + url,
data: params,
method: 'GET',
header: {
'content-type': 'application/json',
'x-auth-token': uni.getStorageSync('token')
},
success: function(res) {
resolve(res.data);
},
error: function(error) {
reject(error.data);
},
complete: function() {
uni.hideLoading();
return;
}
})
})
return promise;
}
function authorize() {
var token = uni.getStorageSync('token');
if (token) {
uni.switchTab({
url: '/pages/tabbar/notice'
});
} else {
if (isWeiXin()) {
post('wap/wechat/config').then(res => {
if (res.status) {
wxAuthorize(res.data);
} else {
uni.showModal({
title: '错误',
content: res.data
});
}
}).catch(res => {
});
} else {
uni.reLaunch({
url:'/pages/login/wap'
});
}
}
}
function wxAuthorize(config) {
var params = getParams();
if (params.code) {
// 去掉url的参数
var host = location.href.split('?')[0];
history.pushState({}, 0, host);
post('wap/wechat/authorize', {code: params.code}).then(res => {
uni.setStorageSync('openid', res.data.openid);
if (res.status) {
uni.setStorageSync('access', res.data.access);
uni.setStorageSync('token', res.data.token);
uni.setStorageSync('user', res.data.user);
uni.reLaunch({
url: '/pages/tabbar/notice'
});
} else {
uni.showModal({
title: '错误',
content: res.data
});
uni.reLaunch({
url:'/pages/login/wechat'
});
}
}).catch(res => {
uni.showModal({
title: '错误',
content: res.data
});
});
} else {
let appid = config.appid;
let uri = encodeURIComponent(window.location.href);
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${uri}&response_type=code&scope=snsapi_base&state=gdoooa#wechat_redirect`;
}
}
function logout() {
var me = this;
if (isWeiXin()) {
var openid = uni.getStorageSync('openid');
if (openid == '') {
uni.showToast({
title: 'Openid不能为空。'
});
return;
}
uni.showModal({
title: '警告',
content: '确定要解绑帐号吗?',
success: function (btn) {
if (btn.confirm) {
post('wap/wechat/logout', {openid: openid}).then(res => {
if (res.status) {
uni.removeStorageSync('access');
uni.removeStorageSync('token');
uni.removeStorageSync('user');
uni.reLaunch({
url:'/pages/index'
});
}
});
} else if (btn.cancel) {
}
}
});
} else {
uni.showModal({
title: '警告',
content: '确定要注销帐号吗?',
success: function (btn) {
if (btn.confirm) {
post('wap/auth/logout').then(res => {
uni.removeStorageSync('access');
uni.removeStorageSync('token');
uni.removeStorageSync('user');
uni.reLaunch({
url:'/pages/index'
});
});
} else if (btn.cancel) {
}
}
});
}
}
function isWeiXin() {
var ua = window.navigator.userAgent.toLowerCase();
if (ua.match(/MicroMessenger/i) == 'micromessenger') {
return true; // 是微信端
} else {
return false;
}
}
function getParams() {
var query = window.location.search.substring(1);
var vars = query.split("&");
var ret = {};
for (var i = 0; i < vars.length;i++) {
var pair = vars[i].split("=");
ret[pair[0]] = pair[1];
}
return ret;
}
/** 压缩图片
* @param {Object} file 上传对象files[0]
* @param {Object} options 压缩设置对象
* @param {Function} callback 回调函数
* @result {Object} 返回blob文件对象
* */
var compressImg = function(file, options, callback) {
var self = this;
var imgname = file.name;
var imgtype = (imgname.substring(imgname.lastIndexOf('.') + 1)).toLowerCase();
if(imgtype == 'jpg' || imgtype == 'jpeg') {
imgtype = 'image/jpeg';
} else {
imgtype = 'image/png';
}
// 用FileReader读取文件
var reader = new FileReader();
// 将图片读取为base64
reader.readAsDataURL(file);
reader.onload = function(evt) {
var base64 = evt.target.result;
// 创建图片对象
var img = new Image();
// 用图片对象加载读入的base64
img.src = base64;
img.onload = function () {
var that = this,
canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
canvas.setAttribute('width', that.width);
canvas.setAttribute('height', that.height);
// 将图片画入canvas
ctx.drawImage(that, 0, 0, that.width, that.height);
// 压缩到指定体积以下(M
if (options.size) {
var scale = 0.9;
(function f(scale) {
if (base64.length / 1024 / 1024 > options.size && scale > 0) {
base64 = canvas.toDataURL(imgtype, scale);
scale = scale - 0.1;
f(scale);
} else {
callback(base64);
}
})(scale);
} else if(options.scale) {
// 按比率压缩
base64 = canvas.toDataURL(imgtype, options.scale);
callback(base64);
}
}
}
};
module.exports = {
compressImg,
post,
get,
getParams,
baseURL,
authorize,
logout,
isWeiXin
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

+228
View File
@@ -0,0 +1,228 @@
<template>
<view class="w-100">
<view class="w-100 flex_wrap">
<view class="imgs-view" v-for="(v,i) in imgArray" :key="i">
<image @click="preview(v,i)" :src="v"></image>
<view class="del-btn" @click="delImg(i)">
<image src="@/components/my-components/imgs/delete.png"></image>
</view>
</view>
<view v-if="imgArray.length < imgCount" class="upload-img-view flex_xy_center" @click="upPhoto">
<image src="@/components/my-components/imgs/jia.png"></image>
</view>
</view>
<view class="tip">* 最多上传{{imgCount}}张图片(<label> {{imgArray.length}} </label>/{{imgCount}})</view>
</view>
</template>
<script>
export default {
name: 'imgUpload',
props: {
imgArr: { // 图片数组
type: [Array],
},
uploadImgCount: { // 一次上传图片数
type: String,
default: '3'
},
imgCount: { // 可上传图片总数
type: String,
default: '3'
},
imgSize: { //图片大小 单位M
type: Number,
default: 10
},
imgType: {
type: [Array],
default: function() {
return ['jpeg', 'png', 'jpg']
}
}
},
created() {
this.imgArray = this.imgArr;
},
data() {
return {
imgArray: []
}
},
watch: {},
methods: {
upPhoto() {
let me = this;
if (Number(me.imgCount - me.imgArray.length) < Number(me.uploadImgCount)) {
me.uploadImgCount = Number(me.imgCount - me.imgArray.length);
}
uni.chooseImage({
count: Number(me.uploadImgCount),
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['camera'], // 从相册选择
success: function(res) {
if (res) {
if (res.tempFiles instanceof Array && res.tempFiles) {
for (let item of res.tempFiles) {
if (item.size > (me.imgSize * 1024 * 1024)) {
uni.showToast({
title: `图片不能大于${me.imgSize}M`,
icon: 'none'
})
return false;
}
let r = me.imgType.some(v => {
let type = item.type.split('/');
if (type.length)
return (v === type[1]);
});
if (!r) {
uni.showToast({
title: `只允许上传${me.imgType}的类型`,
icon: 'none'
})
return false;
}
}
}
me.imgArray = [...me.imgArray, ...res.tempFilePaths];
}
}
});
},
preview(url, index) {
// 预览图片
uni.previewImage({
urls: [url]
});
},
delImg(i) {
const me = this;
uni.showModal({
title: '提示',
content: '是否删除这张照片?',
success: function(res) {
if (res.confirm) {
me.imgArray.splice(i, 1);
} else if (res.cancel) {}
}
});
},
async upload(callback) {
const me = this;
if (me.imgArray) {
let successNum = 0;
let urlArr = [];
for (let item of me.imgArray) {
await me.uploadImg(item, res => {
if (res.code == 200) { //接口回调值 *注意修改为自己接口对应的!!!
successNum++;
if (res.data.code == 200) { //接口回调值 *注意修改为自己接口对应的!!!
urlArr.push(res.data.data);
}
} else {
urlArr.push(res);
}
if (urlArr.length == me.imgArray.length) {
callback(me.result(urlArr, successNum));
}
});
}
}
},
result(urlArr, successNum) {
let result = {
urlArray: urlArr,
success: successNum
}
return result;
},
uploadImg(item, callback) {
const me = this;
uni.uploadFile({
url: $config.SERVER_URL + 'api/sys/user/modify/uploadPic', // 自行修改各自的对应的接口
filePath: item,
name: 'file',
success: (uploadFileRes) => {
if (uploadFileRes) {
let res = JSON.parse(uploadFileRes.data);
callback(res);
}
}
});
}
}
}
</script>
<style scoped>
.w-100 {
width: 100%;
}
.flex {
/* 转为弹性盒模型*/
display: flex;
}
.flex_bet {
/* 两端左右*/
display: flex;
justify-content: space-between;
}
.flex_wrap {
/* 转为弹性盒模型并自动换行*/
display: flex;
flex-wrap: wrap;
}
.upload-img-view {
height: 200upx;
width: 31.5%;
border-radius: 0;
border: 1upx solid #F1F1F1;
display: flex;
justify-content: center;
align-items: center;
}
.upload-img-view>image {
width: 60upx;
height: 60upx;
}
.imgs-view {
height: 200upx;
width: 32%;
border-radius: 0;
margin-right: 12upx;
margin-bottom: 12upx;
border: 1upx solid #F1F1F1;
box-sizing: border-box;
position: relative;
}
.imgs-view:last-child {
margin-right: 0;
}
.imgs-view>image {
width: 100%;
height: 100%;
border-radius: 0;
}
.tip {
font-size: 24upx;
color: #999;
margin-top: 12upx;
}
.tip > label {
color: #009100;
}
.del-btn {
position: absolute;
top: 2rpx;
right: 2rpx;
width: 32upx;
height: 32upx;
z-index: 999;
}
.del-btn>image {
width: 100%;
height: 100%;
display: flex;
}
</style>
+151
View File
@@ -0,0 +1,151 @@
<template>
<text v-if="text" :class="inverted ? 'uni-badge--' + type + ' uni-badge--' + size + ' uni-badge--' + type + '-inverted' : 'uni-badge--' + type + ' uni-badge--' + size"
:style="badgeStyle" class="uni-badge" @click="onClick()">{{ text }}</text>
</template>
<script>
/**
* Badge 数字角标
* @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
* @tutorial https://ext.dcloud.net.cn/plugin?id=21
* @property {String} text 角标内容
* @property {String} type = [default|primary|success|warning|error] 颜色类型
* @value default 灰色
* @value primary 蓝色
* @value success 绿色
* @value warning 黄色
* @value error 红色
* @property {String} size = [normal|small] Badge 大小
* @value normal 一般尺寸
* @value small 小尺寸
* @property {String} inverted = [true|false] 是否无需背景颜色
* @event {Function} click 点击 Badge 触发事件
* @example <uni-badge text="1"></uni-badge>
*/
export default {
name: 'UniBadge',
props: {
type: {
type: String,
default: 'default'
},
inverted: {
type: Boolean,
default: false
},
text: {
type: [String, Number],
default: ''
},
size: {
type: String,
default: 'normal'
}
},
data() {
return {
badgeStyle: ''
};
},
watch: {
text() {
this.setStyle()
}
},
mounted() {
this.setStyle()
},
methods: {
setStyle() {
this.badgeStyle = `width: ${String(this.text).length * 8 + 12}px`
},
onClick() {
this.$emit('click');
}
}
};
</script>
<style lang="scss" scoped>
$bage-size: 12px;
$bage-small: scale(0.8);
$bage-height: 20px;
.uni-badge {
/* #ifndef APP-PLUS */
display: flex;
/* #endif */
justify-content: center;
flex-direction: row;
height: $bage-height;
line-height: $bage-height;
color: $uni-text-color;
border-radius: 100px;
background-color: $uni-bg-color-hover;
background-color: transparent;
text-align: center;
font-family: 'Helvetica Neue', Helvetica, sans-serif;
font-size: $bage-size;
padding: 0px 6px;
}
.uni-badge--inverted {
padding: 0 5px 0 0;
color: $uni-bg-color-hover;
}
.uni-badge--default {
color: $uni-text-color;
background-color: $uni-bg-color-hover;
}
.uni-badge--default-inverted {
color: $uni-text-color-grey;
background-color: transparent;
}
.uni-badge--primary {
color: $uni-text-color-inverse;
background-color: $uni-color-primary;
}
.uni-badge--primary-inverted {
color: $uni-color-primary;
background-color: transparent;
}
.uni-badge--success {
color: $uni-text-color-inverse;
background-color: $uni-color-success;
}
.uni-badge--success-inverted {
color: $uni-color-success;
background-color: transparent;
}
.uni-badge--warning {
color: $uni-text-color-inverse;
background-color: $uni-color-warning;
}
.uni-badge--warning-inverted {
color: $uni-color-warning;
background-color: transparent;
}
.uni-badge--error {
color: $uni-text-color-inverse;
background-color: $uni-color-error;
}
.uni-badge--error-inverted {
color: $uni-color-error;
background-color: transparent;
}
.uni-badge--small {
transform: $bage-small;
transform-origin: center center;
}
</style>
+428
View File
@@ -0,0 +1,428 @@
<template>
<view>
<view v-if="popMenu && (leftBottom||rightBottom||leftTop||rightTop)" :class="{
'uni-fab--leftBottom': leftBottom,
'uni-fab--rightBottom': rightBottom,
'uni-fab--leftTop': leftTop,
'uni-fab--rightTop': rightTop
}" class="uni-fab">
<view :class="{
'uni-fab__content--left': horizontal === 'left',
'uni-fab__content--right': horizontal === 'right',
'uni-fab__content--flexDirection': direction === 'vertical',
'uni-fab__content--flexDirectionStart': flexDirectionStart,
'uni-fab__content--flexDirectionEnd': flexDirectionEnd,
'uni-fab__content--other-platform': !isAndroidNvue
}" :style="{ width: boxWidth, height: boxHeight, backgroundColor: styles.backgroundColor }" class="uni-fab__content" elevation="5">
<view v-if="flexDirectionStart || horizontalLeft" class="uni-fab__item uni-fab__item--first" />
<view v-for="(item, index) in content" :key="index" :class="{ 'uni-fab__item--active': isShow }" class="uni-fab__item" @click="_onItemClick(index, item)">
<image :src="item.active ? item.selectedIconPath : item.iconPath" class="uni-fab__item-image" mode="widthFix" />
<text class="uni-fab__item-text" :style="{ color: item.active ? styles.selectedColor : styles.color }">{{ item.text }}</text>
</view>
<view v-if="flexDirectionEnd || horizontalRight" class="uni-fab__item uni-fab__item--first" />
</view>
</view>
<view :class="{
'uni-fab__circle--leftBottom': leftBottom,
'uni-fab__circle--rightBottom': rightBottom,
'uni-fab__circle--leftTop': leftTop,
'uni-fab__circle--rightTop': rightTop,
'uni-fab__content--other-platform': !isAndroidNvue
}" class="uni-fab__circle uni-fab__plus" :style="{ 'background-color': styles.buttonColor }" @click="_onClick">
<view class="fab-circle-v" :class="{'uni-fab__plus--active': isShow}"></view>
<view class="fab-circle-h" :class="{'uni-fab__plus--active': isShow}"></view>
</view>
</view>
</template>
<script>
let platform = 'other'
// #ifdef APP-NVUE
platform = uni.getSystemInfoSync().platform
// #endif
/**
* Fab 悬浮按钮
* @description 点击可展开一个图形按钮菜单
* @tutorial https://ext.dcloud.net.cn/plugin?id=144
* @property {Object} pattern 可选样式配置项
* @property {Object} horizontal = [left | right] 水平对齐方式
* @value left 左对齐
* @value right 右对齐
* @property {Object} vertical = [bottom | top] 垂直对齐方式
* @value bottom 下对齐
* @value top 上对齐
* @property {Object} direction = [horizontal | vertical] 展开菜单显示方式
* @value horizontal 水平显示
* @value vertical 垂直显示
* @property {Array} content 展开菜单内容配置项
* @property {Boolean} popMenu 是否使用弹出菜单
* @event {Function} trigger 展开菜单点击事件,返回点击信息
* @event {Function} fabClick 悬浮按钮点击事件
*/
export default {
name: 'UniFab',
props: {
pattern: {
type: Object,
default () {
return {}
}
},
horizontal: {
type: String,
default: 'left'
},
vertical: {
type: String,
default: 'bottom'
},
direction: {
type: String,
default: 'horizontal'
},
content: {
type: Array,
default () {
return []
}
},
show: {
type: Boolean,
default: false
},
popMenu: {
type: Boolean,
default: true
}
},
data() {
return {
fabShow: false,
isShow: false,
isAndroidNvue: platform === 'android',
styles: {
color: '#3c3e49',
selectedColor: '#007AFF',
backgroundColor: '#fff',
buttonColor: '#3c3e49'
}
}
},
computed: {
contentWidth(e) {
return (this.content.length + 1) * 55 + 10 + 'px'
},
contentWidthMin() {
return 55 + 'px'
},
// 动态计算宽度
boxWidth() {
return this.getPosition(3, 'horizontal')
},
// 动态计算高度
boxHeight() {
return this.getPosition(3, 'vertical')
},
// 计算左下位置
leftBottom() {
return this.getPosition(0, 'left', 'bottom')
},
// 计算右下位置
rightBottom() {
return this.getPosition(0, 'right', 'bottom')
},
// 计算左上位置
leftTop() {
return this.getPosition(0, 'left', 'top')
},
rightTop() {
return this.getPosition(0, 'right', 'top')
},
flexDirectionStart() {
return this.getPosition(1, 'vertical', 'top')
},
flexDirectionEnd() {
return this.getPosition(1, 'vertical', 'bottom')
},
horizontalLeft() {
return this.getPosition(2, 'horizontal', 'left')
},
horizontalRight() {
return this.getPosition(2, 'horizontal', 'right')
}
},
watch: {
pattern(newValue, oldValue) {
//console.log(JSON.stringify(newValue))
this.styles = Object.assign({}, this.styles, newValue)
}
},
created() {
this.isShow = this.show
if (this.top === 0) {
this.fabShow = true
}
// 初始化样式
this.styles = Object.assign({}, this.styles, this.pattern)
},
methods: {
_onClick() {
this.$emit('fabClick')
if (!this.popMenu) {
return
}
this.isShow = !this.isShow
},
open() {
this.isShow = true
},
close() {
this.isShow = false
},
/**
* 按钮点击事件
*/
_onItemClick(index, item) {
this.$emit('trigger', {
index,
item
})
},
/**
* 获取 位置信息
*/
getPosition(types, paramA, paramB) {
if (types === 0) {
return this.horizontal === paramA && this.vertical === paramB
} else if (types === 1) {
return this.direction === paramA && this.vertical === paramB
} else if (types === 2) {
return this.direction === paramA && this.horizontal === paramB
} else {
return this.isShow && this.direction === paramA ? this.contentWidth : this.contentWidthMin
}
}
}
}
</script>
<style scoped>
.uni-fab {
position: fixed;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
z-index: 10;
}
.uni-fab--active {
opacity: 1;
}
.uni-fab--leftBottom {
left: 5px;
bottom: 20px;
/* #ifdef H5 */
bottom: calc(20px + var(--window-bottom));
/* #endif */
padding: 10px;
}
.uni-fab--leftTop {
left: 5px;
top: 30px;
/* #ifdef H5 */
top: calc(30px + var(--window-top));
/* #endif */
padding: 10px;
}
.uni-fab--rightBottom {
right: 5px;
bottom: 20px;
/* #ifdef H5 */
bottom: calc(20px + var(--window-bottom));
/* #endif */
padding: 10px;
}
.uni-fab--rightTop {
right: 5px;
top: 30px;
/* #ifdef H5 */
top: calc(30px + var(--window-top));
/* #endif */
padding: 10px;
}
.uni-fab__circle {
position: fixed;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
width: 55px;
height: 55px;
background-color: #3c3e49;
border-radius: 55px;
z-index: 11;
}
.uni-fab__circle--leftBottom {
left: 15px;
bottom: 30px;
/* #ifdef H5 */
bottom: calc(30px + var(--window-bottom));
/* #endif */
}
.uni-fab__circle--leftTop {
left: 15px;
top: 40px;
/* #ifdef H5 */
top: calc(40px + var(--window-top));
/* #endif */
}
.uni-fab__circle--rightBottom {
right: 15px;
bottom: 30px;
/* #ifdef H5 */
bottom: calc(30px + var(--window-bottom));
/* #endif */
}
.uni-fab__circle--rightTop {
right: 15px;
top: 40px;
/* #ifdef H5 */
top: calc(40px + var(--window-top));
/* #endif */
}
.uni-fab__circle--left {
left: 0;
}
.uni-fab__circle--right {
right: 0;
}
.uni-fab__circle--top {
top: 0;
}
.uni-fab__circle--bottom {
bottom: 0;
}
.uni-fab__plus {
font-weight: bold;
}
.fab-circle-v {
position: absolute;
width: 3px;
height: 31px;
left: 26px;
top: 12px;
background-color: white;
transform: rotate(0deg);
transition: transform 0.3s;
}
.fab-circle-h {
position: absolute;
width: 31px;
height: 3px;
left: 12px;
top: 26px;
background-color: white;
transform: rotate(0deg);
transition: transform 0.3s;
}
.uni-fab__plus--active {
transform: rotate(135deg);
}
.uni-fab__content {
/* #ifndef APP-NVUE */
box-sizing: border-box;
display: flex;
/* #endif */
flex-direction: row;
border-radius: 55px;
overflow: hidden;
transition-property: width, height;
transition-duration: 0.2s;
width: 55px;
border-color: #DDDDDD;
border-width: 1rpx;
border-style: solid;
}
.uni-fab__content--other-platform {
border-width: 0px;
box-shadow: 0 0 5px 2px rgba(0, 0, 0, 0.2);
}
.uni-fab__content--left {
justify-content: flex-start;
}
.uni-fab__content--right {
justify-content: flex-end;
}
.uni-fab__content--flexDirection {
flex-direction: column;
justify-content: flex-end;
}
.uni-fab__content--flexDirectionStart {
flex-direction: column;
justify-content: flex-start;
}
.uni-fab__content--flexDirectionEnd {
flex-direction: column;
justify-content: flex-end;
}
.uni-fab__item {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
width: 55px;
height: 55px;
opacity: 0;
transition: opacity 0.2s;
}
.uni-fab__item--active {
opacity: 1;
}
.uni-fab__item-image {
width: 25px;
height: 25px;
margin-bottom: 3px;
}
.uni-fab__item-text {
color: #FFFFFF;
font-size: 12px;
}
.uni-fab__item--first {
width: 55px;
}
</style>
@@ -0,0 +1,108 @@
<template>
<view v-if="width" :style="'width:'+width+';'+(square?'height:'+width:'')" class="uni-grid-item">
<view :class="{ 'uni-grid-item--border': showBorder, 'uni-grid-item--border-top': showBorder && index < column, 'uni-highlight': highlight }"
:style="{ 'border-right-color': borderColor ,'border-bottom-color': borderColor ,'border-top-color': borderColor }"
class="uni-grid-item__box" @click="_onClick">
<slot />
</view>
</view>
</template>
<script>
export default {
name: 'UniGridItem',
inject: ['grid'],
props: {
index:{
type: Number,
default: 0
}
},
data() {
return {
column: 0,
showBorder: true,
square: true,
highlight: true,
left: 0,
top: 0,
openNum: 2,
width: 0,
borderColor: '#e5e5e5'
}
},
created() {
this.column = this.grid.column
this.showBorder = this.grid.showBorder
this.square = this.grid.square
this.highlight = this.grid.highlight
this.top = this.hor === 0 ? this.grid.hor : this.hor
this.left = this.ver === 0 ? this.grid.ver : this.ver
this.borderColor = this.grid.borderColor
this.grid.children.push(this)
// this.grid.init()
this.width = this.grid.width
},
beforeDestroy() {
this.grid.children.forEach((item, index) => {
if (item === this) {
this.grid.children.splice(index, 1)
}
})
},
methods: {
_onClick() {
this.grid.change({
detail: {
index: this.index
}
})
}
}
}
</script>
<style lang="scss" scoped>
.uni-grid-item {
/* #ifndef APP-NVUE */
height: 100%;
display: flex;
/* #endif */
}
.uni-grid-item__box {
/* #ifndef APP-NVUE */
display: flex;
width: 100%;
/* #endif */
position: relative;
flex: 1;
flex-direction: column;
// justify-content: center;
// align-items: center;
}
.uni-grid-item--border {
position: relative;
border-bottom-color: $uni-border-color;
border-bottom-style: solid;
border-bottom-width: 1px;
border-right-color: $uni-border-color;
border-right-style: solid;
border-right-width: 1px;
}
.uni-grid-item--border-top {
border-top-color: $uni-border-color;
border-top-style: solid;
border-top-width: 1px;
/* #ifndef APP-NVUE */
height: 100%;
box-sizing: border-box;
/* #endif */
}
.uni-highlight:active {
background-color: $uni-bg-color-hover;
}
</style>
+120
View File
@@ -0,0 +1,120 @@
<template>
<view class="uni-grid-wrap">
<view :id="elId" ref="uni-grid" class="uni-grid" :class="{ 'uni-grid--border': showBorder }" :style="{ 'border-left-style':'solid','border-left-color':borderColor, 'border-left-width':showBorder?'1px':0 }">
<slot />
</view>
</view>
</template>
<script>
// #ifdef APP-NVUE
const dom = uni.requireNativePlugin('dom');
// #endif
export default {
name: 'UniGrid',
props: {
// 每列显示个数
column: {
type: Number,
default: 3
},
// 是否显示边框
showBorder: {
type: Boolean,
default: true
},
// 边框颜色
borderColor: {
type: String,
default: '#e5e5e5'
},
// 是否正方形显示,默认为 true
square: {
type: Boolean,
default: true
},
highlight: {
type: Boolean,
default: true
}
},
provide() {
return {
grid: this
}
},
data() {
const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
return {
elId,
width: 0
}
},
created() {
this.children = []
},
mounted() {
this.init()
},
methods: {
init() {
setTimeout(() => {
this._getSize((width) => {
this.children.forEach((item, index) => {
item.width = width
})
})
}, 50)
},
change(e) {
this.$emit('change', e)
},
_getSize(fn) {
// #ifndef APP-NVUE
uni.createSelectorQuery()
.in(this)
.select(`#${this.elId}`)
.boundingClientRect()
.exec(ret => {
this.width = parseInt((ret[0].width-1) / this.column) + 'px'
fn(this.width)
})
// #endif
// #ifdef APP-NVUE
dom.getComponentRect(this.$refs['uni-grid'], (ret) => {
this.width = parseInt((ret.size.width-1) / this.column) + 'px'
fn(this.width)
})
// #endif
}
}
}
</script>
<style lang="scss" scoped>
.uni-grid-wrap {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
flex-direction: column;
/* #ifdef H5 */
width: 100%;
/* #endif */
}
.uni-grid {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
// flex: 1;
flex-direction: row;
flex-wrap: wrap;
}
.uni-grid--border {
border-left-color: $uni-border-color;
border-left-style: solid;
border-left-width: 1px;
}
</style>
+96
View File
@@ -0,0 +1,96 @@
export default {
'contact': '\ue100',
'person': '\ue101',
'personadd': '\ue102',
'contact-filled': '\ue130',
'person-filled': '\ue131',
'personadd-filled': '\ue132',
'phone': '\ue200',
'email': '\ue201',
'chatbubble': '\ue202',
'chatboxes': '\ue203',
'phone-filled': '\ue230',
'email-filled': '\ue231',
'chatbubble-filled': '\ue232',
'chatboxes-filled': '\ue233',
'weibo': '\ue260',
'weixin': '\ue261',
'pengyouquan': '\ue262',
'chat': '\ue263',
'qq': '\ue264',
'videocam': '\ue300',
'camera': '\ue301',
'mic': '\ue302',
'location': '\ue303',
'mic-filled': '\ue332',
'speech': '\ue332',
'location-filled': '\ue333',
'micoff': '\ue360',
'image': '\ue363',
'map': '\ue364',
'compose': '\ue400',
'trash': '\ue401',
'upload': '\ue402',
'download': '\ue403',
'close': '\ue404',
'redo': '\ue405',
'undo': '\ue406',
'refresh': '\ue407',
'star': '\ue408',
'plus': '\ue409',
'minus': '\ue410',
'circle': '\ue411',
'checkbox': '\ue411',
'close-filled': '\ue434',
'clear': '\ue434',
'refresh-filled': '\ue437',
'star-filled': '\ue438',
'plus-filled': '\ue439',
'minus-filled': '\ue440',
'circle-filled': '\ue441',
'checkbox-filled': '\ue442',
'closeempty': '\ue460',
'refreshempty': '\ue461',
'reload': '\ue462',
'starhalf': '\ue463',
'spinner': '\ue464',
'spinner-cycle': '\ue465',
'search': '\ue466',
'plusempty': '\ue468',
'forward': '\ue470',
'back': '\ue471',
'left-nav': '\ue471',
'checkmarkempty': '\ue472',
'home': '\ue500',
'navigate': '\ue501',
'gear': '\ue502',
'paperplane': '\ue503',
'info': '\ue504',
'help': '\ue505',
'locked': '\ue506',
'more': '\ue507',
'flag': '\ue508',
'home-filled': '\ue530',
'gear-filled': '\ue532',
'info-filled': '\ue534',
'help-filled': '\ue535',
'more-filled': '\ue537',
'settings': '\ue560',
'list': '\ue562',
'bars': '\ue563',
'loop': '\ue565',
'paperclip': '\ue567',
'eye': '\ue568',
'arrowup': '\ue580',
'arrowdown': '\ue581',
'arrowleft': '\ue582',
'arrowright': '\ue583',
'arrowthinup': '\ue584',
'arrowthindown': '\ue585',
'arrowthinleft': '\ue586',
'arrowthinright': '\ue587',
'pulldown': '\ue588',
'closefill': '\ue589',
'sound': '\ue590',
'scan': '\ue612'
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,272 @@
<template>
<!-- #ifdef APP-NVUE -->
<cell>
<!-- #endif -->
<view :class="disabled ? 'uni-list-item--disabled' : ''" :hover-class="disabled || showSwitch ? '' : 'uni-list-item--hover'"
class="uni-list-item" @click="onClick">
<view class="uni-list-item__container" :class="{'uni-list-item--first':isFirstChild}">
<view v-if="thumb" class="uni-list-item__icon">
<image :src="thumb" class="uni-list-item__icon-img" />
</view>
<view v-else-if="showExtraIcon" class="uni-list-item__icon">
<uni-icons :color="extraIcon.color" :size="extraIcon.size" :type="extraIcon.type" class="uni-icon-wrapper" />
</view>
<view class="uni-list-item__content">
<slot />
<text class="uni-list-item__content-title">{{ title }}</text>
<text v-if="note" class="uni-list-item__content-note">{{ note }}</text>
</view>
<view class="uni-list-item__extra">
<text v-if="rightText" class="uni-list-item__extra-text">{{rightText}}</text>
<uni-badge v-if="showBadge" :type="badgeType" :text="badgeText" />
<switch v-if="showSwitch" :disabled="disabled" :checked="switchChecked" @change="onSwitchChange" />
<slot name="right"></slot>
<uni-icons v-if="showArrow" :size="20" class="uni-icon-wrapper" color="#bbb" type="arrowright" />
</view>
</view>
</view>
<!-- #ifdef APP-NVUE -->
</cell>
<!-- #endif -->
</template>
<script>
import uniIcons from '../uni-icons/uni-icons.vue'
import uniBadge from '../uni-badge/uni-badge.vue'
/**
* ListItem 列表子组件
* @description 列表子组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
* @property {String} title 标题
* @property {String} note 描述
* @property {String} thumb 左侧缩略图,若thumb有值,则不会显示扩展图标
* @property {String} badgeText 数字角标内容
* @property {String} badgeType 数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21)
* @property {String} rightText 右侧文字内容
* @property {Boolean} disabled = [true|false]是否禁用
* @property {Boolean} showArrow = [true|false] 是否显示箭头图标
* @property {Boolean} showBadge = [true|false] 是否显示数字角标
* @property {Boolean} showSwitch = [true|false] 是否显示Switch
* @property {Boolean} switchChecked = [true|false] Switch是否被选中
* @property {Boolean} showExtraIcon = [true|false] 左侧是否显示扩展图标
* @property {Boolean} scrollY = [true|false] 允许纵向滚动,需要显式的设置其宽高
* @property {Object} extraIcon 扩展图标参数,格式为 {color: '#4cd964',size: '22',type: 'spinner'}
* @event {Function} click 点击 uniListItem 触发事件
* @event {Function} switchChange 点击切换 Switch 时触发
*/
export default {
name: 'UniListItem',
components: {
uniIcons,
uniBadge
},
props: {
title: {
type: String,
default: ''
}, // 列表标题
note: {
type: String,
default: ''
}, // 列表描述
disabled: {
// 是否禁用
type: [Boolean, String],
default: false
},
showArrow: {
// 是否显示箭头
type: [Boolean, String],
default: true
},
showBadge: {
// 是否显示数字角标
type: [Boolean, String],
default: false
},
showSwitch: {
// 是否显示Switch
type: [Boolean, String],
default: false
},
switchChecked: {
// Switch是否被选中
type: [Boolean, String],
default: false
},
badgeText: {
// badge内容
type: String,
default: ''
},
badgeType: {
// badge类型
type: String,
default: 'success'
},
rightText: {
// 右侧文字内容
type: String,
default: ''
},
thumb: {
// 缩略图
type: String,
default: ''
},
showExtraIcon: {
// 是否显示扩展图标
type: [Boolean, String],
default: false
},
extraIcon: {
type: Object,
default () {
return {
type: 'contact',
color: '#000000',
size: 20
}
}
}
},
inject: ['list'],
data() {
return {
isFirstChild: false
}
},
mounted() {
if (!this.list.firstChildAppend) {
this.list.firstChildAppend = true
this.isFirstChild = true
}
},
methods: {
onClick() {
this.$emit('click')
},
onSwitchChange(e) {
this.$emit('switchChange', e.detail)
}
}
}
</script>
<style lang="scss" scoped>
$list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg;
.uni-list-item {
font-size: $uni-font-size-lg;
position: relative;
flex-direction: column;
justify-content: space-between;
padding-left: $uni-spacing-row-lg;
}
.uni-list-item--disabled {
opacity: 0.3;
}
.uni-list-item--hover {
background-color: $uni-bg-color-hover;
}
.uni-list-item__container {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
padding: $list-item-pd;
padding-left: 0;
flex: 1;
position: relative;
justify-content: space-between;
align-items: center;
/* #ifdef APP-PLUS */
border-top-color: $uni-border-color;
border-top-style: solid;
border-top-width: 0.5px;
/* #endif */
}
.uni-list-item--first {
border-top-width: 0px;
}
/* #ifndef APP-NVUE */
.uni-list-item__container:after {
position: absolute;
top: 0;
right: 0;
left: 0;
height: 1px;
content: '';
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
background-color: $uni-border-color;
}
.uni-list-item--first:after {
height: 0px;
}
/* #endif */
.uni-list-item__content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
overflow: hidden;
flex-direction: column;
color: #3b4144;
}
.uni-list-item__content-title {
font-size: $uni-font-size-base;
color: #3b4144;
overflow: hidden;
}
.uni-list-item__content-note {
margin-top: 6rpx;
color: $uni-text-color-grey;
font-size: $uni-font-size-sm;
overflow: hidden;
}
.uni-list-item__extra {
// width: 25%;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: flex-end;
align-items: center;
}
.uni-list-item__icon {
margin-right: 18rpx;
flex-direction: row;
justify-content: center;
align-items: center;
}
.uni-list-item__icon-img {
height: $uni-img-size-base;
width: $uni-img-size-base;
}
.uni-list-item__extra-text {
color: $uni-text-color-grey;
font-size: $uni-font-size-sm;
}
</style>
+75
View File
@@ -0,0 +1,75 @@
<template>
<!-- #ifndef APP-NVUE -->
<view class="uni-list">
<slot />
</view>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<list class="uni-list" :enableBackToTop="enableBackToTop" loadmoreoffset="15" :scroll-y="scrollY" @loadmore="loadMore">
<slot />
</list>
<!-- #endif -->
</template>
<script>
/**
* List 列表
* @description 列表组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=24
*/
export default {
name: 'UniList',
'mp-weixin': {
options: {
multipleSlots: false
}
},
props: {
enableBackToTop: {
type: [Boolean, String],
default: false
},
scrollY: {
type: [Boolean, String],
default: false
}
},
provide() {
return {
list: this
}
},
created() {
this.firstChildAppend = false
},
methods: {
loadMore(e) {
this.$emit("scrolltolower");
}
}
}
</script>
<style lang="scss" scoped>
.uni-list {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
background-color: $uni-bg-color;
position: relative;
flex-direction: column;
// border-bottom-color: $uni-border-color;
// border-bottom-style: solid;
// border-bottom-width: 1px;
}
/* #ifndef APP-NVUE */
.uni-list:before {
height: 0;
}
.uni-list:after {
height: 0;
}
/* #endif */
</style>
+65
View File
@@ -0,0 +1,65 @@
<template>
<!-- #ifdef APP-NVUE -->
<refresh :display="display" @refresh="onrefresh" @pullingdown="onpullingdown">
<slot />
</refresh>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<view ref="uni-refresh" class="uni-refresh" v-show="isShow">
<slot />
</view>
<!-- #endif -->
</template>
<script>
export default {
name: 'UniRefresh',
props: {
display: {
type: [String],
default: "hide"
}
},
data() {
return {
pulling: false
}
},
computed: {
isShow() {
if (this.display === "show" || this.pulling === true) {
return true;
}
return false;
}
},
created() {},
methods: {
onchange(value) {
this.pulling = value;
},
onrefresh(e) {
this.$emit("refresh", e);
},
onpullingdown(e) {
// #ifdef APP-NVUE
this.$emit("pullingdown", e);
// #endif
// #ifndef APP-NVUE
var detail = {
viewHeight: 90,
pullingDistance: e.height
}
this.$emit("pullingdown", detail);
// #endif
}
}
}
</script>
<style>
.uni-refresh {
height: 0;
overflow: hidden;
}
</style>
+87
View File
@@ -0,0 +1,87 @@
var pullDown = {
threshold: 95,
maxHeight: 200,
callRefresh: 'onrefresh',
callPullingDown: 'onpullingdown',
refreshSelector: '.uni-refresh'
};
function ready(newValue, oldValue, ownerInstance, instance) {
var state = instance.getState()
state.canPullDown = newValue;
// console.log(newValue);
}
function touchStart(e, instance) {
var state = instance.getState();
state.refreshInstance = instance.selectComponent(pullDown.refreshSelector);
state.canPullDown = (state.refreshInstance != null && state.refreshInstance != undefined);
if (!state.canPullDown) {
return
}
// console.log("touchStart");
state.height = 0;
state.touchStartY = e.touches[0].pageY || e.changedTouches[0].pageY;
state.refreshInstance.setStyle({
'height': 0
});
state.refreshInstance.callMethod("onchange", true);
}
function touchMove(e, ownerInstance) {
var instance = e.instance;
var state = instance.getState();
if (!state.canPullDown) {
return
}
var oldHeight = state.height;
var endY = e.touches[0].pageY || e.changedTouches[0].pageY;
var height = endY - state.touchStartY;
if (height > pullDown.maxHeight) {
return;
}
var refreshInstance = state.refreshInstance;
refreshInstance.setStyle({
'height': height + 'px'
});
height = height < pullDown.maxHeight ? height : pullDown.maxHeight;
state.height = height;
refreshInstance.callMethod(pullDown.callPullingDown, {
height: height
});
}
function touchEnd(e, ownerInstance) {
var state = e.instance.getState();
if (!state.canPullDown) {
return
}
state.refreshInstance.callMethod("onchange", false);
var refreshInstance = state.refreshInstance;
if (state.height > pullDown.threshold) {
refreshInstance.callMethod(pullDown.callRefresh);
return;
}
refreshInstance.setStyle({
'height': 0
});
}
function propObserver(newValue, oldValue, instance) {
pullDown = newValue;
}
module.exports = {
touchmove: touchMove,
touchstart: touchStart,
touchend: touchEnd,
propObserver: propObserver
}
File diff suppressed because one or more lines are too long
+235
View File
@@ -0,0 +1,235 @@
<template>
<view class="uni-navbar">
<view :class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }" :style="{ 'background-color': backgroundColor }" class="uni-navbar__content">
<uni-status-bar v-if="statusBar" />
<view :style="{ color: color,backgroundColor: backgroundColor }" class="uni-navbar__header uni-navbar__content_view">
<view @tap="onClickLeft" class="uni-navbar__header-btns uni-navbar__header-btns-left uni-navbar__content_view">
<view class="uni-navbar__content_view" v-if="leftIcon.length">
<uni-icons :color="color" :type="leftIcon" size="24" />
</view>
<view :class="{ 'uni-navbar-btn-icon-left': !leftIcon.length }" class="uni-navbar-btn-text uni-navbar__content_view" v-if="leftText.length">
<text :style="{ color: color, fontSize: '14px' }">{{ leftText }}</text>
</view>
<slot name="left" />
</view>
<view class="uni-navbar__header-container uni-navbar__content_view">
<view class="uni-navbar__header-container-inner uni-navbar__content_view" v-if="title.length">
<text class="uni-nav-bar-text" :style="{color: color }">{{ title }}</text>
</view>
<!-- 标题插槽 -->
<slot />
</view>
<view :class="title.length ? 'uni-navbar__header-btns-right' : ''" @tap="onClickRight" class="uni-navbar__header-btns uni-navbar__content_view">
<view class="uni-navbar__content_view" v-if="rightIcon.length">
<uni-icons :color="color" :type="rightIcon" size="24" />
</view>
<!-- 优先显示图标 -->
<view class="uni-navbar-btn-text uni-navbar__content_view" v-if="rightText.length && !rightIcon.length">
<text class="uni-nav-bar-right-text">{{ rightText }}</text>
</view>
<slot name="right" />
</view>
</view>
</view>
<view class="uni-navbar__placeholder" v-if="fixed">
<uni-status-bar v-if="statusBar" />
<view class="uni-navbar__placeholder-view" />
</view>
</view>
</template>
<script>
import uniStatusBar from "../uni-status-bar/uni-status-bar.vue";
import uniIcons from "../uni-icons/uni-icons.vue";
/**
* NavBar 自定义导航栏
* @description 导航栏组件,主要用于头部导航
* @tutorial https://ext.dcloud.net.cn/plugin?id=52
* @property {String} title 标题文字
* @property {String} leftText 左侧按钮文本
* @property {String} rightText 右侧按钮文本
* @property {String} leftIcon 左侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
* @property {String} rightIcon 右侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
* @property {String} color 图标和文字颜色
* @property {String} backgroundColor 导航栏背景颜色
* @property {Boolean} fixed = [true|false] 是否固定顶部
* @property {Boolean} statusBar = [true|false] 是否包含状态栏
* @property {Boolean} shadow = [true|false] 导航栏下是否有阴影
* @event {Function} clickLeft 左侧按钮点击时触发
* @event {Function} clickRight 右侧按钮点击时触发
*/
export default {
name: "UniNavBar",
components: {
uniStatusBar,
uniIcons
},
props: {
title: {
type: String,
default: ""
},
leftText: {
type: String,
default: ""
},
rightText: {
type: String,
default: ""
},
leftIcon: {
type: String,
default: ""
},
rightIcon: {
type: String,
default: ""
},
fixed: {
type: [Boolean, String],
default: false
},
color: {
type: String,
default: "#000000"
},
backgroundColor: {
type: String,
default: "#FFFFFF"
},
statusBar: {
type: [Boolean, String],
default: false
},
shadow: {
type: [Boolean, String],
default: false
},
border: {
type: [Boolean, String],
default: true
}
},
mounted() {
if (uni.report && this.title !== '') {
uni.report('title', this.title)
}
},
methods: {
onClickLeft() {
this.$emit("clickLeft");
},
onClickRight() {
this.$emit("clickRight");
}
}
};
</script>
<style scoped>
.uni-nav-bar-text {
/* #ifdef APP-PLUS */
font-size: 34rpx;
/* #endif */
/* #ifndef APP-PLUS */
font-size: 32rpx;
/* #endif */
}
.uni-nav-bar-right-text {
font-size: 28rpx;
}
.uni-navbar__content {
position: relative;
background-color: #ffffff;
overflow: hidden;
}
.uni-navbar__content_view {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
align-items: center;
flex-direction: row;
/* background-color: #FFFFFF;
*/
}
.uni-navbar__header {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
height: 44px;
line-height: 44px;
font-size: 16px;
/* background-color: #ffffff;
*/
}
.uni-navbar__header-btns {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-wrap: nowrap;
width: 120rpx;
padding: 0 6px;
justify-content: center;
align-items: center;
}
.uni-navbar__header-btns-left {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
width: 150rpx;
justify-content: flex-start;
}
.uni-navbar__header-btns-right {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
width: 150rpx;
padding-right: 30rpx;
justify-content: flex-end;
}
.uni-navbar__header-container {
flex: 1;
}
.uni-navbar__header-container-inner {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
align-items: center;
justify-content: center;
font-size: 28rpx;
}
.uni-navbar__placeholder-view {
height: 44px;
}
.uni-navbar--fixed {
position: fixed;
z-index: 998;
}
.uni-navbar--shadow {
/* #ifndef APP-NVUE */
box-shadow: 0 1px 6px #ccc;
/* #endif */
}
.uni-navbar--border {
border-bottom-width: 1rpx;
border-bottom-style: solid;
border-bottom-color: #e5e5e5;
}
</style>
@@ -0,0 +1,392 @@
<template>
<view v-if="show" class="uni-noticebar" :style="{ backgroundColor: backgroundColor }" @click="onClick">
<!-- #ifdef MP-ALIPAY -->
<view v-if="showClose === true || showClose === 'true'" class="uni-noticebar-close" @click="close">
<uni-icons type="closeempty" :color="color" size="12" />
</view>
<view v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon">
<uni-icons type="sound" :color="color" size="14" />
</view>
<!-- #endif -->
<!-- #ifndef MP-ALIPAY -->
<uni-icons v-if="showClose === true || showClose === 'true'" class="uni-noticebar-close" type="closeempty" :color="color" size="12" @click="close" />
<uni-icons v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon" type="sound" :color="color" size="14" />
<!-- #endif -->
<view ref="textBox" class="uni-noticebar__content-wrapper" :class="{'uni-noticebar__content-wrapper--scrollable':scrollable, 'uni-noticebar__content-wrapper--single':!scrollable && (single || moreText)}">
<view :id="elIdBox" class="uni-noticebar__content" :class="{'uni-noticebar__content--scrollable':scrollable, 'uni-noticebar__content--single':!scrollable && (single || moreText)}">
<text :id="elId" ref="animationEle" class="uni-noticebar__content-text" :class="{'uni-noticebar__content-text--scrollable':scrollable,'uni-noticebar__content-text--single':!scrollable && (single || moreText)}" :style="{color:color, width:wrapWidth+'px', 'animationDuration': animationDuration, '-webkit-animationDuration': animationDuration ,animationPlayState: webviewHide?'paused':animationPlayState,'-webkit-animationPlayState':webviewHide?'paused':animationPlayState, animationDelay: animationDelay, '-webkit-animationDelay':animationDelay}">{{text}}</text>
</view>
</view>
<view v-if="showGetMore === true || showGetMore === 'true'" class="uni-noticebar__more" @click="clickMore">
<text v-if="moreText" :style="{ color: moreColor }" class="uni-noticebar__more-text">{{ moreText }}</text>
<uni-icons type="arrowright" :color="moreColor" size="14" />
</view>
</view>
</template>
<script>
import uniIcons from '../uni-icons/uni-icons.vue'
// #ifdef APP-NVUE
const dom = weex.requireModule('dom');
const animation = weex.requireModule('animation');
// #endif
/**
* NoticeBar 自定义导航栏
* @description 通告栏组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=30
* @property {Number} speed 文字滚动的速度,默认100px/秒
* @property {String} text 显示文字
* @property {String} backgroundColor 背景颜色
* @property {String} color 文字颜色
* @property {String} moreColor 查看更多文字的颜色
* @property {String} moreText 设置“查看更多”的文本
* @property {Boolean} single = [true|false] 是否单行
* @property {Boolean} scrollable = [true|false] 是否滚动,为true时,NoticeBar为单行
* @property {Boolean} showIcon = [true|false] 是否显示左侧喇叭图标
* @property {Boolean} showClose = [true|false] 是否显示左侧关闭按钮
* @property {Boolean} showGetMore = [true|false] 是否显示右侧查看更多图标,为true时,NoticeBar为单行
* @event {Function} click 点击 NoticeBar 触发事件
* @event {Function} close 关闭 NoticeBar 触发事件
* @event {Function} getmore 点击”查看更多“时触发事件
*/
export default {
name: 'UniNoticeBar',
components: {
uniIcons
},
props: {
text: {
type: String,
default: ''
},
moreText: {
type: String,
default: ''
},
backgroundColor: {
type: String,
default: '#fffbe8'
},
speed: {
// 默认1s滚动100px
type: Number,
default: 100
},
color: {
type: String,
default: '#de8c17'
},
moreColor: {
type: String,
default: '#999999'
},
single: {
// 是否单行
type: [Boolean, String],
default: false
},
scrollable: {
// 是否滚动,添加后控制单行效果取消
type: [Boolean, String],
default: false
},
showIcon: {
// 是否显示左侧icon
type: [Boolean, String],
default: false
},
showGetMore: {
// 是否显示右侧查看更多
type: [Boolean, String],
default: false
},
showClose: {
// 是否显示左侧关闭按钮
type: [Boolean, String],
default: false
}
},
data() {
const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
const elIdBox = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
return {
textWidth: 0,
boxWidth: 0,
wrapWidth: '',
webviewHide: false,
// #ifdef APP-NVUE
stopAnimation: false,
// #endif
elId: elId,
elIdBox: elIdBox,
show: true,
animationDuration: 'none',
animationPlayState: 'paused',
animationDelay: '0s'
}
},
mounted() {
// #ifdef APP-PLUS
var pages = getCurrentPages();
var page = pages[pages.length - 1];
var currentWebview = page.$getAppWebview();
currentWebview.addEventListener('hide', () => {
this.webviewHide = true
})
currentWebview.addEventListener('show', () => {
this.webviewHide = false
})
// #endif
this.$nextTick(() => {
this.initSize()
})
},
// #ifdef APP-NVUE
beforeDestroy() {
this.stopAnimation = true
},
// #endif
methods: {
initSize() {
if (this.scrollable) {
// #ifndef APP-NVUE
let query = [],
boxWidth = 0,
textWidth = 0;
let textQuery = new Promise((resolve, reject) => {
uni.createSelectorQuery()
// #ifndef MP-ALIPAY
.in(this)
// #endif
.select(`#${this.elId}`)
.boundingClientRect()
.exec(ret => {
this.textWidth = ret[0].width
resolve()
})
})
let boxQuery = new Promise((resolve, reject) => {
uni.createSelectorQuery()
// #ifndef MP-ALIPAY
.in(this)
// #endif
.select(`#${this.elIdBox}`)
.boundingClientRect()
.exec(ret => {
this.boxWidth = ret[0].width
resolve()
})
})
query.push(textQuery)
query.push(boxQuery)
Promise.all(query).then(() => {
this.animationDuration = `${this.textWidth / this.speed}s`
this.animationDelay = `-${this.boxWidth / this.speed}s`
setTimeout(() => {
this.animationPlayState = 'running'
}, 1000)
})
// #endif
// #ifdef APP-NVUE
dom.getComponentRect(this.$refs['animationEle'], (res) => {
let winWidth = uni.getSystemInfoSync().windowWidth
this.textWidth = res.size.width
animation.transition(this.$refs['animationEle'], {
styles: {
transform: `translateX(-${winWidth}px)`
},
duration: 0,
timingFunction: 'linear',
delay: 0
}, () => {
if (!this.stopAnimation) {
animation.transition(this.$refs['animationEle'], {
styles: {
transform: `translateX(-${this.textWidth}px)`
},
timingFunction: 'linear',
duration: (this.textWidth - winWidth) / this.speed * 1000,
delay: 1000
}, () => {
if (!this.stopAnimation) {
this.loopAnimation()
}
});
}
});
})
// #endif
}
// #ifdef APP-NVUE
if (!this.scrollable && (this.single || this.moreText)) {
dom.getComponentRect(this.$refs['textBox'], (res) => {
this.wrapWidth = res.size.width
})
}
// #endif
},
loopAnimation() {
// #ifdef APP-NVUE
animation.transition(this.$refs['animationEle'], {
styles: {
transform: `translateX(0px)`
},
duration: 0
}, () => {
if (!this.stopAnimation) {
animation.transition(this.$refs['animationEle'], {
styles: {
transform: `translateX(-${this.textWidth}px)`
},
duration: this.textWidth / this.speed * 1000,
timingFunction: 'linear',
delay: 0
}, () => {
if (!this.stopAnimation) {
this.loopAnimation()
}
});
}
});
// #endif
},
clickMore() {
this.$emit('getmore')
},
close() {
this.show = false;
this.$emit('close')
},
onClick() {
this.$emit('click')
}
}
}
</script>
<style scoped>
.uni-noticebar {
/* #ifndef APP-NVUE */
display: flex;
width: 100%;
box-sizing: border-box;
/* #endif */
flex-direction: row;
align-items: center;
padding: 6px 12px;
margin-bottom: 10px;
}
.uni-noticebar-close {
margin-right: 5px;
}
.uni-noticebar-icon {
margin-right: 5px;
}
.uni-noticebar__content-wrapper {
flex: 1;
flex-direction: column;
overflow: hidden;
}
.uni-noticebar__content-wrapper--single {
/* #ifndef APP-NVUE */
line-height: 18px;
/* #endif */
}
.uni-noticebar__content-wrapper--single,
.uni-noticebar__content-wrapper--scrollable {
flex-direction: row;
}
/* #ifndef APP-NVUE */
.uni-noticebar__content-wrapper--scrollable {
position: relative;
height: 18px;
}
/* #endif */
.uni-noticebar__content--scrollable {
/* #ifdef APP-NVUE */
flex: 0;
/* #endif */
/* #ifndef APP-NVUE */
flex: 1;
display: block;
overflow: hidden;
/* #endif */
}
.uni-noticebar__content--single {
/* #ifndef APP-NVUE */
display: flex;
flex: none;
width: 100%;
justify-content: center;
/* #endif */
}
.uni-noticebar__content-text {
font-size: 14px;
line-height: 18px;
/* #ifndef APP-NVUE */
word-break: break-all;
/* #endif */
}
.uni-noticebar__content-text--single {
/* #ifdef APP-NVUE */
lines: 1;
/* #endif */
/* #ifndef APP-NVUE */
display: block;
width: 100%;
white-space: nowrap;
/* #endif */
overflow: hidden;
text-overflow: ellipsis;
}
.uni-noticebar__content-text--scrollable {
/* #ifdef APP-NVUE */
lines: 1;
padding-left: 750rpx;
/* #endif */
/* #ifndef APP-NVUE */
position: absolute;
display: block;
height: 18px;
line-height: 18px;
white-space: nowrap;
padding-left: 100%;
animation: notice 10s 0s linear infinite both;
animation-play-state: paused;
/* #endif */
}
.uni-noticebar__more {
/* #ifndef APP-NVUE */
display: inline-flex;
/* #endif */
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
padding-left: 5px;
}
.uni-noticebar__more-text {
font-size: 14px;
}
@keyframes notice {
100% {
transform: translate3d(-100%, 0, 0);
}
}
</style>
+264
View File
@@ -0,0 +1,264 @@
<template>
<view v-if="showPopup" class="uni-popup" @touchmove.stop.prevent="clear">
<uni-transition :mode-class="['fade']" :styles="maskClass" :duration="duration" :show="showTrans" @click="onTap" />
<uni-transition :mode-class="ani" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
<view class="uni-popup__wrapper-box" @click.stop="clear">
<slot />
</view>
</uni-transition>
</view>
</template>
<script>
import uniTransition from '../uni-transition/uni-transition.vue'
/**
* PopUp 弹出层
* @description 弹出层组件,为了解决遮罩弹层的问题
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} type = [top|center|bottom] 弹出方式
* @value top 顶部弹出
* @value center 中间弹出
* @value bottom 底部弹出
* @property {Boolean} animation = [ture|false] 是否开启动画
* @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
* @event {Function} change 打开关闭弹窗触发,e={show: false}
*/
export default {
name: 'UniPopup',
components: {
uniTransition
},
props: {
// 开启动画
animation: {
type: Boolean,
default: true
},
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
type: {
type: String,
default: 'center'
},
// maskClick
maskClick: {
type: Boolean,
default: true
}
},
data() {
return {
duration: 300,
ani: [],
showPopup: false,
showTrans: false,
maskClass: {
'position': 'fixed',
'bottom': 0,
'top': 0,
'left': 0,
'right': 0,
'backgroundColor': 'rgba(0, 0, 0, 0.4)'
},
transClass: {
'position': 'fixed',
'left': 0,
'right': 0,
}
}
},
watch: {
type: {
handler: function(newVal) {
switch (this.type) {
case 'top':
this.ani = ['slide-top']
this.transClass = {
'position': 'fixed',
'left': 0,
'right': 0,
}
break
case 'bottom':
this.ani = ['slide-bottom']
this.transClass = {
'position': 'fixed',
'left': 0,
'right': 0,
'bottom': 0
}
break
case 'center':
this.ani = ['zoom-out', 'fade']
this.transClass = {
'position': 'fixed',
/* #ifndef APP-NVUE */
'display': 'flex',
'flexDirection': 'column',
/* #endif */
'bottom': 0,
'left': 0,
'right': 0,
'top': 0,
'justifyContent': 'center',
'alignItems': 'center'
}
break
}
},
immediate: true
}
},
created() {
if (this.animation) {
this.duration = 300
} else {
this.duration = 0
}
},
methods: {
clear(e) {
// TODO nvue 取消冒泡
e.stopPropagation()
},
open() {
this.showPopup = true
this.$nextTick(() => {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.showTrans = true
}, 50);
})
this.$emit('change', {
show: true
})
},
close(type) {
this.showTrans = false
this.$nextTick(() => {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.$emit('change', {
show: false
})
this.showPopup = false
}, 300)
})
},
onTap() {
if (!this.maskClick) return
this.close()
}
}
}
</script>
<style scoped>
.uni-popup {
position: fixed;
/* #ifdef H5 */
top: var(--window-top);
/* #endif */
/* #ifndef H5 */
top: 0;
/* #endif */
bottom: 0;
left: 0;
right: 0;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
}
.uni-popup__mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.4);
opacity: 0;
}
.mask-ani {
transition-property: opacity;
transition-duration: 0.2s;
}
.uni-top-mask {
opacity: 1;
}
.uni-bottom-mask {
opacity: 1;
}
.uni-center-mask {
opacity: 1;
}
.uni-popup__wrapper {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: absolute;
}
.top {
top: 0;
left: 0;
right: 0;
transform: translateY(-500px);
}
.bottom {
bottom: 0;
left: 0;
right: 0;
transform: translateY(500px);
}
.center {
/* #ifndef APP-NVUE */
display: flex;
flex-direction: column;
/* #endif */
bottom: 0;
left: 0;
right: 0;
top: 0;
justify-content: center;
align-items: center;
transform: scale(1.2);
opacity: 0;
}
.uni-popup__wrapper-box {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: relative;
}
.content-ani {
/* transition: transform 0.3s;
*/
transition-property: transform, opacity;
transition-duration: 0.2s;
}
.uni-top-content {
transform: translateY(0);
}
.uni-bottom-content {
transform: translateY(0);
}
.uni-center-content {
transform: scale(1);
opacity: 1;
}
</style>
@@ -0,0 +1,183 @@
<template>
<view class="uni-searchbar">
<view :style="{borderRadius:radius+'px',backgroundColor: bgColor}" class="uni-searchbar__box" @click="searchClick">
<!-- #ifdef MP-ALIPAY -->
<view class="uni-searchbar__box-icon-search">
<uni-icons color="#999999" size="18" type="search" />
</view>
<!-- #endif -->
<!-- #ifndef MP-ALIPAY -->
<uni-icons color="#999999" class="uni-searchbar__box-icon-search" size="18" type="search" />
<!-- #endif -->
<input v-if="show" :focus="showSync" :placeholder="placeholder" :maxlength="maxlength" @confirm="confirm" class="uni-searchbar__box-search-input"
confirm-type="search" type="text" v-model="searchVal" />
<text v-else class="uni-searchbar__text-placeholder">{{ placeholder }}</text>
<view v-if="show && (clearButton==='always'||clearButton==='auto'&&searchVal!=='')" class="uni-searchbar__box-icon-clear" @click="clear">
<uni-icons color="#999999" class="" size="24" type="clear" />
</view>
</view>
<text @click="cancel" class="uni-searchbar__cancel" v-if="cancelButton ==='always' || show && cancelButton ==='auto'">{{cancelText}}</text>
</view>
</template>
<script>
import uniIcons from "../uni-icons/uni-icons.vue";
export default {
name: "UniSearchBar",
components: {
uniIcons
},
props: {
placeholder: {
type: String,
default: "请输入搜索内容"
},
radius: {
type: [Number, String],
default: 5
},
clearButton: {
type: String,
default: "auto"
},
cancelButton: {
type: String,
default: "auto"
},
cancelText: {
type: String,
default: '取消'
},
bgColor: {
type: String,
default: "#F8F8F8"
},
maxlength: {
type: [Number, String],
default: 100
}
},
data() {
return {
show: false,
showSync: false,
searchVal: ""
}
},
watch: {
searchVal() {
this.$emit("input", {
value: this.searchVal
})
}
},
methods: {
searchClick() {
if (this.show) {
return
}
this.searchVal = ""
this.show = true;
this.$nextTick(() => {
this.showSync = true;
})
},
clear() {
this.searchVal = ""
},
cancel() {
this.$emit("cancel", {
value: this.searchVal
});
this.searchVal = ""
this.show = false
this.showSync = false
// #ifndef APP-PLUS
uni.hideKeyboard()
// #endif
// #ifdef APP-PLUS
plus.key.hideSoftKeybord()
// #endif
},
confirm() {
// #ifndef APP-PLUS
uni.hideKeyboard();
// #endif
// #ifdef APP-PLUS
plus.key.hideSoftKeybord()
// #endif
this.$emit("confirm", {
value: this.searchVal
})
}
}
};
</script>
<style lang="scss" scoped>
$uni-searchbar-height: 36px;
.uni-searchbar {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
position: relative;
padding: $uni-spacing-col-base;
background-color: $uni-bg-color;
}
.uni-searchbar__box {
/* #ifndef APP-NVUE */
display: flex;
box-sizing: border-box;
/* #endif */
overflow: hidden;
position: relative;
flex: 1;
justify-content: center;
flex-direction: row;
align-items: center;
height: $uni-searchbar-height;
padding: 5px 8px 5px 0px;
border-width: 0.5px;
border-style: solid;
border-color: $uni-border-color;
}
.uni-searchbar__box-icon-search {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
width: 32px;
justify-content: center;
align-items: center;
color: $uni-text-color-placeholder;
}
.uni-searchbar__box-search-input {
flex: 1;
font-size: $uni-font-size-base;
color: $uni-text-color;
}
.uni-searchbar__box-icon-clear {
align-items: center;
line-height: 24px;
padding-left: 5px;
}
.uni-searchbar__text-placeholder {
font-size: $uni-font-size-base;
color: $uni-text-color-placeholder;
margin-left: 5px;
}
.uni-searchbar__cancel {
padding-left: 10px;
line-height: $uni-searchbar-height;
font-size: 14px;
color: $uni-text-color;
}
</style>
+136
View File
@@ -0,0 +1,136 @@
<template>
<view class="uni-section" nvue>
<view v-if="type" class="uni-section__head">
<view :class="type" class="uni-section__head-tag" />
</view>
<view class="uni-section__content">
<text :class="{'distraction':!subTitle}" class="uni-section__content-title">{{ title }}</text>
<text v-if="subTitle" class="uni-section__content-sub">{{ subTitle }}</text>
</view>
<slot />
</view>
</template>
<script>
/**
* Section 标题栏
* @description 标题栏
* @property {String} type = [line|circle] 标题装饰类型
* @value line 竖线
* @value circle 圆形
* @property {String} title 主标题
* @property {String} subTitle 副标题
*/
export default {
name: 'UniTitle',
props: {
type: {
type: String,
default: ''
},
title: {
type: String,
default: ''
},
subTitle: {
type: String,
default: ''
}
},
data() {
return {}
},
watch: {
title(newVal) {
if (uni.report && newVal !== '') {
uni.report('title', newVal)
}
}
},
methods: {
onClick() {
this.$emit('click')
}
}
}
</script>
<style scoped>
.uni-section {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
margin-top: 10px;
flex-direction: row;
align-items: center;
padding: 0 10px;
height: 50px;
background-color: #f8f8f8;
/* #ifdef APP-NVUE */
border-bottom-color: #e5e5e5;
border-bottom-style: solid;
border-bottom-width: 0.5px;
/* #endif */
font-weight: normal;
}
/* #ifndef APP-NVUE */
.uni-section:after {
position: absolute;
bottom: 0;
right: 0;
left: 0;
height: 1px;
content: '';
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
background-color: #e5e5e5;
}
/* #endif */
.uni-section__head {
flex-direction: row;
justify-content: center;
align-items: center;
margin-right: 10px;
}
.line {
height: 15px;
background-color: #c0c0c0;
border-radius: 5px;
width: 3px;
}
.circle {
width: 8px;
height: 8px;
border-top-right-radius: 50px;
border-top-left-radius: 50px;
border-bottom-left-radius: 50px;
border-bottom-right-radius: 50px;
background-color: #c0c0c0;
}
.uni-section__content {
flex: 1;
color: #333;
}
.uni-section__content-title {
font-size: 28rpx;
color: #333;
}
.distraction {
flex-direction: row;
align-items: center;
}
.uni-section__content-sub {
font-size: 24rpx;
color: #999;
}
</style>
@@ -0,0 +1,26 @@
<template>
<view :style="{ height: statusBarHeight }" class="uni-status-bar">
<slot />
</view>
</template>
<script>
var statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px'
export default {
name: 'UniStatusBar',
data() {
return {
statusBarHeight: statusBarHeight
}
}
}
</script>
<style scoped>
.uni-status-bar {
width: 750rpx;
height: 20px;
/* height: var(--status-bar-height);
*/
}
</style>
@@ -0,0 +1,279 @@
<template>
<view v-if="isShow" ref="ani" class="uni-transition" :class="[ani.in]" :style="'transform:' +transform+';'+stylesObject" @click="change">
<slot></slot>
</view>
</template>
<script>
// #ifdef APP-NVUE
const animation = uni.requireNativePlugin('animation');
// #endif
/**
* Transition 过渡动画
* @description 简单过渡动画组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
* @property {Array} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
* @value fade 渐隐渐出过渡
* @value slide-top 由上至下过渡
* @value slide-right 由右至左过渡
* @value slide-bottom 由下至上过渡
* @value slide-left 由左至右过渡
* @value zoom-in 由小到大过渡
* @value zoom-out 由大到小过渡
* @property {Number} duration 过渡动画持续时间
* @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
*/
export default {
name: 'uniTransition',
props: {
show: {
type: Boolean,
default: false
},
modeClass: {
type: Array,
default () {
return []
}
},
duration: {
type: Number,
default: 300
},
styles: {
type: Object,
default () {
return {}
}
}
},
data() {
return {
isShow: false,
transform: '',
ani: {
in: '',
active: ''
}
};
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.open()
} else {
this.close()
}
},
immediate: true
}
},
computed: {
stylesObject() {
let styles = {
...this.styles,
'transition-duration': this.duration / 1000 + 's'
}
let transfrom = ''
for (let i in styles) {
let line = this.toLine(i)
transfrom += line + ':' + styles[i] + ';'
}
return transfrom
}
},
created() {
// this.timer = null
// this.nextTick = (time = 50) => new Promise(resolve => {
// clearTimeout(this.timer)
// this.timer = setTimeout(resolve, time)
// return this.timer
// });
},
methods: {
change() {
this.$emit('click', {
detail: this.isShow
})
},
open() {
clearTimeout(this.timer)
this.isShow = true
this.transform = ''
this.ani.in = ''
for (let i in this.getTranfrom(false)) {
if (i === 'opacity') {
this.ani.in = 'fade-in'
} else {
this.transform += `${this.getTranfrom(false)[i]} `
}
}
this.$nextTick(() => {
setTimeout(() => {
this._animation(true)
}, 50)
})
},
close(type) {
clearTimeout(this.timer)
this._animation(false)
},
_animation(type) {
let styles = this.getTranfrom(type)
// #ifdef APP-NVUE
if (!this.$refs['ani']) return
animation.transition(this.$refs['ani'].ref, {
styles,
duration: this.duration, //ms
timingFunction: 'ease',
needLayout: false,
delay: 0 //ms
}, () => {
if (!type) {
this.isShow = false
}
this.$emit('change', {
detail: this.isShow
})
})
// #endif
// #ifndef APP-NVUE
this.transform = ''
for (let i in styles) {
if (i === 'opacity') {
this.ani.in = `fade-${type?'out':'in'}`
} else {
this.transform += `${styles[i]} `
}
}
this.timer = setTimeout(() => {
if (!type) {
this.isShow = false
}
this.$emit('change', {
detail: this.isShow
})
}, this.duration)
// #endif
},
getTranfrom(type) {
let styles = {
transform: ''
}
this.modeClass.forEach((mode) => {
switch (mode) {
case 'fade':
styles.opacity = type ? 1 : 0
break;
case 'slide-top':
styles.transform += `translateY(${type?'0':'-100%'}) `
break;
case 'slide-right':
styles.transform += `translateX(${type?'0':'100%'}) `
break;
case 'slide-bottom':
styles.transform += `translateY(${type?'0':'100%'}) `
break;
case 'slide-left':
styles.transform += `translateX(${type?'0':'-100%'}) `
break;
case 'zoom-in':
styles.transform += `scale(${type?1:0.8}) `
break;
case 'zoom-out':
styles.transform += `scale(${type?1:1.2}) `
break;
}
})
return styles
},
_modeClassArr(type) {
let mode = this.modeClass
if (typeof(mode) !== "string") {
let modestr = ''
mode.forEach((item) => {
modestr += (item + '-' + type + ',')
})
return modestr.substr(0, modestr.length - 1)
} else {
return mode + '-' + type
}
},
// getEl(el) {
// console.log(el || el.ref || null);
// return el || el.ref || null
// },
toLine(name) {
return name.replace(/([A-Z])/g, "-$1").toLowerCase();
}
}
}
</script>
<style scoped>
.uni-transition {
transition-timing-function: ease;
transition-duration: 0.3s;
transition-property: transform, opacity;
}
.fade-in {
opacity: 0;
}
.fade-active {
opacity: 1;
}
.slide-top-in {
/* transition-property: transform, opacity; */
transform: translateY(-100%);
}
.slide-top-active {
transform: translateY(0);
/* opacity: 1; */
}
.slide-right-in {
transform: translateX(100%);
}
.slide-right-active {
transform: translateX(0);
}
.slide-bottom-in {
transform: translateY(100%);
}
.slide-bottom-active {
transform: translateY(0);
}
.slide-left-in {
transform: translateX(-100%);
}
.slide-left-active {
transform: translateX(0);
opacity: 1;
}
.zoom-in-in {
transform: scale(0.8);
}
.zoom-out-active {
transform: scale(1);
}
.zoom-out-in {
transform: scale(1.2);
}
</style>
+14
View File
@@ -0,0 +1,14 @@
import Vue from 'vue'
import App from './App'
import api from './api.js'
Vue.config.productionTip = false
Vue.prototype.$api = api
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
+86
View File
@@ -0,0 +1,86 @@
{
"name" : "盛华管理",
"appid" : "",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
"transformPx" : false,
"app-plus" : {
"usingComponents" : true,
"compilerVersion" : 3,
/* 5+App */
"modules" : {},
/* */
"distribute" : {
/* */
"android" : {
/* android */
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
"ios" : {},
/* ios */
"sdkConfigs" : {}
}
},
"h5" : {
"devServer" : {
"port" : "",
"disableHostCheck" : true,
"proxy" : {
"/wap" : {
"target" : "http://wedev.gdoooa.com",
"changeOrigin" : true,
"pathRewrite" : {
"^/wap" : ""
}
}
},
"https" : false
},
"title" : "爱客办公",
"router" : {
"base" : "/h5/"
},
"sdkConfigs" : {
"maps" : {
"qqmap" : {
"key" : "W6FBZ-JV4K4-O6WU5-XGZOL-GMTPJ-KIFWJ"
}
}
}
},
/* SDK */
"quickapp" : {},
/* */
"mp-weixin" : {
/* */
"appid" : "",
"setting" : {
"urlCheck" : true
},
"usingComponents" : true
}
}
+145
View File
@@ -0,0 +1,145 @@
{
"pages": [
{
"path": "pages/index",
"style": {
"navigationStyle":"custom"
}
},
{
"path": "pages/tabbar/notice",
"style": {
"navigationBarTitleText": "消息中心",
"navigationStyle":"custom",
"enablePullDownRefresh": true
}
},{
"path": "pages/tabbar/work",
"style": {
"navigationBarTitleText": "应用",
"navigationStyle":"custom"
}
},{
"path": "pages/tabbar/publish",
"style": {
"navigationBarTitleText": "发布",
"navigationStyle":"custom"
}
},{
"path": "pages/tabbar/addressbook",
"style": {
"navigationBarTitleText": "通讯录",
"navigationStyle":"custom"
}
},{
"path": "pages/tabbar/me",
"style": {
"navigationBarTitleText": "个人",
"navigationStyle":"custom"
}
},{
"path": "pages/login/wap",
"style": {
"navigationStyle":"custom"
}
},{
"path": "pages/login/wechat",
"style": {
"navigationStyle":"custom"
}
},{
"path": "pages/webview",
"style": {
"navigationStyle":"custom"
}
},{
"path": "pages/app/article/index",
"style": {
"navigationStyle":"custom",
"navigationBarTitleText": "新闻公告",
"enablePullDownRefresh": true
}
},{
"path": "pages/app/workflow/index",
"style": {
"navigationStyle":"custom",
"navigationBarTitleText": "工作流程",
"enablePullDownRefresh": true
}
},{
"path": "pages/app/saleOrder/index",
"style": {
"navigationStyle":"custom",
"navigationBarTitleText": "销售订单",
"enablePullDownRefresh": true
}
},{
"path": "pages/app/delivery/index",
"style": {
"navigationStyle":"custom",
"navigationBarTitleText": "发货列表",
"enablePullDownRefresh": true
}
},{
"path": "pages/app/approach/index",
"style": {
"navigationStyle":"custom",
"navigationBarTitleText": "进店列表",
"enablePullDownRefresh": true
}
},{
"path": "pages/app/promotion/index",
"style": {
"navigationStyle":"custom",
"navigationBarTitleText": "促销列表",
"enablePullDownRefresh": true
}
},{
"path": "pages/app/promotionMaterial/index",
"style": {
"navigationStyle":"custom",
"navigationBarTitleText": "促销资料列表",
"enablePullDownRefresh": true
}
},{
"path": "pages/app/promotionMaterial/upload",
"style": {
"navigationStyle":"custom",
"navigationBarTitleText": "促销资料上传"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "味聚特商务系统",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"borderStyle": "black",
"backgroundColor": "#F8F8F8",
"color": "#8F8F94",
"selectedColor": "#007aff",
"list": [{
"pagePath": "pages/tabbar/notice",
"iconPath": "static/img/tabbar/news.png",
"selectedIconPath": "static/img/tabbar/news_on.png",
"text": "消息"
},{
"pagePath": "pages/tabbar/work",
"iconPath": "static/img/tabbar/work.png",
"selectedIconPath": "static/img/tabbar/work_on.png",
"text": "应用"
},{
"pagePath": "pages/tabbar/addressbook",
"iconPath": "static/img/tabbar/addresslist.png",
"selectedIconPath": "static/img/tabbar/addresslist_on.png",
"text": "通讯录"
},{
"pagePath": "pages/tabbar/me",
"iconPath": "static/img/tabbar/me.png",
"selectedIconPath": "static/img/tabbar/me_on.png",
"text": "我"
}]
}
}
+274
View File
@@ -0,0 +1,274 @@
<template>
<view>
<view class="header" id="header">
<scroll-view id="tab-bar" class="scroll-h" :scroll-x="true" :show-scrollbar="false">
<view v-for="(tab, index) in tabBars" :key="index" class="uni-tab-item" :id="tab.id" @click="ontabtap(index)">
<text class="uni-tab-item-title" :class="tabIndex == index ? 'uni-tab-item-title-active' : ''">{{tab.name}}</text>
</view>
</scroll-view>
<view class="search-controller">
<uni-search-bar radius="50" placeholder="搜索单号" @confirm="search" />
</view>
<view class="line-h"></view>
</view>
<view class="uni-list uni-list-controller" :style="'margin-top:' + listTop + 'px;'">
<view class="uni-list-cell" hover-class="uni-list-cell-hover" v-for="(row, key) in tabBars[tabIndex].data" :key="key" @click="goDetail(row)">
<view class="uni-media-list">
<view class="uni-media-list-body">
<view class="uni-media-list-text-top">
<text>{{ row.master_sn }}</text>
<text>{{ row.master_customer_id_name }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text class="desc">{{ htmlClear(row.master_status) }}</text>
<text class="desc">{{ row.master_created_at }}</text>
</view>
</view>
</view>
</view>
</view>
<uni-load-more :status="tabBars[tabIndex].status" :icon-size="16" :content-text="tabBars[tabIndex].contentText" />
</view>
</template>
<script>
import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
import {dateUtils} from '@/util.js';
export default {
components: {
uniLoadMore
},
data() {
return {
tabIndex: 0,
listTop: 103,
tabBars: [{
name: '审核中',
id: 'flow.todo',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}, {
name: '已生效',
id: 'flow.done',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}],
reload: false
};
},
onLoad() {
var me = this;
me.getList(0);
},
onPullDownRefresh() {
let me = this;
me.reload = true;
let tab = me.tabBars[me.tabIndex];
tab.page = 1;
tab.status = 'more';
me.getList(me.tabIndex);
},
onReachBottom() {
let me = this;
let tab = me.tabBars[me.tabIndex];
if (tab.status == 'noMore') {
return;
}
tab.status = 'more';
this.getList(me.tabIndex);
},
mounted() {
let me = this;
uni.createSelectorQuery().in(this).select('#header').boundingClientRect(function(e) {
me.listTop = e.height - 1;
}).exec();
},
methods: {
ontabtap(index) {
var me = this;
me.tabIndex = index;
this.switchTab(index);
},
switchTab(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.data.length == 0) {
me.getList(index);
}
},
htmlClear(str) {
// 正则去掉所有的html标记
return str.replace(/<[^>]+>/g, "");
},
formatDate(value) {
return dateUtils.formatDate(value);
},
getList(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.status == 'noMore') {
if (me.reload) {
me.reload = false;
uni.stopPullDownRefresh();
}
return;
}
me.$api.post('approach/approach/index', {by: tab.id, page: tab.page}).then(res => {
if (me.reload) {
tab.data = [];
me.reload = false;
uni.stopPullDownRefresh();
}
tab.data = tab.data.concat(res.data);
if (res.current_page >= res.last_page) {
tab.status = 'noMore';
} else {
tab.page = res.current_page + 1;
}
}).catch(error => {
});
},
goDetail: function(row) {
uni.navigateTo({
url: '/pages/webview?title=进店详情&url=' + encodeURIComponent('approach/approach/show?id=' + row.master_id),
});
}
}
};
</script>
<style>
page {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: center;
background: rgba(249, 249, 249, 1);
}
.header {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 100;
background: #fff;
width: 100vw;
}
.uni-list-controller {
margin-top: 103px;
width: 100vw;
}
.uni-media-list-logo {
width: 140rpx;
height: 140rpx;
}
.uni-media-list-body {
height: auto;
justify-content: space-around;
}
.uni-media-list-text-top {
display: flex;
font-size: 28rpx;
flex-direction: row;
justify-content: space-between;
}
.uni-media-list-text-bottom {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 15rpx;
}
.uni-media-list-text-bottom .desc {
margin-bottom: 15rpx;
display: block;
}
.uni-media-list-text-bottom .desc:last-child {
margin-bottom: 0;
}
.scroll-h {
width: 750rpx;
height: 80rpx;
flex-direction: row;
white-space: nowrap;
align-items: center;
border-bottom: 1px solid #c8c7cc;
}
.line-h {
height: 1rpx;
background-color: #cccccc;
}
.uni-tab-item {
display: inline-block;
/*
padding-left: 70rpx;
padding-right: 70rpx;
*/
text-align: center;
width: 50%;
}
.uni-tab-item-title {
color: #555;
font-size: 30rpx;
height: 80rpx;
line-height: 80rpx;
flex-wrap: nowrap;
white-space: nowrap;
}
.uni-tab-item-title-active {
color: #007AFF;
}
.scroll-v {
flex: 1;
width: 750rpx;
}
.search-controller {
padding: 10rpx;
}
.search-result {
margin-top: 10px;
margin-bottom: 20px;
text-align: center;
}
.search-result-text {
text-align: center;
font-size: 14px;
}
</style>
+299
View File
@@ -0,0 +1,299 @@
<template>
<view>
<view class="header" id="header">
<scroll-view id="tab-bar" class="scroll-h" :scroll-x="true" :show-scrollbar="false">
<view v-for="(tab, index) in tabBars" :key="index" class="uni-tab-item" :id="tab.id" @click="ontabtap(index)">
<text class="uni-tab-item-title" :class="tabIndex == index ? 'uni-tab-item-title-active' : ''">{{tab.name}}</text>
</view>
</scroll-view>
<view class="search-controller">
<uni-search-bar radius="50" placeholder="搜索主题" @confirm="search" />
</view>
<view class="line-h"></view>
</view>
<view class="uni-list uni-list-controller" :style="'margin-top:' + listTop + 'px;'">
<view class="uni-list-cell" hover-class="uni-list-cell-hover" v-for="(row, key) in tabBars[tabIndex].data" :key="key" @click="goDetail(row)">
<view class="uni-media-list">
<view class="uni-media-list-body">
<view class="uni-media-list-text-top">
<text>{{ row.name }}</text>
<text>{{ row.description }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text class="desc">{{ row.created_by }}</text>
<text class="desc">{{ row.created_at }}</text>
</view>
</view>
</view>
</view>
</view>
<uni-load-more :status="tabBars[tabIndex].status" :icon-size="16" :content-text="tabBars[tabIndex].contentText" />
</view>
</template>
<script>
import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
import {dateUtils} from '@/util.js';
export default {
components: {
uniLoadMore
},
data() {
return {
tabIndex: 0,
listTop: 103,
tabBars: [{
name: '全部',
id: 'all',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}, {
name: '未读',
id: 'unread',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}, {
name: '已读',
id: 'done',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}],
reload: false
};
},
onLoad() {
var me = this;
me.getList(0);
},
mounted() {
let me = this;
uni.createSelectorQuery().in(this).select('#header').boundingClientRect(function(e) {
me.listTop = e.height - 1;
}).exec();
},
onPullDownRefresh() {
let me = this;
me.reload = true;
let tab = me.tabBars[me.tabIndex];
tab.page = 1;
tab.status = 'more';
me.getList(me.tabIndex);
},
onReachBottom() {
let me = this;
let tab = me.tabBars[me.tabIndex];
if (tab.status == 'noMore') {
return;
}
tab.status = 'more';
this.getList(me.tabIndex);
},
methods: {
ontabtap(index) {
var me = this;
me.tabIndex = index;
this.switchTab(index);
},
switchTab(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.data.length == 0) {
me.getList(index);
}
},
formatDate(value) {
return dateUtils.formatDate(value);
},
getList(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.status == 'noMore') {
if (me.reload) {
me.reload = false;
uni.stopPullDownRefresh();
}
return;
}
me.$api.post('article/article/index', {tab: tab.id, page: tab.page}).then(res => {
if (me.reload) {
tab.data = [];
me.reload = false;
uni.stopPullDownRefresh();
}
tab.data = tab.data.concat(res.data);
if (res.current_page >= res.last_page) {
tab.status = 'noMore';
} else {
tab.page = res.current_page + 1;
}
}).catch(error => {
});
},
goDetail: function(row) {
uni.navigateTo({
url: '/pages/webview?title=公告详情&url=' + encodeURIComponent('article/article/show?id=' + row.id),
});
}
}
};
</script>
<style>
page {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: center;
background: rgba(249, 249, 249, 1);
}
.header {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 100;
background: #fff;
width: 100vw;
}
.uni-list-controller {
margin-top: 103px;
width: 100vw;
}
.uni-media-list-logo {
width: 140rpx;
height: 140rpx;
}
.uni-media-list-body {
height: auto;
justify-content: space-around;
}
.uni-media-list-text-top {
font-size: 28rpx;
overflow: hidden;
}
.uni-media-list-text-bottom {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 15rpx;
}
.uni-media-list-text-bottom .desc {
margin-bottom: 15rpx;
display: block;
}
.uni-media-list-text-bottom .desc:last-child {
margin-bottom: 0;
}
.tabs {
flex: 1;
flex-direction: column;
overflow: hidden;
background-color: #ffffff;
height: 100vh;
}
.scroll-h {
width: 750rpx;
height: 80rpx;
flex-direction: row;
white-space: nowrap;
align-items: center;
border-bottom: 1px solid #c8c7cc;
}
.line-h {
height: 1rpx;
background-color: #cccccc;
}
.uni-tab-item {
display: inline-block;
/*
padding-left: 70rpx;
padding-right: 70rpx;
*/
text-align: center;
width: 33.33333%;
}
.uni-tab-item-title {
color: #555;
font-size: 30rpx;
height: 80rpx;
line-height: 80rpx;
flex-wrap: nowrap;
white-space: nowrap;
}
.uni-tab-item-title-active {
color: #007AFF;
}
.swiper-box {
flex: 1;
height: 50vh;
}
.swiper-item {
flex: 1;
flex-direction: row;
}
.scroll-v {
flex: 1;
width: 750rpx;
}
.search-controller {
padding: 10rpx;
}
.search-result {
margin-top: 10px;
margin-bottom: 20px;
text-align: center;
}
.search-result-text {
text-align: center;
font-size: 14px;
}
</style>
+313
View File
@@ -0,0 +1,313 @@
<template>
<view>
<view class="header" id="header">
<scroll-view id="tab-bar" class="scroll-h" :scroll-x="true" :show-scrollbar="false">
<view v-for="(tab, index) in tabBars" :key="index" class="uni-tab-item" :id="tab.id" @click="ontabtap(index)">
<text class="uni-tab-item-title" :class="tabIndex == index ? 'uni-tab-item-title-active' : ''">{{tab.name}}</text>
</view>
</scroll-view>
<view class="search-controller">
<uni-search-bar radius="50" placeholder="搜索单号" @confirm="search" />
</view>
<view class="line-h"></view>
</view>
<view class="uni-list uni-list-controller" :style="'margin-top:' + listTop + 'px;'">
<view class="uni-list-cell" hover-class="uni-list-cell-hover" v-for="(row, key) in tabBars[tabIndex].data" :key="key" @click="goDetail(row)">
<view class="uni-media-list">
<view class="uni-media-list-body">
<view class="uni-media-list-text-top">
<text>{{ row.master_sn }}</text>
<text>{{ htmlClear(row.master_status) }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text class="desc">{{ row.master_customer_id_name }}</text>
<text class="desc">{{ row.master_invoice_dt }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text class="desc">预计到货日期{{ row.master_invoice_dt }}</text>
<text class="desc">实发数量{{ row.total_quantity }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text class="desc">收货地址{{ row.master_warehouse_address }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text class="desc">物流公司{{ row.master_freight_logistics_id_name }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text class="desc">物流电话{{ row.master_freight_logistics_phone }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text class="desc">运输单号{{ row.master_freight_sn }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text class="desc">配件吨位(T){{ row.master_freight_part_weight }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text class="desc">发运方式{{ row.master_freight_type_name }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text class="desc">承担运费{{ row.master_freight_customer_money }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text class="desc">物流备注{{ row.master_freight_remark }}</text>
</view>
</view>
</view>
</view>
</view>
<uni-load-more :status="tabBars[tabIndex].status" :icon-size="16" :content-text="tabBars[tabIndex].contentText" />
</view>
</template>
<script>
import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
import {dateUtils} from '@/util.js';
export default {
components: {
uniLoadMore
},
data() {
return {
tabIndex: 0,
listTop: 103,
tabBars: [{
name: '审核中',
id: 'flow.todo',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}, {
name: '已生效',
id: 'flow.done',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}],
reload: false
};
},
onLoad() {
var me = this;
me.getList(0);
},
mounted() {
let me = this;
uni.createSelectorQuery().in(this).select('#header').boundingClientRect(function(e) {
me.listTop = e.height - 1;
}).exec();
},
onPullDownRefresh() {
let me = this;
me.reload = true;
let tab = me.tabBars[me.tabIndex];
tab.page = 1;
tab.status = 'more';
me.getList(me.tabIndex);
},
onReachBottom() {
let me = this;
let tab = me.tabBars[me.tabIndex];
if (tab.status == 'noMore') {
return;
}
tab.status = 'more';
this.getList(me.tabIndex);
},
methods: {
ontabtap(index) {
var me = this;
me.tabIndex = index;
this.switchTab(index);
},
switchTab(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.data.length == 0) {
me.getList(index);
}
},
htmlClear(str) {
// 正则去掉所有的html标记
return str.replace(/<[^>]+>/g, "");
},
formatDate(value) {
return dateUtils.formatDate(value);
},
getList(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.status == 'noMore') {
if (me.reload) {
me.reload = false;
uni.stopPullDownRefresh();
}
return;
}
me.$api.post('stock/delivery/count', {by: tab.id, page: tab.page}).then(res => {
if (me.reload) {
tab.data = [];
me.reload = false;
uni.stopPullDownRefresh();
}
tab.data = tab.data.concat(res.data);
if (res.current_page >= res.last_page) {
tab.status = 'noMore';
} else {
tab.page = res.current_page + 1;
}
}).catch(error => {
});
},
goDetail: function(row) {
uni.navigateTo({
url: '/pages/webview?title=发货详情&url=' + encodeURIComponent('stock/delivery/show?id=' + row.master_id),
});
}
}
};
</script>
<style>
page {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: center;
background: rgba(249, 249, 249, 1);
}
.header {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 100;
background: #fff;
width: 100vw;
}
.uni-list-controller {
margin-top: 103px;
width: 100vw;
}
.uni-media-list-logo {
width: 140rpx;
height: 140rpx;
}
.uni-media-list-body {
height: auto;
justify-content: space-around;
}
.uni-media-list-text-top {
font-size: 28rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.uni-media-list-text-bottom {
display: flex;
flex-direction: row;
justify-content: space-between;
padding-top: 15rpx;
}
.tabs {
flex: 1;
flex-direction: column;
overflow: hidden;
background-color: #ffffff;
height: 100vh;
}
.scroll-h {
width: 750rpx;
height: 80rpx;
flex-direction: row;
white-space: nowrap;
align-items: center;
border-bottom: 1px solid #c8c7cc;
}
.line-h {
height: 1rpx;
background-color: #cccccc;
}
.uni-tab-item {
display: inline-block;
/*
padding-left: 70rpx;
padding-right: 70rpx;
*/
text-align: center;
width: 50%;
}
.uni-tab-item-title {
color: #555;
font-size: 30rpx;
height: 80rpx;
line-height: 80rpx;
flex-wrap: nowrap;
white-space: nowrap;
}
.uni-tab-item-title-active {
color: #007AFF;
}
.swiper-box {
flex: 1;
height: 50vh;
}
.swiper-item {
flex: 1;
flex-direction: row;
}
.scroll-v {
flex: 1;
width: 750rpx;
}
.search-controller {
padding: 10rpx;
}
.search-result {
margin-top: 10px;
margin-bottom: 20px;
text-align: center;
}
.search-result-text {
text-align: center;
font-size: 14px;
}
</style>
+270
View File
@@ -0,0 +1,270 @@
<template>
<view>
<view class="header" id="header">
<scroll-view id="tab-bar" class="scroll-h" :scroll-x="true" :show-scrollbar="false">
<view v-for="(tab, index) in tabBars" :key="index" class="uni-tab-item" :id="tab.id" @click="ontabtap(index)">
<text class="uni-tab-item-title" :class="tabIndex == index ? 'uni-tab-item-title-active' : ''">{{tab.name}}</text>
</view>
</scroll-view>
<view class="search-controller">
<uni-search-bar radius="50" placeholder="搜索单号" @confirm="search" />
</view>
<view class="line-h"></view>
</view>
<view class="uni-list uni-list-controller" :style="'margin-top:' + listTop + 'px;'">
<view class="uni-list-cell" hover-class="uni-list-cell-hover" v-for="(row, key) in tabBars[tabIndex].data" :key="key" @click="goDetail(row)">
<view class="uni-media-list">
<view class="uni-media-list-body">
<view class="uni-media-list-text-top">
<text>{{ row.master_sn }}</text>
<text>{{ row.master_customer_id_name }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text>{{ htmlClear(row.master_status) }}</text>
<text>{{ row.master_created_at }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text>开始日期{{ row.master_start_dt }}</text>
<text>结束日期{{ row.master_end_dt }}</text>
</view>
</view>
</view>
</view>
</view>
<uni-load-more :status="tabBars[tabIndex].status" :icon-size="16" :content-text="tabBars[tabIndex].contentText" />
</view>
</template>
<script>
import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
import {dateUtils} from '@/util.js';
export default {
components: {
uniLoadMore
},
data() {
return {
tabIndex: 0,
listTop: 103,
tabBars: [{
name: '审核中',
id: 'flow.todo',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}, {
name: '已生效',
id: 'flow.done',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}],
reload: false
};
},
onLoad() {
var me = this;
me.getList(0);
},
onPullDownRefresh() {
let me = this;
me.reload = true;
let tab = me.tabBars[me.tabIndex];
tab.page = 1;
tab.status = 'more';
me.getList(me.tabIndex);
},
onReachBottom() {
let me = this;
let tab = me.tabBars[me.tabIndex];
if (tab.status == 'noMore') {
return;
}
tab.status = 'more';
this.getList(me.tabIndex);
},
mounted() {
let me = this;
uni.createSelectorQuery().in(this).select('#header').boundingClientRect(function(e) {
me.listTop = e.height - 1;
}).exec();
},
methods: {
ontabtap(index) {
var me = this;
me.tabIndex = index;
this.switchTab(index);
},
switchTab(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.data.length == 0) {
me.getList(index);
}
},
htmlClear(str) {
// 正则去掉所有的html标记
return str.replace(/<[^>]+>/g, "");
},
formatDate(value) {
return dateUtils.formatDate(value);
},
getList(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.status == 'noMore') {
if (me.reload) {
me.reload = false;
uni.stopPullDownRefresh();
}
return;
}
me.$api.post('promotion/promotion/index', {by: tab.id, page: tab.page}).then(res => {
if (me.reload) {
tab.data = [];
me.reload = false;
uni.stopPullDownRefresh();
}
tab.data = tab.data.concat(res.data);
if (res.current_page >= res.last_page) {
tab.status = 'noMore';
} else {
tab.page = res.current_page + 1;
}
}).catch(error => {
});
},
goDetail: function(row) {
uni.navigateTo({
url: '/pages/webview?title=促销详情&url=' + encodeURIComponent('promotion/promotion/show?id=' + row.master_id),
});
}
}
};
</script>
<style>
page {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: center;
background: rgba(249, 249, 249, 1);
}
.header {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 100;
background: #fff;
width: 100vw;
}
.uni-list-controller {
margin-top: 103px;
width: 100vw;
}
.uni-media-list-logo {
width: 140rpx;
height: 140rpx;
}
.uni-media-list-body {
height: auto;
justify-content: space-around;
}
.uni-media-list-text-top {
display: flex;
font-size: 28rpx;
flex-direction: row;
justify-content: space-between;
padding-bottom: 15rpx;
}
.uni-media-list-text-bottom {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.scroll-h {
width: 750rpx;
height: 80rpx;
flex-direction: row;
white-space: nowrap;
align-items: center;
border-bottom: 1px solid #c8c7cc;
}
.line-h {
height: 1rpx;
background-color: #cccccc;
}
.uni-tab-item {
display: inline-block;
/*
padding-left: 70rpx;
padding-right: 70rpx;
*/
text-align: center;
width: 50%;
}
.uni-tab-item-title {
color: #555;
font-size: 30rpx;
height: 80rpx;
line-height: 80rpx;
flex-wrap: nowrap;
white-space: nowrap;
}
.uni-tab-item-title-active {
color: #007AFF;
}
.scroll-v {
flex: 1;
width: 750rpx;
}
.search-controller {
padding: 10rpx;
}
.search-result {
margin-top: 10px;
margin-bottom: 20px;
text-align: center;
}
.search-result-text {
text-align: center;
font-size: 14px;
}
</style>
+305
View File
@@ -0,0 +1,305 @@
<template>
<view>
<view class="header" id="header">
<uni-nav-bar color="#ffffff" background-color="#007AFF" status-bar="true" left-icon="arrowleft" left-text="返回" :right-text="is_add ? '新增' : ''" @clickLeft="back" @clickRight="add" />
<scroll-view id="tab-bar" class="scroll-h" :scroll-x="true" :show-scrollbar="false">
<view v-for="(tab, index) in tabBars" :key="index" class="uni-tab-item" :id="tab.id" @click="ontabtap(index)">
<text class="uni-tab-item-title" :class="tabIndex == index ? 'uni-tab-item-title-active' : ''">{{tab.name}}</text>
</view>
</scroll-view>
</view>
<view class="uni-list uni-list-controller" :style="'margin-top:' + listTop + 'px;'">
<view v-for="(row, key) in tabBars[tabIndex].data" :key="key">
<view class="uni-media-list">
<view class="uni-media-list-body">
<img :src=" baseURL + '/uploads/' + row.path" style="width:100%;">
<view class="uni-media-list-text">
<view class="uni-media-list-text-top">
<text>{{ row.created_by }}</text>
<text>{{ formatDate(row.created_at) }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text>{{ row.location }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<uni-load-more :status="tabBars[tabIndex].status" :icon-size="16" :content-text="tabBars[tabIndex].contentText" />
</view>
</template>
<script>
import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
import uniNavBar from '@/components/uni-nav-bar/uni-nav-bar.vue'
import {dateUtils} from '@/util.js';
import {baseURL} from '@/api.js';
export default {
components: {
uniLoadMore,
uniNavBar
},
data() {
return {
is_add: false,
promotion_id: 0,
tabIndex: 0,
listTop: 103,
baseURL: baseURL,
tabBars: [{
name: '审核中',
id: '0',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}, {
name: '已审核不合格',
id: '1',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}, {
name: '已审核合格',
id: '2',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}],
reload: false
};
},
onLoad(options) {
var me = this;
me.promotion_id = options.promotion_id;
// 判断谁可以上传资料
var user = uni.getStorageSync('user');
if (user.group_id == 3 || user.id == 1) {
me.is_add = true;
}
me.getList(0);
},
onPullDownRefresh() {
let me = this;
me.reload = true;
let tab = me.tabBars[me.tabIndex];
tab.page = 1;
tab.status = 'more';
me.getList(me.tabIndex);
},
onReachBottom() {
let me = this;
let tab = me.tabBars[me.tabIndex];
if (tab.status == 'noMore') {
return;
}
tab.status = 'more';
this.getList(me.tabIndex);
},
mounted() {
let me = this;
uni.createSelectorQuery().in(this).select('#header').boundingClientRect(function(e) {
me.listTop = e.height - 1;
}).exec();
},
methods: {
back() {
uni.navigateBack();
},
add() {
let me = this;
uni.navigateTo({
url: '/pages/app/promotionMaterial/upload?promotion_id=' + me.promotion_id
});
},
ontabtap(index) {
var me = this;
me.tabIndex = index;
this.switchTab(index);
},
switchTab(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.data.length == 0) {
me.getList(index);
}
},
htmlClear(str) {
// 正则去掉所有的html标记
return str.replace(/<[^>]+>/g, "");
},
formatDate(value) {
return dateUtils.formatDate(value);
},
getList(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.status == 'noMore') {
if (me.reload) {
me.reload = false;
uni.stopPullDownRefresh();
}
return;
}
me.$api.post('promotion/material/index', {by: tab.id, page: tab.page}).then(res => {
if (me.reload) {
tab.data = [];
me.reload = false;
uni.stopPullDownRefresh();
}
tab.data = tab.data.concat(res.data);
if (res.current_page >= res.last_page) {
tab.status = 'noMore';
} else {
tab.page = res.current_page + 1;
}
}).catch(error => {
});
}
}
};
</script>
<style>
page {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: center;
background: rgba(249, 249, 249, 1);
}
.header {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 100;
background: #fff;
width: 100vw;
}
.uni-list-controller {
margin-top: 103px;
background-color: #f1f1f1;
width: 100vw;
}
.uni-media-list {
}
.uni-media-list-logo {
width: 140rpx;
height: 140rpx;
}
.uni-media-list-body {
background-color: #fff;
height: auto;
justify-content: space-around;
border-radius: 10rpx;
}
.uni-media-list-text {
width: calc(100% - 30rpx);
padding: 15rpx;
}
.uni-media-list-text-top {
display: flex;
font-size: 28rpx;
flex-direction: row;
justify-content: space-between;
padding-bottom: 0;
}
.uni-media-list-text-bottom {
display: flex;
flex-direction: row;
justify-content: space-between;
padding-bottom: 15rpx;
}
.scroll-h {
width: 750rpx;
height: 80rpx;
flex-direction: row;
white-space: nowrap;
align-items: center;
border-bottom: 1px solid #c8c7cc;
}
.line-h {
height: 1rpx;
background-color: #cccccc;
}
.uni-tab-item {
display: inline-block;
/*
padding-left: 70rpx;
padding-right: 70rpx;
*/
text-align: center;
width: 33.333333%;
}
.uni-tab-item-title {
color: #555;
font-size: 30rpx;
height: 80rpx;
line-height: 80rpx;
flex-wrap: nowrap;
white-space: nowrap;
}
.uni-tab-item-title-active {
color: #007AFF;
}
.scroll-v {
flex: 1;
width: 750rpx;
}
.search-controller {
padding: 10rpx;
}
.search-result {
margin-top: 10px;
margin-bottom: 20px;
text-align: center;
}
.search-result-text {
text-align: center;
font-size: 14px;
}
</style>
+249
View File
@@ -0,0 +1,249 @@
<template>
<view>
<view class="upload-box">
<view class="uni-form-item">
<view class="title">位置信息</view>
<input class="uni-input" disabled="disabled" v-model="location" />
</view>
<view class="uni-form-item">
<view class="title">门店名称</view>
<input class="uni-input" placeholder="请输入门店名称" v-model="name" />
</view>
<view class="uni-form-item" style="border:0;">
<img-upload :imgArr="images" imgCount="3" ref="imgUpload" />
</view>
</view>
<view class="notice-box">
<uni-notice-bar :show-close="true" :single="true" :text="'页面将在' + second + '秒后失效'" />
</view>
<view class="submit-box">
<button type="primary" @click="submit">提交</button>
<button type="info" @click="refresh">刷新</button>
</view>
</view>
</template>
<style>
page {
background-color: #fff;
}
.submit-box {
display: flex;
margin-right: 15rpx;
}
.submit-box uni-button {
margin-left: 15rpx;
flex-direction: row;
width: 100%;
justify-content: space-between;
}
.notice-box {
padding: 0 15rpx;
}
.upload-box {
padding-left: 15rpx;
}
.uni-form-item {
border-bottom: 1px solid #F1F1F1;
padding-top: 20rpx;
padding-bottom: 20rpx;
}
.title {
color: #888;
}
.uni-input {
color: #222;
padding: 4px 12px 6px 12px;
line-height: 1.8;
}
</style>
<script>
var wx = require('weixin');
import uniNoticeBar from '@/components/uni-notice-bar/uni-notice-bar.vue'
import imgUpload from '@/components/my-components/uImgUpload.vue';
var InterTimer = null;
export default {
components: {
imgUpload,
uniNoticeBar
},
data() {
return {
name: '',
location: '位置获取中...',
promotion_id: 0,
latitude: 0,
longitude: 0,
images: [],
second: 180,
}
},
onLoad(options) {
var me = this;
me.promotion_id = options.promotion_id;
},
methods: {
getLocation() {
let me = this;
wx.getLocation({
type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'
success: function(res) {
console.log('微信定位成功');
me.latitude = res.latitude;
me.longitude = res.longitude;
me.$api.post('wap/wechat/mapGeocoder', {
location: res.latitude + ',' + res.longitude
})
.then(ret => {
if (ret.status == 0) {
me.location = ret.result.address;
}
});
},
fail: function(res) {
console.log(res);
}
});
},
setRemainTime() {
let me = this;
if (me.second > 0) {
me.second = me.second - 1;
} else {
window.clearInterval(InterTimer);
}
},
refresh() {
let me = this;
me.name = '';
me.location = '';
me.latitude = 0;
me.longitude = 0;
me.images = [];
me.second = 180;
me.$refs.imgUpload.imgArray = [];
me.getLocation();
},
submit() {
let me = this;
if (me.second <= 0) {
uni.showModal({
content: "无法提交,表单已超时",
confirmText: "确定",
showCancel: false
});
return;
}
if (me.name == '') {
uni.showModal({
content: "门店信息不能为空",
confirmText: "确定",
showCancel: false
});
return;
}
if (me.location == '') {
uni.showModal({
content: "位置信息不能为空",
confirmText: "确定",
showCancel: false
});
return;
}
if (me.latitude == 0 || me.longitude == 0) {
uni.showModal({
content: "经纬度不能为空",
confirmText: "确定",
showCancel: false
});
return;
}
if (me.promotion_id == 0) {
uni.showModal({
content: "促销编号不能为空",
confirmText: "确定",
showCancel: false
});
return;
}
let files = me.$refs.imgUpload.imgArray.map((uri, index) => {
return {
name: "images[" + index + "]",
uri: uri
}
});
uni.showLoading({
mask: true,
title: '数据处理中...'
});
uni.uploadFile({
url: me.$api.baseURL + "/promotion/material/store",
files: files,
formData: {
name: me.name,
location: me.location,
lat: me.latitude,
lng: me.longitude,
promotion_id: me.promotion_id,
},
header: {
'x-auth-token': uni.getStorageSync('token')
},
success: function(res) {
uni.hideLoading();
let ret = JSON.parse(res.data);
if (ret.status) {
uni.redirectTo({
url: '/pages/app/promotionMaterial/index?promotion_id=' + me.promotion_id
});
} else {
uni.showModal({
content: ret.data,
confirmText: "确定",
showCancel: false
});
}
}
});
}
},
mounted() {
var me = this;
InterTimer = window.setInterval(me.setRemainTime, 1000);
me.$api.post('wap/wechat/jsConfig', {
url: window.location.href
}).then(ret => {
wx.config(ret);
wx.ready(function() {
me.getLocation();
});
wx.error(function(res) {
console.log(res.errMsg);
});
}).catch(error => {
console.log(error);
});
}
}
</script>
+274
View File
@@ -0,0 +1,274 @@
<template>
<view>
<view class="header" id="header">
<scroll-view id="tab-bar" class="scroll-h" :scroll-x="true" :show-scrollbar="false">
<view v-for="(tab, index) in tabBars" :key="index" class="uni-tab-item" :id="tab.id" @click="ontabtap(index)">
<text class="uni-tab-item-title" :class="tabIndex == index ? 'uni-tab-item-title-active' : ''">{{tab.name}}</text>
</view>
</scroll-view>
<view class="search-controller">
<uni-search-bar radius="50" placeholder="搜索单号" @confirm="search" />
</view>
<view class="line-h"></view>
</view>
<view class="uni-list uni-list-controller" :style="'margin-top:' + listTop + 'px;'">
<view class="uni-list-cell" hover-class="uni-list-cell-hover" v-for="(row, key) in tabBars[tabIndex].data" :key="key" @click="goDetail(row)">
<view class="uni-media-list">
<view class="uni-media-list-body">
<view class="uni-media-list-text-top">
<text>{{ row.master_sn }}</text>
<text>{{ row.master_customer_id_name }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text class="desc">{{ htmlClear(row.master_status) }}</text>
<text class="desc">{{ row.master_created_at }}</text>
</view>
</view>
</view>
</view>
</view>
<uni-load-more :status="tabBars[tabIndex].status" :icon-size="16" :content-text="tabBars[tabIndex].contentText" />
</view>
</template>
<script>
import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
import {dateUtils} from '@/util.js';
export default {
components: {
uniLoadMore
},
data() {
return {
tabIndex: 0,
listTop: 103,
tabBars: [{
name: '审核中',
id: 'flow.todo',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}, {
name: '已生效',
id: 'flow.done',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}],
reload: false
};
},
onLoad() {
var me = this;
me.getList(0);
},
onPullDownRefresh() {
let me = this;
me.reload = true;
let tab = me.tabBars[me.tabIndex];
tab.page = 1;
tab.status = 'more';
me.getList(me.tabIndex);
},
onReachBottom() {
let me = this;
let tab = me.tabBars[me.tabIndex];
if (tab.status == 'noMore') {
return;
}
tab.status = 'more';
this.getList(me.tabIndex);
},
mounted() {
let me = this;
uni.createSelectorQuery().in(this).select('#header').boundingClientRect(function(e) {
me.listTop = e.height - 1;
}).exec();
},
methods: {
ontabtap(index) {
var me = this;
me.tabIndex = index;
this.switchTab(index);
},
switchTab(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.data.length == 0) {
me.getList(index);
}
},
htmlClear(str) {
// 正则去掉所有的html标记
return str.replace(/<[^>]+>/g, "");
},
formatDate(value) {
return dateUtils.formatDate(value);
},
getList(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.status == 'noMore') {
if (me.reload) {
me.reload = false;
uni.stopPullDownRefresh();
}
return;
}
me.$api.post('order/order/count', {by: tab.id, page: tab.page}).then(res => {
if (me.reload) {
tab.data = [];
me.reload = false;
uni.stopPullDownRefresh();
}
tab.data = tab.data.concat(res.data);
if (res.current_page >= res.last_page) {
tab.status = 'noMore';
} else {
tab.page = res.current_page + 1;
}
}).catch(error => {
});
},
goDetail: function(row) {
uni.navigateTo({
url: '/pages/webview?title=销售订单详情&url=' + encodeURIComponent('order/order/show?id=' + row.master_id),
});
}
}
};
</script>
<style>
page {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: center;
background: rgba(249, 249, 249, 1);
}
.header {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 100;
background: #fff;
width: 100vw;
}
.uni-list-controller {
margin-top: 103px;
width: 100vw;
}
.uni-media-list-logo {
width: 140rpx;
height: 140rpx;
}
.uni-media-list-body {
height: auto;
justify-content: space-around;
}
.uni-media-list-text-top {
display: flex;
font-size: 28rpx;
flex-direction: row;
justify-content: space-between;
}
.uni-media-list-text-bottom {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-top: 15rpx;
}
.uni-media-list-text-bottom .desc {
margin-bottom: 15rpx;
display: block;
}
.uni-media-list-text-bottom .desc:last-child {
margin-bottom: 0;
}
.scroll-h {
width: 750rpx;
height: 80rpx;
flex-direction: row;
white-space: nowrap;
align-items: center;
border-bottom: 1px solid #c8c7cc;
}
.line-h {
height: 1rpx;
background-color: #cccccc;
}
.uni-tab-item {
display: inline-block;
/*
padding-left: 70rpx;
padding-right: 70rpx;
*/
text-align: center;
width: 50%;
}
.uni-tab-item-title {
color: #555;
font-size: 30rpx;
height: 80rpx;
line-height: 80rpx;
flex-wrap: nowrap;
white-space: nowrap;
}
.uni-tab-item-title-active {
color: #007AFF;
}
.scroll-v {
flex: 1;
width: 750rpx;
}
.search-controller {
padding: 10rpx;
}
.search-result {
margin-top: 10px;
margin-bottom: 20px;
text-align: center;
}
.search-result-text {
text-align: center;
font-size: 14px;
}
</style>
+295
View File
@@ -0,0 +1,295 @@
<template>
<view>
<view class="header" id="header">
<scroll-view id="tab-bar" class="scroll-h" :scroll-x="true" :show-scrollbar="false">
<view v-for="(tab, index) in tabBars" :key="index" class="uni-tab-item" :id="tab.id" @click="ontabtap(index)">
<text class="uni-tab-item-title" :class="tabIndex == index ? 'uni-tab-item-title-active' : ''">{{tab.name}}</text>
</view>
</scroll-view>
<view class="search-controller">
<uni-search-bar radius="50" placeholder="搜索主题或文号" @confirm="search" />
</view>
<view class="line-h"></view>
</view>
<view class="uni-list uni-list-controller" :style="'margin-top:' + listTop + 'px;'">
<view class="uni-list-cell" hover-class="uni-list-cell-hover" v-for="(row, key) in tabBars[tabIndex].data" :key="key" @click="goDetail(row)">
<view class="uni-media-list">
<view class="uni-media-list-body">
<view class="uni-media-list-text-top">{{ row.title }}</view>
<view class="uni-media-list-text-bottom">
<text class="desc">{{ row.name }}</text>
<text class="desc">{{ row.step.name }}</text>
</view>
</view>
</view>
</view>
</view>
<uni-load-more :status="tabBars[tabIndex].status" :icon-size="16" :content-text="tabBars[tabIndex].contentText" />
</view>
</template>
<script>
import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
export default {
components: {
uniLoadMore
},
data() {
return {
tabIndex: 0,
listTop: 103,
tabBars: [{
name: '待办中',
id: 'todo',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}, {
name: '已办理',
id: 'trans',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}, {
name: '已结束',
id: 'done',
page: 1,
data: [],
status: 'more',
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
}],
reload: false
};
},
onLoad() {
var me = this;
me.getList(0);
},
mounted() {
let me = this;
uni.createSelectorQuery().in(this).select('#header').boundingClientRect(function(e) {
me.listTop = e.height - 1;
}).exec();
},
onPullDownRefresh() {
let me = this;
me.reload = true;
let tab = me.tabBars[me.tabIndex];
tab.page = 1;
tab.status = 'more';
me.getList(me.tabIndex);
},
onReachBottom() {
let me = this;
let tab = me.tabBars[me.tabIndex];
if (tab.status == 'noMore') {
return;
}
tab.status = 'more';
this.getList(me.tabIndex);
},
methods: {
ontabtap(index) {
var me = this;
me.tabIndex = index;
this.switchTab(index);
},
switchTab(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.data.length == 0) {
me.getList(index);
}
},
formatDate(value) {
return dateUtils.formatDate(value);
},
getList(index) {
var me = this;
let tab = me.tabBars[index];
if (tab.status == 'noMore') {
if (me.reload) {
me.reload = false;
uni.stopPullDownRefresh();
}
return;
}
me.$api.post('workflow/workflow/index', {option: tab.id, page: tab.page}).then(res => {
if (me.reload) {
tab.data = [];
me.reload = false;
uni.stopPullDownRefresh();
}
tab.data = tab.data.concat(res.data);
if (res.current_page >= res.last_page) {
tab.status = 'noMore';
} else {
tab.page = res.current_page + 1;
}
}).catch(error => {
});
},
goDetail: function(row) {
uni.navigateTo({
url: '/pages/webview?title=流程详情&url=' + encodeURIComponent('workflow/workflow/edit?process_id=' + row.process_id),
});
}
}
};
</script>
<style>
page {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: center;
background: rgba(249, 249, 249, 1);
}
.header {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 100;
background: #fff;
width: 100vw;
}
.uni-list-controller {
width: 100vw;
}
.uni-media-list-logo {
width: 140rpx;
height: 140rpx;
}
.uni-media-list-body {
height: auto;
justify-content: space-around;
}
.uni-media-list-text-top {
font-size: 28rpx;
overflow: hidden;
}
.uni-media-list-text-bottom {
/*
display: flex;
flex-direction: row;
justify-content: space-between;
*/
margin-top: 15rpx;
}
.uni-media-list-text-bottom .desc {
margin-bottom: 15rpx;
display: block;
}
.uni-media-list-text-bottom .desc:last-child {
margin-bottom: 0;
}
.tabs {
flex: 1;
flex-direction: column;
overflow: hidden;
background-color: #ffffff;
height: 100vh;
}
.scroll-h {
width: 750rpx;
height: 80rpx;
flex-direction: row;
white-space: nowrap;
align-items: center;
border-bottom: 1px solid #c8c7cc;
}
.line-h {
height: 1rpx;
background-color: #cccccc;
}
.uni-tab-item {
display: inline-block;
/*
padding-left: 70rpx;
padding-right: 70rpx;
*/
text-align: center;
width: 33.33333%;
}
.uni-tab-item-title {
color: #555;
font-size: 30rpx;
height: 80rpx;
line-height: 80rpx;
flex-wrap: nowrap;
white-space: nowrap;
}
.uni-tab-item-title-active {
color: #007AFF;
}
.swiper-box {
flex: 1;
height: 50vh;
}
.swiper-item {
flex: 1;
flex-direction: row;
}
.scroll-v {
flex: 1;
width: 750rpx;
}
.search-controller {
padding: 10rpx;
}
.search-result {
margin-top: 10px;
margin-bottom: 20px;
text-align: center;
}
.search-result-text {
text-align: center;
font-size: 14px;
}
</style>
+409
View File
@@ -0,0 +1,409 @@
<template>
<view class="tabs">
<view class="header">
<scroll-view id="tab-bar" class="scroll-h" :scroll-x="true" :show-scrollbar="false">
<view v-for="(tab, index) in tabBars" :key="index" class="uni-tab-item" :id="tab.id" :data-current="index" @click="ontabtap">
<text class="uni-tab-item-title" :class="tabIndex == index ? 'uni-tab-item-title-active' : ''">{{tab.name}}</text>
</view>
</scroll-view>
<view class="search-controller">
<uni-search-bar radius="50" placeholder="搜索主题或文号" @confirm="search" />
</view>
</view>
<view class="line-h"></view>
<swiper :current="tabIndex" class="swiper-box" style="flex:1;" :duration="300" @change="ontabchange">
<swiper-item class="swiper-item" v-for="(tab, index1) in newsList" :key="index1">
<!-- #ifndef APP-NVUE -->
<scroll-view class="scroll-v list" :show-scrollbar="true" refresher-enabled="true" enableBackToTop="true" scroll-y @scrolltolower="loadMore(index1)">
<view v-for="(newsitem, index2) in tab.data" :key="index2">
<media-item :options="newsitem" @click="goDetail(newsitem)"></media-item>
</view>
<view class="loading-more" v-if="tab.isLoading">
<text class="loading-more-text">{{tab.loadingText}}</text>
</view>
</scroll-view>
<!-- #endif -->
</swiper-item>
</swiper>
</view>
</template>
<script>
import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
import mediaItem from '@/pages/app/workflow/item.nvue';
import {dateUtils} from '@/util.js';
export default {
components: {
uniLoadMore,
mediaItem
},
data() {
return {
newsList: [],
cacheTab: [],
tabIndex: 0,
tabBars: [{
name: '待办中',
id: 'todo'
}, {
name: '已办理',
id: 'trans'
}, {
name: '已结束',
id: 'done'
}],
page: 1,
scrollInto: "",
showTips: false,
navigateFlag: false,
pulling: false,
refreshIcon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAB5QTFRFcHBw3Nzct7e39vb2ycnJioqK7e3tpqam29vb////D8oK7wAAAAp0Uk5T////////////ALLMLM8AAABxSURBVHja7JVBDoAgDASrjqj//7CJBi90iyYeOHTPMwmFZrHjYyyFYYUy1bwUZqtJIYVxhf1a6u0R7iUvWsCcrEtwJHp8MwMdvh2amHduiZD3rpWId9+BgPd7Cc2LIkPyqvlQvKxKBJ//Qwq/CacAAwDUv0a0YuKhzgAAAABJRU5ErkJggg=="
};
},
onLoad() {
var me = this;
me.tabBars.forEach((tabBar) => {
me.newsList.push({
data: [],
page: 1,
isLoading: false,
isComplete: false,
refreshText: "",
loadingText: '加载更多...'
});
});
this.getList(0);
},
methods: {
loadMore(e) {
this.getList(this.tabIndex);
},
ontabtap(e) {
var me = this;
let index = e.target.dataset.current || e.currentTarget.dataset.current;
// this.switchTab(index);
me.tabIndex = index;
//me.scrollInto = me.tabBars[index].id;
},
ontabchange(e) {
let index = e.target.current || e.detail.current;
this.switchTab(index);
},
switchTab(index) {
var me = this;
me.getList(index);
console.log(22);
/*
// 缓存 tabId
if (this.newsList[this.tabIndex].data.length > MAX_CACHE_DATA) {
let isExist = this.cacheTab.indexOf(this.tabIndex);
if (isExist < 0) {
this.cacheTab.push(this.tabIndex);
//console.log("cache index:: " + this.tabIndex);
}
}
*/
me.tabIndex = index;
me.scrollInto = me.tabBars[index].id;
/*
// 释放 tabId
if (this.cacheTab.length > MAX_CACHE_PAGE) {
let cacheIndex = this.cacheTab[0];
this.clearTabData(cacheIndex);
this.cacheTab.splice(0, 1);
//console.log("remove cache index:: " + cacheIndex);
}
*/
},
clearTabData(e) {
this.newsList[e].data.length = 0;
this.newsList[e].loadingText = "加载更多...";
},
refreshData() {
},
onrefresh(e) {
var tab = this.newsList[this.tabIndex];
if (!tab.refreshFlag) {
return;
}
tab.refreshing = true;
tab.refreshText = "正在刷新...";
setTimeout(() => {
this.refreshData();
this.pulling = true;
tab.refreshing = false;
tab.refreshFlag = false;
tab.refreshText = "已刷新";
setTimeout(() => { // TODO fix ios和Android 动画时间相反问题
this.pulling = false;
}, 500);
}, 2000);
},
onpullingdown(e) {
var tab = this.newsList[this.tabIndex];
if (tab.refreshing || this.pulling) {
return;
}
if (Math.abs(e.pullingDistance) > Math.abs(e.viewHeight)) {
tab.refreshFlag = true;
tab.refreshText = "释放立即刷新";
} else {
tab.refreshFlag = false;
tab.refreshText = "下拉可以刷新";
}
},
formatDate(value) {
return dateUtils.formatDate(value);
},
getList(index) {
var me = this;
let tab = me.newsList[index];
let option = me.tabBars[index].id;
if (tab.isComplete) {
return;
}
me.$api.post('workflow/workflow/index', {option: option, page: tab.page}).then(res => {
tab.data = tab.data.concat(res.data);
uni.stopPullDownRefresh();
if (res.current_page >= res.last_page) {
tab.isComplete = true;
} else {
tab.page = res.current_page + 1;
}
}).catch(error => {
});
},
goDetail: function(e) {
// if (!/前|刚刚/.test(e.published_at)) {
// e.published_at = dateUtils.format(e.published_at);
// }
let detail = {
author_name: e.author_name,
cover: e.cover,
id: e.id,
post_id: e.post_id,
published_at: e.published_at,
title: e.title
};
uni.navigateTo({
url: '../list2detail-detail/list2detail-detail?detailDate=' + encodeURIComponent(JSON.stringify(detail))
});
},
setTime: function(items) {
var newItems = [];
items.forEach(e => {
newItems.push({
author_name: e.author_name,
cover: e.cover,
id: e.id,
post_id: e.post_id,
published_at: dateUtils.format(e.published_at),
title: e.title
});
});
return newItems;
}
}
};
</script>
<style>
.uni-media-list-logo {
width: 140rpx;
height: 140rpx;
}
.uni-media-list-body {
height: auto;
justify-content: space-around;
}
.uni-media-list-text-top {
height: 50rpx;
font-size: 28rpx;
overflow: hidden;
}
.uni-media-list-text-bottom {
/*
display: flex;
flex-direction: row;
justify-content: space-between;
*/
}
.uni-media-list-text-bottom .desc {
margin-bottom: 15rpx;
display: block;
}
.uni-media-list-text-bottom .desc:last-child {
margin-bottom: 0;
}
.tabs {
flex: 1;
flex-direction: column;
overflow: hidden;
background-color: #ffffff;
height: 100vh;
}
.scroll-h {
width: 750rpx;
height: 80rpx;
flex-direction: row;
white-space: nowrap;
align-items: center;
border-bottom: 1px solid #c8c7cc;
}
.line-h {
height: 1rpx;
background-color: #cccccc;
}
.uni-tab-item {
display: inline-block;
/*
padding-left: 70rpx;
padding-right: 70rpx;
*/
text-align: center;
width: 33.33333%;
}
.uni-tab-item-title {
color: #555;
font-size: 30rpx;
height: 80rpx;
line-height: 80rpx;
flex-wrap: nowrap;
white-space: nowrap;
}
.uni-tab-item-title-active {
color: #007AFF;
}
.swiper-box {
flex: 1;
height: 50vh;
}
.swiper-item {
flex: 1;
flex-direction: row;
}
.scroll-v {
flex: 1;
/* #ifndef MP-ALIPAY */
flex-direction: column;
/* #endif */
width: 750rpx;
}
.update-tips {
position: absolute;
left: 0;
top: 41px;
right: 0;
padding-top: 5px;
padding-bottom: 5px;
background-color: #FDDD9B;
align-items: center;
justify-content: center;
text-align: center;
}
.update-tips-text {
font-size: 14px;
color: #ffffff;
}
.refresh {
width: 750rpx;
height: 64px;
justify-content: center;
}
.refresh-view {
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
justify-content: center;
}
.refresh-icon {
width: 30px;
height: 30px;
transition-duration: .5s;
transition-property: transform;
transform: rotate(0deg);
transform-origin: 15px 15px;
}
.refresh-icon-active {
transform: rotate(180deg);
}
.loading-icon {
width: 20px;
height: 20px;
margin-right: 5px;
color: #999999;
}
.loading-text {
margin-left: 2px;
font-size: 16px;
color: #999999;
}
.loading-more {
align-items: center;
justify-content: center;
padding-top: 10px;
padding-bottom: 10px;
text-align: center;
}
.loading-more-text {
font-size: 28rpx;
color: #999;
}
.search-controller {
padding: 10rpx;
}
.search-result {
margin-top: 10px;
margin-bottom: 20px;
text-align: center;
}
.search-result-text {
text-align: center;
font-size: 14px;
}
</style>
+207
View File
@@ -0,0 +1,207 @@
<template>
<!-- remove list-cell layer fix android 4.x overflow limit error: 28 layers! -->
<!-- <view class="list-cell view" @click="click"></view> -->
<view class="media-item view" hover-class="media-item-hover" v-if="options.title" @click="click">
<!-- <view class="view" :style="options.article_type === 2 ? 'flex-direction: row';" :class="{'media-image-right': options.article_type === 2, 'media-image-left': options.article_type === 1}"> -->
<!-- TODO 在支付宝小程序下 需要用 style 覆盖标签的默认样式 -->
<view class="view" :style="{flexDirection: (options.article_type === 1 || options.article_type === 2)?(options.article_type === 2 ?'row':'row-reverse'):'column' }">
<text class="media-title" :class="{'media-title2': options.article_type === 1 || options.article_type === 2}">{{options.title}}</text>
<view v-if="options.image_list || options.image_url" class="image-section flex-row" :class="{'image-section-right': options.article_type === 2, 'image-section-left': options.article_type === 1}"
:style="{flexDirection: 'row' }">
<image class="image-list1" :class="{'image-list2': options.article_type === 1 || options.article_type === 2}" v-if="options.image_url"
:src="options.image_url"></image>
<image class="image-list3" v-if="options.image_list" :src="source.url" v-for="(source, i) in options.image_list"
:key="i" />
</view>
</view>
<view class="media-foot flex-row" style="flex-direction: row;">
<view class="media-info flex-row" style="flex-direction: row;">
<text class="info-text">{{options.source}}</text>
<text class="info-text">{{options.comment_count}}条评论</text>
<text class="info-text">{{options.datetime}}</text>
</view>
<!--
<view class="max-close-view" @click.stop="close">
<view class="close-l close-h"></view>
<view class="close-l close-v"></view>
</view>
-->
</view>
<view class="media-item-line" style="position: absolute;"></view>
</view>
</template>
<script>
export default {
props: {
options: {
type: Object,
default: function(e) {
return {}
}
}
},
methods: {
click() {
this.$emit('click');
},
close(e) {
this.$emit('close');
}
}
}
</script>
<style>
.view {
flex-direction: column;
}
.flex-row {
flex-direction: row;
}
.flex-col {
flex-direction: column;
}
.list-cell {
width: 750rpx;
padding: 0 30rpx;
}
.uni-list-cell-hover {
background-color: #eeeeee;
}
.media-item {
position: relative;
flex: 1;
flex-direction: column;
/* border-bottom-width: 1rpx;
border-bottom-style: solid;
border-bottom-color: #ebebeb; */
padding: 20rpx 30rpx 21rpx 30rpx;
}
.media-item-hover{
background-color: #eee;
}
.media-item-line {
position: absolute;
left: 30rpx;
right: 30rpx;
bottom: 0;
height: 1rpx;
background-color: #ebebeb;
}
.media-image-right {
flex-direction: row;
}
.media-image-left {
flex-direction: row-reverse;
}
.media-title {
flex: 1;
}
.media-title {
lines: 3;
text-overflow: ellipsis;
font-size: 30rpx;
color: #555555;
}
.media-title2 {
flex: 1;
margin-top: 6rpx;
line-height: 40rpx;
}
.image-section {
margin-top: 20rpx;
flex-direction: row;
justify-content: space-between;
}
.image-section-right {
margin-top: 0rpx;
margin-left: 10rpx;
width: 225rpx;
height: 146rpx;
}
.image-section-left {
margin-top: 0rpx;
margin-right: 10rpx;
width: 225rpx;
height: 146rpx;
}
.image-list1 {
width: 690rpx;
height: 481rpx;
}
.image-list2 {
width: 225rpx;
height: 146rpx;
}
.image-list3 {
width: 225rpx;
height: 146rpx;
}
.media-info {
flex-direction: row;
align-items: center;
}
.info-text {
margin-right: 20rpx;
color: #999999;
font-size: 24rpx;
}
.media-foot {
margin-top: 25rpx;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.max-close-view {
position: relative;
align-items: center;
flex-direction: row;
width: 40rpx;
height: 30rpx;
line-height: 30rpx;
border-width: 1rpx;
border-style: solid;
border-color: #aaaaaa;
border-radius: 4px;
justify-content: center;
text-align: center;
}
.close-l {
position: absolute;
width: 18rpx;
height: 1rpx;
background-color: #aaaaaa;
}
.close-h {
transform: rotate(45deg);
}
.close-v {
transform: rotate(-45deg);
}
</style>
+56
View File
@@ -0,0 +1,56 @@
<template>
<view class="page_index">
<view class="head">
<view class="head_inner_title">爱客办公</view>
<view class="head_inner_description">Gdoo Office</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {}
},
onLoad: function() {
var me = this;
me.$api.authorize();
},
methods: {
}
}
</script>
<style>
page {
height: auto;
min-height: 100%;
background-color: #f5f6f8;
font-size: 14px;
}
</style>
<style lang="scss" scoped>
.page_index {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
.head {
position: relative;
transform: translateY(-50%);
.head_inner_title {
text-align: center;
font-size: 50rpx;
color: #007aff;
display: block;
}
.head_inner_description {
margin-top: 5rpx;
text-align: center;
font-size: 20rpx;
color: #666;
display: block;
}
}
</style>
+215
View File
@@ -0,0 +1,215 @@
<template>
<view class="page_login">
<!-- 头部logo -->
<view class="head">
<view class="head_inner_title">爱客办公</view>
<view class="head_inner_description">Gdoo Office</view>
</view>
<!-- 登录form -->
<view class="login_form">
<view class="input">
<view class="img">
<span class="iconfont icon-icon_signal"></span>
</view>
<input type="text" v-model="username" placeholder="请输入账号">
</view>
<view class="line" />
<view class="input">
<view class="img">
<span class="iconfont icon-icon_shield"></span>
</view>
<input type="password" v-model="password" placeholder="请输入密码">
</view>
</view>
<!-- 登录提交 -->
<button class="submit" type="primary" @tap="login">登录</button>
<view class="quick_login_line">
<text class="text">爱客办公</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
username: '',
password: ''
}
},
methods: {
login() {
var me = this;
if (me.username == '') {
uni.showToast({
title: '帐号不能为空。'
});
return;
}
if (me.password == '') {
uni.showToast({
title: '密码不能为空。'
});
return;
}
me.$api.post('wap/auth/login', {username: me.username, password: me.password}).then(res => {
if (res.status) {
uni.setStorageSync('access', res.data.access);
uni.setStorageSync('token', res.data.token);
uni.setStorageSync('user', res.data.user);
uni.switchTab({
url: '/pages/tabbar/notice'
});
} else {
uni.showToast({
title: res.data
});
}
}).catch(res => {
console.log(res);
});
}
}
}
</script>
<style>
page {
height: auto;
min-height: 100%;
background-color: #f5f6f8;
font-size: 14px;
}
</style>
<style lang="scss" scoped>
$logo-padding: 100rpx;
$form-border-color: rgba(214, 214, 214, 1);
$text-color: #B6B6B6;
.page_login {
padding: 10rpx;
}
.head {
/*
display: flex;
align-items: center;
justify-content: center;
*/
text-align: center;
padding-top: $logo-padding;
padding-bottom: $logo-padding;
.head_inner_title {
text-align: center;
font-size: 50rpx;
color: #007aff;
}
.head_inner_description {
margin-top: 5rpx;
text-align: center;
font-size: 20rpx;
color: #666;
}
.head_bg {
border: 1px solid #8f8f8f;
border-radius: 50rpx;
width: 100rpx;
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
.head_inner_bg {
border-radius: 40rpx;
width: 80rpx;
height: 80rpx;
line-height: 80rpx;
font-size: 30rpx;
display: flex;
background-color: #f8f8f8;
align-items: flex-end;
justify-content: center;
overflow: hidden;
}
}
}
.login_form {
display: flex;
margin: 40rpx;
flex-direction: column;
align-items: center;
justify-content: center;
border: 1px solid $form-border-color;
border-radius: 10rpx;
background-color: #fff;
.line {
width: 100%;
height: 1px;
background-color: $form-border-color;
}
.input {
width: 100%;
max-height: 45px;
display: flex;
padding: 3rpx;
flex-direction: row;
align-items: center;
justify-content: center;
.img {
min-width: 40px;
min-height: 40px;
margin: 5px;
display: flex;
align-items: center;
justify-content: center;
.iconfont {
font-size: 45rpx;
color: #999;
}
}
input {
outline: none;
height: 30px;
width: 100%;
&:focus {
outline: none;
}
}
}
}
.submit {
margin-top: 30px;
margin-left: 20px;
margin-right: 20px;
color: white;
}
.quick_login_line {
/*
margin-top: 40px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
*/
position: absolute;
bottom: 30rpx;
left: 50%;
transform: translate(-50%, 0);
.text {
text-align: center;
font-size: 13px;
color: #aaa;
margin: 2px;
}
}
</style>
+224
View File
@@ -0,0 +1,224 @@
<template>
<view class="page_login">
<!-- 头部logo -->
<view class="head">
<view class="head_inner_title">爱客办公</view>
<view class="head_inner_description">Gdoo Office</view>
</view>
<!-- 登录form -->
<view class="login_form">
<view class="input">
<view class="img">
<span class="iconfont icon-icon_signal"></span>
</view>
<input type="text" v-model="username" placeholder="请输入账号">
</view>
<view class="line" />
<view class="input">
<view class="img">
<span class="iconfont icon-icon_shield"></span>
</view>
<input type="password" v-model="password" placeholder="请输入密码">
</view>
</view>
<!-- 登录提交 -->
<button class="submit" type="primary" @tap="register">绑定</button>
<view class="quick_login_line">
<text class="text">爱客ERP</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
username: '',
password: ''
}
},
methods: {
register() {
var me = this;
var openid = uni.getStorageSync('openid');
if (openid == '') {
uni.showToast({
title: 'Openid不能为空。'
});
return;
}
if (me.username == '') {
uni.showToast({
title: '帐号不能为空。'
});
return;
}
if (me.password == '') {
uni.showToast({
title: '密码不能为空。'
});
return;
}
me.$api.post('wap/wechat/login', {openid: openid, username: me.username, password: me.password}).then(res => {
if (res.status) {
uni.setStorageSync('access', res.data.access);
uni.setStorageSync('token', res.data.token);
uni.setStorageSync('user', res.data.user);
uni.switchTab({
url: '/pages/tabbar/notice'
});
} else {
uni.showToast({
title: res.data
});
}
}).catch(res => {
console.log(res);
});
}
}
}
</script>
<style>
page {
height: auto;
min-height: 100%;
background-color: #f5f6f8;
font-size: 14px;
}
</style>
<style lang="scss" scoped>
$logo-padding: 100rpx;
$form-border-color: rgba(214, 214, 214, 1);
$text-color: #B6B6B6;
.page_login {
padding: 10rpx;
}
.head {
/*
display: flex;
align-items: center;
justify-content: center;
*/
text-align: center;
padding-top: $logo-padding;
padding-bottom: $logo-padding;
.head_inner_title {
text-align: center;
font-size: 50rpx;
color: #007aff;
}
.head_inner_description {
margin-top: 5rpx;
text-align: center;
font-size: 20rpx;
color: #666;
}
.head_bg {
border: 1px solid #8f8f8f;
border-radius: 50rpx;
width: 100rpx;
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
.head_inner_bg {
border-radius: 40rpx;
width: 80rpx;
height: 80rpx;
line-height: 80rpx;
font-size: 30rpx;
display: flex;
background-color: #f8f8f8;
align-items: flex-end;
justify-content: center;
overflow: hidden;
}
}
}
.login_form {
display: flex;
margin: 40rpx;
flex-direction: column;
align-items: center;
justify-content: center;
border: 1px solid $form-border-color;
border-radius: 10rpx;
background-color: #fff;
.line {
width: 100%;
height: 1px;
background-color: $form-border-color;
}
.input {
width: 100%;
max-height: 45px;
display: flex;
padding: 3rpx;
flex-direction: row;
align-items: center;
justify-content: center;
.img {
min-width: 40px;
min-height: 40px;
margin: 5px;
display: flex;
align-items: center;
justify-content: center;
.iconfont {
font-size: 45rpx;
color: #999;
}
}
input {
outline: none;
height: 30px;
width: 100%;
&:focus {
outline: none;
}
}
}
}
.submit {
margin-top: 30px;
margin-left: 20px;
margin-right: 20px;
color: white;
}
.quick_login_line {
/*
margin-top: 40px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
*/
position: absolute;
bottom: 30rpx;
left: 50%;
transform: translate(-50%, 0);
.text {
text-align: center;
font-size: 13px;
color: #aaa;
margin: 2px;
}
}
</style>
+31
View File
@@ -0,0 +1,31 @@
<template>
<view class="content">
<view style="padding-top:20px;">
<img alt="暂无数据" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAxKSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgIDxlbGxpcHNlIGZpbGw9IiNGNUY1RjUiIGN4PSIzMiIgY3k9IjMzIiByeD0iMzIiIHJ5PSI3Ii8+CiAgICA8ZyBmaWxsLXJ1bGU9Im5vbnplcm8iIHN0cm9rZT0iI0Q5RDlEOSI+CiAgICAgIDxwYXRoIGQ9Ik01NSAxMi43Nkw0NC44NTQgMS4yNThDNDQuMzY3LjQ3NCA0My42NTYgMCA0Mi45MDcgMEgyMS4wOTNjLS43NDkgMC0xLjQ2LjQ3NC0xLjk0NyAxLjI1N0w5IDEyLjc2MVYyMmg0NnYtOS4yNHoiLz4KICAgICAgPHBhdGggZD0iTTQxLjYxMyAxNS45MzFjMC0xLjYwNS45OTQtMi45MyAyLjIyNy0yLjkzMUg1NXYxOC4xMzdDNTUgMzMuMjYgNTMuNjggMzUgNTIuMDUgMzVoLTQwLjFDMTAuMzIgMzUgOSAzMy4yNTkgOSAzMS4xMzdWMTNoMTEuMTZjMS4yMzMgMCAyLjIyNyAxLjMyMyAyLjIyNyAyLjkyOHYuMDIyYzAgMS42MDUgMS4wMDUgMi45MDEgMi4yMzcgMi45MDFoMTQuNzUyYzEuMjMyIDAgMi4yMzctMS4zMDggMi4yMzctMi45MTN2LS4wMDd6IiBmaWxsPSIjRkFGQUZBIi8+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K">
<view style="padding-top:5px;color:#999;">暂无数据</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
title: 'Hello'
}
},
onLoad() {
},
methods: {
}
}
</script>
<style>
.content {
text-align: center;
padding-top: 200upx;
}
</style>
+69
View File
@@ -0,0 +1,69 @@
<template>
<view class="content">
<uni-list>
<uni-list-item title="头像" />
<uni-list-item title="姓名" :rightText="name" />
<uni-list-item title="帐号" :rightText="username" />
<!--
<uni-list-item title="我的订单" />
<uni-list-item title="我的发货" />
-->
</uni-list>
<view class="btns">
<button @click="logout" type="warn" class="text">{{logout_text}}</button>
</view>
</view>
</template>
<script>
import uniSection from '@/components/uni-section/uni-section.vue'
import uniList from '@/components/uni-list/uni-list.vue'
import uniListItem from '@/components/uni-list-item/uni-list-item.vue'
export default {
components: {
uniSection,
uniList,
uniListItem
},
data() {
return {
name: '',
username: '',
logout_text: '帐号注销'
}
},
onLoad() {
let me = this;
let user = uni.getStorageSync('user');
me.name = user.name;
me.username = user.username;
},
methods: {
logout() {
this.$api.logout();
},
openurl() {
uni.navigateTo({
url: '/pages/webview'
});
}
}
}
</script>
<style>
page {
height: auto;
min-height: 100%;
background-color: #f5f6f8;
font-size: 14px;
}
.content {
}
.uni-section {
margin-top: 0;
}
.btns {
padding: 30rpx;
}
</style>
+254
View File
@@ -0,0 +1,254 @@
<template>
<view>
<view class="header" id="header">
<view class="search-controller">
<uni-search-bar radius="50" placeholder="搜索单号" @confirm="search" />
</view>
<view class="line-h"></view>
</view>
<view v-if="rows.length > 0">
<view class="uni-list uni-list-controller" :style="'margin-top:' + listTop + 'px;'">
<view class="uni-list-cell" hover-class="uni-list-cell-hover" v-for="(row, key) in rows" :key="key" @click="goDetail(row)">
<view class="uni-media-list">
<view class="uni-media-list-body">
<view class="uni-media-list-text-top">
<text>{{ row.sn }}</text>
<text>{{ row.name }}</text>
</view>
<view class="uni-media-list-text-bottom">
<text>{{ row.run_name }}</text>
<text>{{ formatDate(row.created_at) }}</text>
</view>
</view>
</view>
</view>
</view>
<!--
<uni-load-more :status="status" :icon-size="16" :content-text="contentText" />
-->
</view>
<view v-else style="padding-top:300rpx;">
<img alt="暂无数据" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAxKSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgIDxlbGxpcHNlIGZpbGw9IiNGNUY1RjUiIGN4PSIzMiIgY3k9IjMzIiByeD0iMzIiIHJ5PSI3Ii8+CiAgICA8ZyBmaWxsLXJ1bGU9Im5vbnplcm8iIHN0cm9rZT0iI0Q5RDlEOSI+CiAgICAgIDxwYXRoIGQ9Ik01NSAxMi43Nkw0NC44NTQgMS4yNThDNDQuMzY3LjQ3NCA0My42NTYgMCA0Mi45MDcgMEgyMS4wOTNjLS43NDkgMC0xLjQ2LjQ3NC0xLjk0NyAxLjI1N0w5IDEyLjc2MVYyMmg0NnYtOS4yNHoiLz4KICAgICAgPHBhdGggZD0iTTQxLjYxMyAxNS45MzFjMC0xLjYwNS45OTQtMi45MyAyLjIyNy0yLjkzMUg1NXYxOC4xMzdDNTUgMzMuMjYgNTMuNjggMzUgNTIuMDUgMzVoLTQwLjFDMTAuMzIgMzUgOSAzMy4yNTkgOSAzMS4xMzdWMTNoMTEuMTZjMS4yMzMgMCAyLjIyNyAxLjMyMyAyLjIyNyAyLjkyOHYuMDIyYzAgMS42MDUgMS4wMDUgMi45MDEgMi4yMzcgMi45MDFoMTQuNzUyYzEuMjMyIDAgMi4yMzctMS4zMDggMi4yMzctMi45MTN2LS4wMDd6IiBmaWxsPSIjRkFGQUZBIi8+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K">
<view style="padding-top:5px;color:#999;">暂无数据</view>
</view>
</view>
</template>
<script>
import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue';
import {dateUtils} from '@/util.js';
export default {
components: {
uniLoadMore
},
data() {
return {
page: 1,
rows: [],
listTop: 0,
status: 'more',
reload: false,
contentText: {
contentdown: '上拉加载更多',
contentrefresh: '加载中',
contentnomore: '没有更多'
}
};
},
onLoad() {
var me = this;
me.getList();
},
mounted() {
let me = this;
uni.createSelectorQuery().in(this).select('#header').boundingClientRect(function(e) {
me.listTop = e.height - 1;
}).exec();
},
onPullDownRefresh() {
let me = this;
me.reload = true;
me.page = 1;
me.status = 'more';
me.getList();
},
onReachBottom() {
let me = this;
if (me.status == 'noMore') {
return;
}
me.status = 'more';
this.getList();
},
methods: {
formatDate(value) {
return dateUtils.formatDate(value);
},
getList() {
var me = this;
if (me.status == 'noMore') {
if (me.reload) {
me.reload = false;
uni.stopPullDownRefresh();
}
return;
}
me.$api.post('index/todo/index', {page: me.page}).then(res => {
if (me.reload) {
me.rows = [];
me.reload = false;
uni.stopPullDownRefresh();
}
me.rows = me.rows.concat(res.data);
if (res.current_page >= res.last_page) {
me.status = 'noMore';
} else {
me.page = res.current_page + 1;
}
if (me.rows.length > 0) {
uni.setTabBarBadge({
index: 0,
text: me.rows.length + ''
});
} else {
uni.removeTabBarBadge({index: 0});
}
}).catch(error => {
});
},
goDetail: function(row) {
uni.navigateTo({
url: '/pages/webview?title=' + row.name + '&url=' + encodeURIComponent(row.url + '?id=' + row.data_id),
});
}
}
};
</script>
<style>
page {
width: 100%;
height: 100%;
display: flex;
flex-wrap: wrap;
align-items: flex-start;
justify-content: center;
background: rgba(249, 249, 249, 1);
}
.header {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 100;
background: #fff;
width: 100vw;
}
.uni-list-controller {
margin-top: 63px;
width: 100vw;
}
.uni-media-list-logo {
width: 140rpx;
height: 140rpx;
}
.uni-media-list-body {
height: auto;
justify-content: space-around;
}
.uni-media-list-text-top {
font-size: 28rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
}
.uni-media-list-text-bottom {
display: flex;
flex-direction: row;
justify-content: space-between;
padding-top: 15rpx;
}
.tabs {
flex: 1;
flex-direction: column;
overflow: hidden;
background-color: #ffffff;
height: 100vh;
}
.scroll-h {
width: 750rpx;
height: 80rpx;
flex-direction: row;
white-space: nowrap;
align-items: center;
border-bottom: 1px solid #c8c7cc;
}
.line-h {
height: 1rpx;
background-color: #cccccc;
}
.uni-tab-item {
display: inline-block;
/*
padding-left: 70rpx;
padding-right: 70rpx;
*/
text-align: center;
width: 33.33333%;
}
.uni-tab-item-title {
color: #555;
font-size: 30rpx;
height: 80rpx;
line-height: 80rpx;
flex-wrap: nowrap;
white-space: nowrap;
}
.uni-tab-item-title-active {
color: #007AFF;
}
.swiper-box {
flex: 1;
height: 50vh;
}
.swiper-item {
flex: 1;
flex-direction: row;
}
.scroll-v {
flex: 1;
width: 750rpx;
}
.search-controller {
padding: 10rpx;
}
.search-result {
margin-top: 10px;
margin-bottom: 20px;
text-align: center;
}
.search-result-text {
text-align: center;
font-size: 14px;
}
</style>
+139
View File
@@ -0,0 +1,139 @@
<template>
<view class="content" :class="{'active':active}">
<image class="logo" :class="{'active':active}" src="../../static/logo.png" mode="aspectFit"></image>
<view class="tabbar-box-wrap">
<view class="tabbar-box">
<view class="tabbar-box-item" @click="goToPage('/pages/tabbar-3-detial/tabbar-3-release/tabbar-3-release')">
<image class="box-image" src="../../static/img/release.png" mode="aspectFit"></image>
<text class="explain">发图文</text>
</view>
<view class="tabbar-box-item" @click="goToPage('/pages/tabbar-3-detial/tabbar-3-video/tabbar-3-video')">
<image class="box-image" src="../../static/img/video.png" mode="aspectFit"></image>
<text class="explain">发视频</text>
</view>
<view class="tabbar-box-item" @click="goToPage('/pages/tabbar-3-detial/tabbar-3-qa/tabbar-3-qa')">
<image class="box-image" src="../../static/img/qa.png" mode="aspectFit"></image>
<text class="explain">提问</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
active: false
};
},
onLoad() {},
onShow() {
// setTimeout(() => {
this.active = true;
// }, 500);
},
onHide() {
this.active = false;
},
methods: {
goToPage(url) {
if (!url) return;
uni.navigateTo({
url
});
}
}
};
</script>
<style lang="scss" scoped>
.content {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
/* #ifdef H5 */
height: calc(100vh - var(--window-bottom) - var(--window-top));
/* #endif */
/* #ifndef H5 */
height: 100vh;
/* #endif */
transition: opacity 0.3s;
background: #999;
opacity: 0;
&.active {
opacity: 1;
}
.logo {
position: relative;
margin-top: -400upx;
width: 200upx;
height: 200upx;
// z-index: -1;
opacity: 0;
transition: opacity 0.3s;
&.active {
opacity: 1;
}
}
}
.tabbar-box-wrap {
position: absolute;
width: 100%;
padding: 50upx;
box-sizing: border-box;
bottom: 0;
left: 0;
.tabbar-box {
position: relative;
display: flex;
width: 100%;
background: #fff;
border-radius: 20upx;
padding: 15upx 20upx;
box-sizing: border-box;
z-index: 2;
box-shadow: 0px 2px 5px 2px rgba(0, 0, 0, 0.1);
&:after {
content: '';
position: absolute;
bottom: -16upx;
left: 0;
right: 0;
margin: auto;
width: 50upx;
height: 50upx;
transform: rotate(45deg);
background: #fff;
z-index: 1;
box-shadow: 2px 2px 5px 1px rgba(0, 0, 0, 0.1);
border-radius: 2px;
}
&:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #ffffff;
border-radius: 20upx;
z-index: 2;
}
.tabbar-box-item {
// position: relative;
width: 100%;
z-index: 3;
margin: 10upx;
color: $uni-color-subtitle;
text-align: center;
font-size: $uni-font-size-base;
.box-image {
width: 100%;
height: $uni-img-size-lg;
}
}
}
}
</style>
+160
View File
@@ -0,0 +1,160 @@
<template>
<view class="content">
<!-- 一般用法 -->
<view class="example-body">
<uni-grid :column="3">
<uni-grid-item v-for="(item, index) in list" :index="index" :key="index">
<view class="grid-item-box" @click="openURL(item)">
<span :class="'iconfont ' + item.icon" :style="'color:' + item.icon_color"></span>
<text class="text">{{ item.text }}</text>
<view v-if="item.badge" class="grid-dot">
<uni-badge :text="item.badge" :type="item.type" />
</view>
</view>
</uni-grid-item>
</uni-grid>
</view>
</view>
</template>
<script>
import uniGrid from "@/components/uni-grid/uni-grid.vue"
import uniGridItem from "@/components/uni-grid-item/uni-grid-item.vue"
import uniBadge from '@/components/uni-badge/uni-badge.vue'
export default {
components: {uniGrid,uniGridItem,uniBadge},
data() {
return {
list: [{
url: '/pages/app/saleOrder/index',
icon: 'icon-icon_dispose',
text: '销售订单',
icon_color: '#007aff',
access: 1,
// badge: '0',
type: "primary"
},{
url: '/pages/app/article/index',
icon: 'icon-icon_notice',
icon_color: '#22ac38',
text: '新闻公告',
access: 1,
// badge: '0',
type: "success"
},
{
url: '/pages/app/delivery/index',
icon: 'icon-icon_send',
icon_color: '#ff9900',
text: '发货列表',
access: 1,
// badge: '0',
type: "warning"
},{
url: '/pages/app/promotion/index',
icon: 'icon-icon_nomemo',
icon_color: '#22ac38',
text: '促销列表',
access: 1,
// badge: '0',
type: "warning"
},{
url: '/pages/app/approach/index',
icon: 'icon-icon_synergy',
icon_color: '#007aff',
text: '进店列表',
access: 1,
// badge: '0',
type: "warning"
},{
url: '/pages/app/workflow/index',
icon: 'icon-icon_subordinate',
icon_color: '#9370DB',
access: 1,
text: '工作流程',
//badge: '0',
type: "warning"
},{
url: '/pages/app/workflow/index',
icon: 'icon-icon_task_done',
icon_color: '#007aff',
access: 1,
text: '工作任务',
// badge: '0',
type: "warning"
},{
url: '/pages/app/workflow/index',
icon: 'icon-icon_calendar',
icon_color: '#ff9900',
access: 1,
text: '个人日程',
// badge: '0',
type: "warning"
},{
url: '/pages/app/workflow/index',
icon: 'icon-icon_group',
icon_color: '#22ac38',
access: 1,
text: '客户列表',
// badge: '0',
type: "warning"
}
]
}
},
onLoad() {
},
methods: {
openURL(item) {
uni.navigateTo({
url: item.url
});
}
}
}
</script>
<style>
view {
font-size: 14px;
line-height: inherit;
}
.content {
text-align: center;
padding: 15rpx;
}
.image {
width: 50rpx;
height: 50rpx;
}
.text {
font-size: 26rpx;
margin-top: 10rpx;
color: #666;
}
.grid-dynamic-box {
margin-bottom: 15px;
}
.grid-item-box {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 15px 0;
}
.grid-item-box .iconfont {
font-size: 80rpx;
}
.grid-dot {
position: absolute;
top: 5px;
right: 15px;
}
</style>
+84
View File
@@ -0,0 +1,84 @@
<template>
<view class="page_index">
<iframe class="webview" ref="iframe" :src="url" id="iframe"></iframe>
</view>
</template>
<script>
export default {
data() {
return {
url: ''
}
},
mounted () {
var me = this;
uni.showLoading({
title:'页面加载中...',
});
const iframe = document.querySelector('#iframe');
iframe.onload = function () {
uni.hideLoading();
}
},
onLoad: function(options) {
var me = this;
document.title = options.title;
var url = decodeURIComponent(options.url);
var token = uni.getStorageSync('token');
if (token) {
me.url = me.$api.baseURL + '/' + url + '&x-auth-token=' + token;
} else {
me.$api.authorize();
}
},
methods: {
}
}
</script>
<style>
page {
height: auto;
min-height: 100%;
background-color: #f0f3f4;
font-size: 14px;
}
.uni-page-head {
border-bottom: 3px solid #333;
}
</style>
<style lang="scss" scoped>
.webview {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border: 0;
width: 100vw;
height: 100vh;
background-color: #f0f3f4;
}
.page_index {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
.head {
position: relative;
transform: translateY(-50%);
.head_inner_title {
text-align: center;
font-size: 60rpx;
color: #007aff;
display: block;
}
.head_inner_description {
margin-top: 5rpx;
text-align: center;
font-size: 30rpx;
color: #666;
display: block;
}
}
</style>
Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 975 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

+539
View File
@@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

+1448
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

+76
View File
@@ -0,0 +1,76 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color:#333;//基本色
$uni-text-color-inverse:#fff;//反色
$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
$uni-text-color-placeholder: #808080;
$uni-text-color-disable:#c0c0c0;
/* 背景颜色 */
$uni-bg-color:#ffffff;
$uni-bg-color-grey:#f8f8f8;
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
/* 边框颜色 */
$uni-border-color:#c8c7cc;
/* 尺寸变量 */
/* 文字尺寸 */
$uni-font-size-sm:24upx;
$uni-font-size-base:28upx;
$uni-font-size-lg:32upx;
/* 图片尺寸 */
$uni-img-size-sm:40upx;
$uni-img-size-base:52upx;
$uni-img-size-lg:80upx;
/* Border Radius */
$uni-border-radius-sm: 4upx;
$uni-border-radius-base: 6upx;
$uni-border-radius-lg: 12upx;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 10px;
$uni-spacing-row-base: 20upx;
$uni-spacing-row-lg: 30upx;
/* 垂直间距 */
$uni-spacing-col-sm: 8upx;
$uni-spacing-col-base: 16upx;
$uni-spacing-col-lg: 24upx;
/* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
/* 文章场景相关 */
$uni-color-title: #2C405A; // 文章标题颜色
$uni-font-size-title:40upx;
$uni-color-subtitle: #555555; // 二级标题颜色
$uni-font-size-subtitle:36upx;
$uni-color-paragraph: #3F536E; // 文章段落颜色
$uni-font-size-paragraph:30upx;
+87
View File
@@ -0,0 +1,87 @@
function formatTime(time) {
if (typeof time !== 'number' || time < 0) {
return time
}
var hour = parseInt(time / 3600)
time = time % 3600
var minute = parseInt(time / 60)
time = time % 60
var second = time
return ([hour, minute, second]).map(function (n) {
n = n.toString()
return n[1] ? n : '0' + n
}).join(':')
}
function formatLocation(longitude, latitude) {
if (typeof longitude === 'string' && typeof latitude === 'string') {
longitude = parseFloat(longitude)
latitude = parseFloat(latitude)
}
longitude = longitude.toFixed(2)
latitude = latitude.toFixed(2)
return {
longitude: longitude.toString().split('.'),
latitude: latitude.toString().split('.')
}
}
var dateUtils = {
UNITS: {
'年': 31557600000,
'月': 2629800000,
'天': 86400000,
'小时': 3600000,
'分钟': 60000,
'秒': 1000
},
humanize: function (milliseconds) {
var humanize = '';
for (var key in this.UNITS) {
if (milliseconds >= this.UNITS[key]) {
humanize = Math.floor(milliseconds / this.UNITS[key]) + key + '前';
break;
}
}
return humanize || '刚刚';
},
format: function (dateStr) {
var date = this.parse(dateStr)
var diff = Date.now() - date.getTime();
if (diff < this.UNITS['天']) {
return this.humanize(diff);
}
var _format = function (number) {
return (number < 10 ? ('0' + number) : number);
};
return date.getFullYear() + '/' + _format(date.getMonth() + 1) + '/' + _format(date.getDate()) + '-' +
_format(date.getHours()) + ':' + _format(date.getMinutes());
},
parse: function (str) { //将"yyyy-mm-dd HH:MM:ss"格式的字符串,转化为一个Date对象
var a = str.split(/[^0-9]/);
return new Date(a[0], a[1] - 1, a[2], a[3], a[4], a[5]);
},
formatDate: function (value) {
function add0(v) {
return v < 10 ? '0' + v : v;
}
value = parseInt(value) * 1000;
var time = new Date(value);
var y = time.getFullYear();
var m = time.getMonth()+1;
var d = time.getDate();
var h = time.getHours();
var mm = time.getMinutes();
var s = time.getSeconds();
return y+'-'+add0(m)+'-'+add0(d)+' '+add0(h)+':'+add0(mm);
}
};
module.exports = {
formatTime,
formatLocation,
dateUtils
}
+1
View File
File diff suppressed because one or more lines are too long