parent
96e9a4e16a
commit
a7a348ac11
@ -1,3 +1,4 @@
|
||||
/* uView组件全局属性 */
|
||||
uni.$u.props.gap.bgColor = '#ffffff'
|
||||
uni.$u.props.gap.height = '10'
|
||||
uni.$u.props.button.throttleTime = 500 // 节流: 0.5s内只触发一次
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,183 +0,0 @@
|
||||
<template>
|
||||
<view class="w-picker-view">
|
||||
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.provinces" :key="index">{{item.label}}</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.citys" :key="index">{{item.label}}</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column v-if="!hideArea">
|
||||
<view class="w-picker-item" v-for="(item,index) in range.areas" :key="index">{{item.label}}</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import areaData from "./areadata/areadata.js"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pickVal:[],
|
||||
range:{
|
||||
provinces:[],
|
||||
citys:[],
|
||||
areas:[]
|
||||
},
|
||||
checkObj:{}
|
||||
};
|
||||
},
|
||||
props:{
|
||||
itemHeight:{
|
||||
type:String,
|
||||
default:"44px"
|
||||
},
|
||||
value:{
|
||||
type:[Array,String],
|
||||
default:""
|
||||
},
|
||||
defaultType:{
|
||||
type:String,
|
||||
default:"label"
|
||||
},
|
||||
hideArea:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
value(val){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.initData();
|
||||
},
|
||||
methods:{
|
||||
getData(){
|
||||
//用来处理初始化数据
|
||||
let provinces=areaData;
|
||||
let dVal=[];
|
||||
let value=this.value;
|
||||
let a1=value[0];//默认值省
|
||||
let a2=value[1];//默认值市
|
||||
let a3=value[2];//默认值区、县
|
||||
let province,city,area;
|
||||
let provinceIndex=provinces.findIndex((v)=>{
|
||||
return v[this.defaultType]==a1
|
||||
});
|
||||
provinceIndex=value?(provinceIndex!=-1?provinceIndex:0):0;
|
||||
let citys=provinces[provinceIndex].children;
|
||||
let cityIndex=citys.findIndex((v)=>{
|
||||
return v[this.defaultType]==a2
|
||||
});
|
||||
cityIndex=value?(cityIndex!=-1?cityIndex:0):0;
|
||||
let areas=citys[cityIndex].children;
|
||||
let areaIndex=areas.findIndex((v)=>{
|
||||
return v[this.defaultType]==a3;
|
||||
});
|
||||
areaIndex=value?(areaIndex!=-1?areaIndex:0):0;
|
||||
dVal=this.hideArea?[provinceIndex,cityIndex]:[provinceIndex,cityIndex,areaIndex];
|
||||
province=provinces[provinceIndex];
|
||||
city=citys[cityIndex];
|
||||
area=areas[areaIndex];
|
||||
let obj=this.hideArea?{
|
||||
province,
|
||||
city
|
||||
}:{
|
||||
province,
|
||||
city,
|
||||
area
|
||||
}
|
||||
return this.hideArea?{
|
||||
provinces,
|
||||
citys,
|
||||
dVal,
|
||||
obj
|
||||
}:{
|
||||
provinces,
|
||||
citys,
|
||||
areas,
|
||||
dVal,
|
||||
obj
|
||||
}
|
||||
},
|
||||
initData(){
|
||||
let dataData=this.getData();
|
||||
let provinces=dataData.provinces;
|
||||
let citys=dataData.citys;
|
||||
let areas=this.hideArea?[]:dataData.areas;
|
||||
let obj=dataData.obj;
|
||||
let province=obj.province,city=obj.city,area=this.hideArea?{}:obj.area;
|
||||
let value=this.hideArea?[province.value,city.value]:[province.value,city.value,area.value];
|
||||
let result=this.hideArea?`${province.label+city.label}`:`${province.label+city.label+area.label}`;
|
||||
this.range=this.hideArea?{
|
||||
provinces,
|
||||
citys,
|
||||
}:{
|
||||
provinces,
|
||||
citys,
|
||||
areas
|
||||
};
|
||||
this.checkObj=obj;
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=dataData.dVal;
|
||||
});
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:value,
|
||||
obj:obj
|
||||
})
|
||||
},
|
||||
handlerChange(e){
|
||||
let arr=[...e.detail.value];
|
||||
let provinceIndex=arr[0],cityIndex=arr[1],areaIndex=this.hideArea?0:arr[2];
|
||||
let provinces=areaData;
|
||||
let citys=(provinces[provinceIndex]&&provinces[provinceIndex].children)||provinces[provinces.length-1].children||[];
|
||||
let areas=this.hideArea?[]:((citys[cityIndex]&&citys[cityIndex].children)||citys[citys.length-1].children||[]);
|
||||
let province=provinces[provinceIndex]||provinces[provinces.length-1],
|
||||
city=citys[cityIndex]||[citys.length-1],
|
||||
area=this.hideArea?{}:(areas[areaIndex]||[areas.length-1]);
|
||||
let obj=this.hideArea?{
|
||||
province,
|
||||
city
|
||||
}:{
|
||||
province,
|
||||
city,
|
||||
area
|
||||
}
|
||||
if(this.checkObj.province.label!=province.label){
|
||||
//当省更新的时候需要刷新市、区县的数据;
|
||||
this.range.citys=citys;
|
||||
if(!this.hideArea){
|
||||
this.range.areas=areas;
|
||||
}
|
||||
|
||||
}
|
||||
if(this.checkObj.city.label!=city.label){
|
||||
//当市更新的时候需要刷新区县的数据;
|
||||
if(!this.hideArea){
|
||||
this.range.areas=areas;
|
||||
}
|
||||
}
|
||||
this.checkObj=obj;
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=arr;
|
||||
})
|
||||
let result=this.hideArea?`${province.label+city.label}`:`${province.label+city.label+area.label}`;
|
||||
let value=this.hideArea?[province.value,city.value]:[province.value,city.value,area.value];
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:value,
|
||||
obj:obj
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./w-picker.css";
|
||||
</style>
|
||||
|
@ -1,129 +0,0 @@
|
||||
<template>
|
||||
<view class="w-picker-view">
|
||||
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range" :key="index">{{item[nodeKey]}}</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props:{
|
||||
itemHeight:{
|
||||
type:String,
|
||||
default:"44px"
|
||||
},
|
||||
options:{
|
||||
type:[Array,Object],
|
||||
default(){
|
||||
return []
|
||||
}
|
||||
},
|
||||
value:{
|
||||
type:String,
|
||||
default:""
|
||||
},
|
||||
defaultType:{
|
||||
type:String,
|
||||
default:"label"
|
||||
},
|
||||
defaultProps:{
|
||||
type:Object,
|
||||
default(){
|
||||
return{
|
||||
label:"label",
|
||||
value:"value"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pickVal:[]
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
nodeKey(){
|
||||
return this.defaultProps.label;
|
||||
},
|
||||
nodeValue(){
|
||||
return this.defaultProps.value;
|
||||
},
|
||||
range(){
|
||||
return this.options
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
value(val){
|
||||
if(this.options.length!=0){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
options(val){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if(this.options.length!=0){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
initData(){
|
||||
let dVal=this.value||"";
|
||||
let data=this.range;
|
||||
let pickVal=[0];
|
||||
let cur=null;
|
||||
let label="";
|
||||
let value,idx;
|
||||
if(this.defaultType==this.nodeValue){
|
||||
value=data.find((v)=>v[this.nodeValue]==dVal);
|
||||
idx=data.findIndex((v)=>v[this.nodeValue]==dVal);
|
||||
}else{
|
||||
value=data.find((v)=>v[this.nodeKey]==dVal);
|
||||
idx=data.findIndex((v)=>v[this.nodeKey]==dVal);
|
||||
}
|
||||
pickVal=[idx!=-1?idx:0];
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=pickVal;
|
||||
});
|
||||
if(this.defaultType==this.nodeValue){
|
||||
this.$emit("change",{
|
||||
result:value?value[this.nodeKey]:data[0][this.nodeKey],
|
||||
value:dVal||data[0][this.nodeKey],
|
||||
obj:value?value:data[0]
|
||||
})
|
||||
}else{
|
||||
this.$emit("change",{
|
||||
result:dVal||data[0][this.nodeKey],
|
||||
value:value?value[this.nodeValue]:data[0][this.nodeValue],
|
||||
obj:value?value:data[0]
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
handlerChange(e){
|
||||
let arr=[...e.detail.value];
|
||||
let pickVal=[arr[0]||0];
|
||||
let data=this.range;
|
||||
let cur=data[arr[0]];
|
||||
let label="";
|
||||
let value="";
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=pickVal;
|
||||
});
|
||||
this.$emit("change",{
|
||||
result:cur[this.nodeKey],
|
||||
value:cur[this.nodeValue],
|
||||
obj:cur
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./w-picker.css";
|
||||
</style>
|
@ -1,26 +0,0 @@
|
||||
.w-picker-flex2{
|
||||
flex:2;
|
||||
}
|
||||
.w-picker-flex1{
|
||||
flex:1;
|
||||
}
|
||||
.w-picker-view {
|
||||
width: 100%;
|
||||
height: 476upx;
|
||||
overflow: hidden;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
z-index: 666;
|
||||
}
|
||||
.d-picker-view{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.w-picker-item {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
height: 88upx;
|
||||
line-height: 88upx;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 30upx;
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
<template>
|
||||
<view class="address-box">
|
||||
<view v-if="!address.area" class="address-empty">
|
||||
<view class="address-tips">
|
||||
<u--text :lines="1" size="14px" color="#333" bold="true" text="请选择收货地址"></u--text>
|
||||
<u-icon class="icon-arrow-right" name="arrow-right"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else class="address-selected">
|
||||
<view class="address-area">
|
||||
<view class="default-tag">默认</view>
|
||||
<u--text :lines="1" size="12px" color="#666" :text="address.area"></u--text>
|
||||
</view>
|
||||
<view class="address-detail">
|
||||
<u--text :lines="2" size="14px" color="#333" :bold="true" :text="address.detail"></u--text>
|
||||
<u-icon class="icon-arrow-right" name="arrow-right"></u-icon>
|
||||
</view>
|
||||
<view class="address-user">
|
||||
<view class="user-text">{{ address.name }}</view>
|
||||
<view class="user-text">{{ address.mobile }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<image class="address-line" src="/static/images/address-line.png"></image>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 地址选择
|
||||
*/
|
||||
export default {
|
||||
name: 'yd-address-select',
|
||||
props: {
|
||||
address: {
|
||||
type: Object,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
methods: {}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.address-box {
|
||||
padding: 0 10rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 0 0 30rpx 30rpx;
|
||||
|
||||
.address-empty {
|
||||
padding: 20rpx 20rpx 0;
|
||||
.address-tips {
|
||||
@include flex-space-between;
|
||||
padding: 10rpx 0;
|
||||
|
||||
.icon-arrow-right {
|
||||
margin-left: 50rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.address-selected {
|
||||
padding: 20rpx 20rpx 0;
|
||||
.address-area {
|
||||
@include flex-left;
|
||||
|
||||
.default-tag {
|
||||
font-size: 22rpx;
|
||||
color: $u-primary;
|
||||
border: 1rpx solid $u-primary;
|
||||
padding: 0 6rpx;
|
||||
margin-right: 10rpx;
|
||||
border-radius: 5rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.address-detail {
|
||||
@include flex-space-between;
|
||||
padding: 10rpx 0;
|
||||
|
||||
.icon-arrow-right {
|
||||
margin-left: 50rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.address-user {
|
||||
@include flex-left;
|
||||
|
||||
.user-text {
|
||||
color: #666;
|
||||
font-size: 24rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.address-line {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
height: 5rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,60 +0,0 @@
|
||||
<template>
|
||||
<u-swiper :list="bannerList" :keyName="keyName" previousMargin="20" nextMargin="20" circular height="150"
|
||||
@change="e => (current = e.current)" :autoplay="true" @click="handleSwiperClick">
|
||||
<view slot="indicator" class="indicator">
|
||||
<view class="indicator__dot" v-for="(item, index) in bannerList" :key="index"
|
||||
:class="[index === current && 'indicator__dot--active']"></view>
|
||||
</view>
|
||||
</u-swiper>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 广告滚动图
|
||||
*/
|
||||
export default {
|
||||
name: 'yd-banner',
|
||||
components: {},
|
||||
props: {
|
||||
keyName: {
|
||||
type: String,
|
||||
default: 'url'
|
||||
},
|
||||
bannerList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
current: 0,
|
||||
currentNum: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSwiperClick(index) {
|
||||
console.log('点击了图片索引值:', index)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.indicator {
|
||||
@include flex(row);
|
||||
justify-content: center;
|
||||
|
||||
&__dot {
|
||||
height: 15rpx;
|
||||
width: 15rpx;
|
||||
border-radius: 100rpx;
|
||||
background-color: rgba(255, 255, 255, 0.35);
|
||||
margin: 0 10rpx;
|
||||
transition: background-color 0.3s;
|
||||
|
||||
&--active {
|
||||
background-color: $custom-bg-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,116 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="product-item" v-for="(item, index) in productList" :key="item.productId" @click="handleProductItemClick(item.productId)">
|
||||
<view class="product-check" @click.stop="handleCheckProduct(item.productId, item.checked)">
|
||||
<u-icon v-if="item.checked" name="checkmark-circle-fill" color="#3c9cff" size="22"></u-icon>
|
||||
<view v-else class="un-check-box"></view>
|
||||
</view>
|
||||
<image class="product-image" :src="item.coverUrl"></image>
|
||||
<view class="item-info">
|
||||
<view class="info-text">
|
||||
<u--text :lines="1" size="15px" color="#333333" :text="item.productTitle"></u--text>
|
||||
<u-gap height="2px"></u-gap>
|
||||
<u--text class="info-tips" :lines="1" size="12px" color="#939393" :text="item.tips"></u--text>
|
||||
</view>
|
||||
<view class="price-number-box">
|
||||
<view class="price-box">
|
||||
<yd-text-price color="red" size="13" intSize="20" :price="item.sellPrice"></yd-text-price>
|
||||
<yd-text-price v-if="item.strikePrice" style="margin-left: 5px" decoration="line-through" color="#999" size="12" :price="item.sellPrice"></yd-text-price>
|
||||
</view>
|
||||
<view class="number-box" @click.stop>
|
||||
<u-number-box min="1" max="999" bgColor="#fff" integer :disableMinus="false" :disabledInput="true" :name="item.productId" :value="item.productCount" @change="handleProductCountChange"></u-number-box>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 购物车商品列表
|
||||
*/
|
||||
export default {
|
||||
name: 'yd-cart-product',
|
||||
props: {
|
||||
productList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
//status: 'nomore',
|
||||
loadingText: '加载中...',
|
||||
loadmoreText: '上拉加载更多',
|
||||
nomoreText: '没有更多了'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleProductItemClick(productId) {
|
||||
uni.$u.route('/pages/product/product', {
|
||||
id: productId
|
||||
})
|
||||
},
|
||||
handleItemCartClick(productId) {
|
||||
this.$store.dispatch('CartProductCountChange', { productIds: [productId], productCount: 1, addition: true }).then(res => {
|
||||
uni.$u.toast('已添加到购物车')
|
||||
})
|
||||
},
|
||||
handleCheckProduct(productId, checked) {
|
||||
this.$emit('productCheckedChange', productId, !checked)
|
||||
},
|
||||
handleProductCountChange({ name, value }) {
|
||||
this.$emit('productCartProductCountChange', name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.product-item {
|
||||
background: #ffffff;
|
||||
@include flex-space-between;
|
||||
border-bottom: $custom-border-style;
|
||||
padding: 10rpx 0 0 5rpx;
|
||||
|
||||
.product-check {
|
||||
padding: 20rpx;
|
||||
|
||||
.un-check-box {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 1px solid #939393;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.item-info {
|
||||
flex: 1;
|
||||
padding: 20rpx 20rpx 0;
|
||||
|
||||
.info-text {
|
||||
height: 70rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.price-number-box {
|
||||
@include flex-space-between;
|
||||
|
||||
.price-box {
|
||||
@include flex-left();
|
||||
}
|
||||
|
||||
.number-box {
|
||||
height: 100rpx;
|
||||
@include flex-center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,173 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<view v-if="showType === 'normal'">
|
||||
<u-gap height="180" bgColor="#398ade"></u-gap>
|
||||
<view class="prod-block">
|
||||
<view class="bloc-header">
|
||||
<text class="bloc-title">{{title}}</text>
|
||||
<text class="see-more">查看更多</text>
|
||||
</view>
|
||||
<view class="prod-grid">
|
||||
<view class="prod-item" v-for="(item, index) in productList" :key="item.id" @click="handleProdItemClick(item.id)">
|
||||
<image class="prod-image" :src="item.image"></image>
|
||||
<view class="item-info">
|
||||
<view class="info-text">
|
||||
<u--text :lines="2" size="14px" color="#333333" :text="item.title"></u--text>
|
||||
</view>
|
||||
<view class="price-and-cart">
|
||||
<yd-text-price color="red" size="12" intSize="18" :price="item.price"></yd-text-price>
|
||||
<u-icon name="shopping-cart" color="#2979ff" size="28"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="showType === 'half'">
|
||||
<view class="prod-block half">
|
||||
<view class="bloc-header">
|
||||
<text class="bloc-title">{{title}}</text>
|
||||
<text class="more">更多 ></text>
|
||||
</view>
|
||||
<view class="prod-grid half">
|
||||
<view class="prod-item" v-for="(item, index) in productList" :key="item.id" @click="handleProdItemClick(item.id)">
|
||||
<image class="prod-image" :src="item.image"></image>
|
||||
<view class="item-info">
|
||||
<view class="info-text">
|
||||
<u--text :lines="1" size="14px" color="#333333" :text="item.title"></u--text>
|
||||
<u--text :lines="1" size="12px" color="#939393" :text="item.desc"></u--text>
|
||||
</view>
|
||||
<view class="price-and-cart">
|
||||
<yd-text-price color="red" size="12" intSize="18" :price="item.price"></yd-text-price>
|
||||
<u-icon name="shopping-cart" color="#2979ff" size="28"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 商品列表
|
||||
*/
|
||||
export default {
|
||||
name: 'yd-product-box',
|
||||
components: {},
|
||||
props: {
|
||||
showType: {
|
||||
type: String,
|
||||
default: 'normal'
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: '商品推荐'
|
||||
},
|
||||
productList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
handleProdItemClick(productId) {
|
||||
uni.$u.route('/pages/product/product', {
|
||||
id: productId
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.prod-block {
|
||||
margin-top: -160px;
|
||||
|
||||
.bloc-header {
|
||||
@include flex-space-between;
|
||||
padding: 10rpx 20rpx;
|
||||
|
||||
.bloc-title {
|
||||
color: $custom-bg-color;
|
||||
font-size: 34rpx;
|
||||
}
|
||||
|
||||
.see-more {
|
||||
color: $custom-bg-color;
|
||||
background: $u-primary;
|
||||
padding: 0 30rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
border-radius: 50rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
&.half {
|
||||
margin-top: 0;
|
||||
|
||||
.bloc-header {
|
||||
margin-top: 50rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.bloc-title {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.more {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.prod-grid {
|
||||
width: 730rpx;
|
||||
margin: 0 auto;
|
||||
@include flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: left;
|
||||
|
||||
&.half {
|
||||
.prod-item {
|
||||
width: 345rpx;
|
||||
margin: 10rpx;
|
||||
|
||||
.prod-image {
|
||||
width: 345rpx;
|
||||
height: 345rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.prod-item {
|
||||
width: 223rpx;
|
||||
margin: 10rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 10rpx;
|
||||
box-shadow: 0rpx 6rpx 8rpx rgba(58, 134, 185, 0.2);
|
||||
|
||||
.prod-image {
|
||||
width: 223rpx;
|
||||
height: 223rpx;
|
||||
border-radius: 10rpx 10rpx 0 0;
|
||||
}
|
||||
|
||||
.item-info {
|
||||
padding: 15rpx;
|
||||
|
||||
.info-text {
|
||||
height: 70rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.price-and-cart {
|
||||
@include flex-space-between;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,114 +0,0 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="prod-block list">
|
||||
<view class="bloc-header">
|
||||
<text class="bloc-title">更多宝贝</text>
|
||||
<text></text>
|
||||
</view>
|
||||
|
||||
<view class="prod-list" v-for="(item, index) in productList" :key="item.id">
|
||||
<view class="prod-item" @click="handleProdItemClick(item.id)">
|
||||
<image class="prod-image" :src="item.image"></image>
|
||||
<view class="item-info">
|
||||
<view class="info-text">
|
||||
<u--text :lines="1" size="14px" color="#333333" :text="item.title"></u--text>
|
||||
<u-gap height="2px"></u-gap>
|
||||
<u--text class="info-desc" :lines="2" size="12px" color="#939393" :text="item.desc"></u--text>
|
||||
</view>
|
||||
<view class="price-and-cart">
|
||||
<yd-text-price color="red" size="12" intSize="18" :price="item.price"></yd-text-price>
|
||||
<u-icon name="shopping-cart" color="#2979ff" size="28"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!--加载更多-->
|
||||
<u-loadmore fontSize="28rpx" :line="true" :status="moreStatus" :loading-text="loadingText" :loadmore-text="loadmoreText" :nomore-text="nomoreText" />
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 商品列表(加载更多)
|
||||
*/
|
||||
export default {
|
||||
name: 'yd-product-more',
|
||||
components: {},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '商品推荐'
|
||||
},
|
||||
productList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
moreStatus: {
|
||||
type: String,
|
||||
default: 'nomore'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
//status: 'nomore',
|
||||
loadingText: '加载中...',
|
||||
loadmoreText: '上拉加载更多',
|
||||
nomoreText: '已经到底了'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleProdItemClick(productId) {
|
||||
uni.$u.route('/pages/product/product', {
|
||||
id: productId
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.prod-block {
|
||||
margin-top: 0;
|
||||
|
||||
.bloc-header {
|
||||
margin-top: 50rpx;
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.bloc-title {
|
||||
margin-left: 20rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.prod-list {
|
||||
.prod-item {
|
||||
background: #ffffff;
|
||||
@include flex-space-between;
|
||||
border-bottom: $custom-border-style;
|
||||
padding: 20rpx;
|
||||
|
||||
.prod-image {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.item-info {
|
||||
flex: 1;
|
||||
padding: 20rpx 20rpx 0;
|
||||
|
||||
.info-text {
|
||||
height: 100rpx;
|
||||
padding-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.price-and-cart {
|
||||
@include flex-space-between;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,205 +0,0 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 搜索框 -->
|
||||
<view class="search-wrap">
|
||||
<u-search placeholder="搜索" disabled height="32" bgColor="#f2f2f2" margin="0 20rpx" :show-action="false"
|
||||
@click="handleSearchClick"></u-search>
|
||||
</view>
|
||||
|
||||
<!-- 分类内容 -->
|
||||
<view class="category-box">
|
||||
<!-- 左侧导航栏 -->
|
||||
<scroll-view scroll-y="true" class='box-left'>
|
||||
<view class="category-item" v-for="(item, index) in categoryList" :key="item.id">
|
||||
<view class="item-title" :class="{ active: currentIndex === index }" @click="handleCategoryClick(index)">
|
||||
<text>{{ item.name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 右侧分类内容 -->
|
||||
<scroll-view scroll-y="true" class="box-right">
|
||||
<view class="category-image">
|
||||
<image :showLoading="true" :src="categoryList[currentIndex].picUrl" mode='widthFix' @click="click"></image>
|
||||
</view>
|
||||
|
||||
<view class="sub-category-box" v-for="(item, index) in categoryList[currentIndex].children" :key="item.id">
|
||||
<view class="sub-category-header">
|
||||
<view class="title">{{ item.name }}</view>
|
||||
<view class="more" @click="handleCategory(item, 0)">查看更多</view>
|
||||
</view>
|
||||
|
||||
<view class="sub-category-grid">
|
||||
<u-grid col="3">
|
||||
<u-grid-item v-for="(subItem, subIndex) in item.children" :key="subItem.id">
|
||||
<view class="sub-category-item" @click="handleCategory(item, subIndex)">
|
||||
<u-icon name="photo" :size="80" v-if="subItem.picUrl === null"></u-icon>
|
||||
<image :src="subItem.picUrl" v-if="subItem.picUrl != null" mode='widthFix' />
|
||||
<text class="sub-category-title">{{ subItem.name }}</text>
|
||||
</view>
|
||||
</u-grid-item>
|
||||
</u-grid>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { categoryListData } from '../../api/category';
|
||||
import { handleTree, convertTree } from '../../utils/tree.js';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
currentIndex: 0,
|
||||
categoryList: []
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
this.handleCategoryList();
|
||||
},
|
||||
methods: {
|
||||
// 点击搜索框
|
||||
handleSearchClick(e) {
|
||||
uni.$u.route('/pages/search/search')
|
||||
},
|
||||
// 点击左侧导航栏
|
||||
handleCategoryClick(index) {
|
||||
if (this.currentIndex !== index) {
|
||||
this.currentIndex = index
|
||||
}
|
||||
},
|
||||
// 获取分类列表并构建树形结构
|
||||
handleCategoryList() {
|
||||
categoryListData().then(res => {
|
||||
this.categoryList = handleTree(res.data, "id", "parentId");
|
||||
})
|
||||
},
|
||||
handleCategory(item, index){
|
||||
// console.log(item)
|
||||
// console.log(index)
|
||||
uni.navigateTo({
|
||||
url:"./product-list?item="+encodeURIComponent(JSON.stringify(item))+"&index="+index
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.search-wrap {
|
||||
background: #ffffff;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.07);
|
||||
padding: 20rpx 0;
|
||||
width: 100%;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.category-box {
|
||||
position: fixed;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
margin-top: 100rpx;
|
||||
height: calc(100% - 100rpx);
|
||||
|
||||
.box-left {
|
||||
width: 200rpx;
|
||||
padding-top: 5rpx;
|
||||
overflow: scroll;
|
||||
z-index: 2;
|
||||
background-color: #f2f2f2;
|
||||
|
||||
.category-item {
|
||||
line-height: 80rpx;
|
||||
height: 80rpx;
|
||||
text-align: center;
|
||||
color: #777;
|
||||
|
||||
.item-title {
|
||||
font-size: 28rpx;
|
||||
|
||||
&.active {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
background: #fff;
|
||||
color: $u-primary;
|
||||
}
|
||||
|
||||
&.active::before {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
content: "";
|
||||
width: 8rpx;
|
||||
height: 32rpx;
|
||||
top: 25rpx;
|
||||
background: $u-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.box-right {
|
||||
width: 550rpx;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
z-index: 1;
|
||||
|
||||
.category-image {
|
||||
width: 510rpx;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
margin: 30rpx 20rpx 0;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-category-box {
|
||||
.sub-category-header {
|
||||
@include flex-space-between;
|
||||
padding: 20rpx 20rpx;
|
||||
|
||||
.title {
|
||||
font-size: 28rpx;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.more {
|
||||
font-size: 22rpx;
|
||||
color: #939393;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-category-grid {
|
||||
padding: 0 15rpx;
|
||||
|
||||
.sub-category-item {
|
||||
@include flex-center(column);
|
||||
background: #fff;
|
||||
|
||||
image {
|
||||
text-align: center;
|
||||
width: 150rpx;
|
||||
height: 150rpx;
|
||||
line-height: 150rpx;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.sub-category-title {
|
||||
margin: 15rpx 0;
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,285 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<!-- 导航栏 -->
|
||||
<u-navbar leftText="返回" title="任务开工" :placeholder="true" leftIconColor=" #409eff" @leftClick="backClick" />
|
||||
<view class="info-item">
|
||||
<view class="title">#30 任务名称 (任务编号: 90569010)</view>
|
||||
<view class="target">
|
||||
<view class="imgbox">
|
||||
<image slot='cover' class="unimg" mode="aspectFill" :src="info.imgurl"></image>
|
||||
<text class="name">xxx产品</text>
|
||||
</view>
|
||||
<view class="number">
|
||||
<text>计划数量: </text>
|
||||
<text style="color:#409eff;font-size: 16px;margin-left: 8px;">30</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="finishtime">
|
||||
<text>完工时间: </text>
|
||||
<text style="color:#999;margin-left: 8px;">2023-10-11 19:58:51</text>
|
||||
</view>
|
||||
</view>
|
||||
<u-gap height="5px"></u-gap>
|
||||
<view class="info-item">
|
||||
<view class="header">计划加工用时</view>
|
||||
<!-- <view class="header">阿里巴巴</view> -->
|
||||
<view class="time">
|
||||
<u-icon name="clock" color="#f56c6c" size="18"></u-icon>
|
||||
<text class="hour">80:00:00 (小时)</text>
|
||||
</view>
|
||||
</view>
|
||||
<u-gap height="5px"></u-gap>
|
||||
<view class="info-item">
|
||||
<view class="header">任务操作</view>
|
||||
<view class="options">
|
||||
<u-button type="primary" :plain="true" :hairline="true" text="领料申请" @click="applyPickingClick"></u-button>
|
||||
<u-button type="primary" :plain="true" :hairline="true" text="完工提报" @click="reportCompletionClick"></u-button>
|
||||
<u-button type="primary" :plain="false" :hairline="true" text="质检申请" @click="checkQualityClick"></u-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 领料申请 -->
|
||||
<u-popup :show="popupApplyShow" mode="center" @close="popupApplyShow = false" :customStyle="{'width': '350px'}"
|
||||
closeable>
|
||||
<view class="picklist">
|
||||
<material-apply :picklist="picklist" :show.sync="popupApplyShow" :checkNumber="checkValid"></material-apply>
|
||||
</view>
|
||||
</u-popup>
|
||||
|
||||
<!-- 完工报告 -->
|
||||
<u-popup :show="popupReviewShow" mode="center" @close="popupReviewShow = false" :customStyle="{'width': '350px'}"
|
||||
closeable>
|
||||
<view class="picklist">
|
||||
<work-report :picklist="picklist" :info="info" :show.sync="popupReviewShow"></work-report>
|
||||
</view>
|
||||
</u-popup>
|
||||
|
||||
<!-- 返库物料选择 -->
|
||||
<u-popup :show="restoreSelectShow" mode="center" @close="restoreSelectShow = false" closeable>
|
||||
<view class="select-box">
|
||||
<uni-section title="选择返库物料" type="line">
|
||||
<uni-data-select :localdata="restoreRange" @change="changeRestore"></uni-data-select>
|
||||
</uni-section>
|
||||
</view>
|
||||
</u-popup>
|
||||
|
||||
<!-- 消息提示 -->
|
||||
<u-toast ref="msg"></u-toast>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import materialApply from './material-apply.vue'
|
||||
import workReport from './work-report.vue'
|
||||
export default {
|
||||
components: {
|
||||
materialApply,
|
||||
workReport
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
checkData: this.checkValid,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
info: {
|
||||
id: 90569010,
|
||||
title: "#001任务名称",
|
||||
productName: "xxx产品",
|
||||
unit: "件",
|
||||
imgurl: require('@/static/images/wuliao.png'),
|
||||
hours: 80,
|
||||
number: 30,
|
||||
completed: 0,
|
||||
status: 1,
|
||||
creator: '管理员',
|
||||
createtime: '2023-10-01 09:58:51',
|
||||
pointer: '小王',
|
||||
finishtime: '2023-10-11 19:58:51',
|
||||
},
|
||||
picklist: [{
|
||||
"id": 10001,
|
||||
"name": "实物物料202212050001",
|
||||
"spec": "330ml/瓶",
|
||||
"number": 1,
|
||||
"unit": "瓶"
|
||||
},
|
||||
{
|
||||
"id": 10002,
|
||||
"name": "实物物料202212050002",
|
||||
"spec": "330ml/瓶",
|
||||
"number": 2,
|
||||
"unit": "瓶"
|
||||
},
|
||||
{
|
||||
"id": 10003,
|
||||
"name": "实物物料202212050003",
|
||||
"spec": "330ml/瓶",
|
||||
"number": 3,
|
||||
"unit": "瓶"
|
||||
},
|
||||
{
|
||||
"id": 10004,
|
||||
"name": "实物物料202212050004",
|
||||
"spec": "100颗",
|
||||
"number": 20,
|
||||
"unit": "件"
|
||||
},
|
||||
{
|
||||
"id": 10005,
|
||||
"name": "实物物料202212050005",
|
||||
"spec": "100颗",
|
||||
"number": 10,
|
||||
"unit": "件"
|
||||
},
|
||||
{
|
||||
"id": 10006,
|
||||
"name": "实物物料202212050006",
|
||||
"spec": "100颗",
|
||||
"number": 10,
|
||||
"unit": "件"
|
||||
}
|
||||
],
|
||||
popupApplyShow: false,
|
||||
popupReviewShow: false,
|
||||
}
|
||||
},
|
||||
onLoad(params) {
|
||||
console.log(params); // 接受列表页传递参数
|
||||
},
|
||||
methods: {
|
||||
backClick() {
|
||||
uni.switchTab({
|
||||
url: "/pages/renwu/index?status=1"
|
||||
});
|
||||
},
|
||||
// 领料申请
|
||||
applyPickingClick() {
|
||||
this.popupApplyShow = true;
|
||||
},
|
||||
// 完工提报
|
||||
reportCompletionClick() {
|
||||
this.popupReviewShow = true;
|
||||
},
|
||||
// 质检申请
|
||||
checkQualityClick() {
|
||||
this.$refs.msg.show({
|
||||
type: 'default',
|
||||
message: "质检申请暂未开发~",
|
||||
});
|
||||
},
|
||||
// 检测输入数字有效性
|
||||
checkValid(that, val) {
|
||||
let invalid = false;
|
||||
if (!/^\d{1,3}$/.test(val) || Number.parseInt(val) <= 0) {
|
||||
invalid = true;
|
||||
that.$nextTick(() => {
|
||||
that.$refs.uToast.show({
|
||||
type: 'error',
|
||||
icon: false,
|
||||
message: "必须为1-999之间的整数",
|
||||
})
|
||||
});
|
||||
}
|
||||
return invalid ? {
|
||||
'border-color': '#f56c6c !important'
|
||||
} : {};
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../styles/base.scss";
|
||||
|
||||
.container {
|
||||
padding: 10px;
|
||||
// font-family: "Alibaba PuHuiTi 2.0 55 Regular";
|
||||
}
|
||||
|
||||
.info-item {
|
||||
min-height: 60px;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #f2f2f2;
|
||||
background-color: $custom-bg-color;
|
||||
|
||||
.title {
|
||||
color: #409eff;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.target {
|
||||
margin-top: 10px;
|
||||
@include flex-space-between(row);
|
||||
|
||||
.imgbox {
|
||||
@include imgbox(30, 30);
|
||||
}
|
||||
|
||||
.number {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.options {
|
||||
margin-top: 10px;
|
||||
@include flex-space-around(row);
|
||||
|
||||
::v-deep {
|
||||
.u-button {
|
||||
width: 100px;
|
||||
height: 35px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.finishtime {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.header {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.time {
|
||||
margin-top: 10px;
|
||||
@include flex-left(row);
|
||||
|
||||
.hour {
|
||||
color: #f56c6c;
|
||||
margin-left: 5px;
|
||||
font-size: 28px;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.picklist {
|
||||
::v-deep {
|
||||
.uni-table-scroll {
|
||||
max-height: 360px;
|
||||
}
|
||||
|
||||
.uni-table-th {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.uni-table-td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.u-alert__content__title {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="subject">
|
||||
<view>{{title}}</view>
|
||||
<view class="options">
|
||||
<u-button type="success" icon="plus" size="mini" @click="addRow"></u-button>
|
||||
<u-button type="primary" icon="minus" size="mini" @click="removeRows"
|
||||
:disabled="selectedIndexs.length == 0"></u-button>
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-mt-4">
|
||||
<uni-table ref="table2" border stripe emptyText="暂未添加记录" type="selection" @selection-change="selectRowChange">
|
||||
<uni-tr>
|
||||
<uni-th width="120" align="center">物料名称</uni-th>
|
||||
<uni-th width="80" align="center">规格</uni-th>
|
||||
<uni-th width="100" align="center">数量</uni-th>
|
||||
</uni-tr>
|
||||
<uni-tr v-for="(item, index) in selectList" :key="index">
|
||||
<uni-td width="120" align="center">{{item.name}}</uni-td>
|
||||
<uni-td width="80" align="center">{{ item.spec }}</uni-td>
|
||||
<uni-td width="100" align="center">
|
||||
<u-input placeholder="数量" v-model="item.number" type="number" maxlength="3" @blur="formatNumber(item)"
|
||||
:custom-style="checkNumber(item.number)">
|
||||
<u-text :text="item.unit" slot="suffix" margin="0 3px 0 0"></u-text>
|
||||
</u-input>
|
||||
</uni-td>
|
||||
</uni-tr>
|
||||
</uni-table>
|
||||
</view>
|
||||
<!-- 物料选择弹框 -->
|
||||
<u-popup :show="selectorShow" mode="center" @close="selectorShow = false" closeable>
|
||||
<view class="select-box">
|
||||
<uni-section title="选择物料" type="line">
|
||||
<uni-data-select :localdata="selectRange" @change="changeRestore"></uni-data-select>
|
||||
</uni-section>
|
||||
</view>
|
||||
</u-popup>
|
||||
|
||||
<u-toast ref="uToast"></u-toast>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
// model: {
|
||||
// prop: 'formData',
|
||||
// event: 'changeData',
|
||||
// },
|
||||
inject: ['checkData'],
|
||||
props: {
|
||||
// formData: {
|
||||
// type: Number,
|
||||
// require: false,
|
||||
// default: 100
|
||||
// }
|
||||
name: {
|
||||
type: String,
|
||||
require: true,
|
||||
},
|
||||
picklist: {
|
||||
type: Array,
|
||||
require: false,
|
||||
default: () => []
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
require: false,
|
||||
default: "上报记录",
|
||||
},
|
||||
},
|
||||
options: {
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectorShow: false,
|
||||
datalist: [], // 物料数据
|
||||
selectList: [], // 选中列表
|
||||
selectedIndexs: [], // 已选中索引
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 深度克隆
|
||||
this.datalist = uni.$u.deepClone(this.picklist);
|
||||
},
|
||||
computed: {
|
||||
// 计算下拉选项
|
||||
selectRange() {
|
||||
return this.datalist.reduce((result, item) => {
|
||||
let obj = {
|
||||
value: item.id,
|
||||
text: item.name,
|
||||
disable: item.disable ? true : false
|
||||
};
|
||||
result.push(obj);
|
||||
return result;
|
||||
}, []);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 输入框失去焦点事件
|
||||
formatNumber(item) {
|
||||
item.number = this.$base.filterNonNumeric(item.number + '');
|
||||
},
|
||||
// 检测输入数字有效性
|
||||
checkNumber(val) {
|
||||
this.checkData(this,val);
|
||||
},
|
||||
// 返库记录选中项发生变化时
|
||||
selectRowChange(e) {
|
||||
this.selectedIndexs = e.detail.index;
|
||||
// console.log(this.selectedIndexs);
|
||||
},
|
||||
// 添加返库数据
|
||||
addRow() {
|
||||
this.selectorShow = true;
|
||||
},
|
||||
// 选中返库物料
|
||||
changeRestore(val) {
|
||||
let index = this.datalist.findIndex(item => item.id == val);
|
||||
if (index != -1) {
|
||||
let obj = Object.assign({}, this.datalist[index]);
|
||||
obj.number = 1; // 返库数量默认为1
|
||||
this.selectList.push(obj);
|
||||
}
|
||||
this.selectorShow = false;
|
||||
},
|
||||
// 删除返库数据
|
||||
removeRows() {
|
||||
this.$base.removeIndexesItems(this.selectedIndexs, this.selectList);
|
||||
console.log(this.selectList);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
selectList: {
|
||||
handler(newVal, oldVal) {
|
||||
console.log(newVal);
|
||||
let restoreIds = newVal.map(v => v.id);
|
||||
for (let index in this.datalist) {
|
||||
let id = this.datalist[index].id;
|
||||
// 赋予对象不存在的属性为响应式
|
||||
this.$set(this.datalist[index], 'disable', restoreIds.includes(id) ? 1 : 0);
|
||||
}
|
||||
// 通知父组件更新表单字段
|
||||
this.$emit('setFormItem', {name: this.name, value: newVal});
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.subject {
|
||||
margin: 10px 0;
|
||||
@include flex-space-between(row);
|
||||
|
||||
.options {
|
||||
@include flex-space-around(row);
|
||||
|
||||
::v-deep {
|
||||
.u-button {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
min-width: 30px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select-box {
|
||||
width: 300px;
|
||||
max-height: 360px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,176 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<uni-card title="完工报告表" padding="5" spacing="0" margin="0">
|
||||
<scroll-view class="scrollbox" :scroll-y="true" scroll-top="0">
|
||||
<view class="report-item">
|
||||
<text class="uni-my-2">成品完成量</text>
|
||||
<view class="target">
|
||||
<view class="imgbox">
|
||||
<image slot='cover' class="unimg" mode="aspectFill" :src="info.imgurl"></image>
|
||||
<text class="name">xxx产品</text>
|
||||
</view>
|
||||
<view class="number">
|
||||
<text>计划数量: </text>
|
||||
<text style="color:#409eff;font-size: 16px;margin-left: 8px;">30</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="completed">
|
||||
<view class="completed_item1">完成数量</view>
|
||||
<view class="completed_item2">
|
||||
<u-input placeholder="数量" v-model="form.completed" type="number" maxlength="3"
|
||||
@blur="formatNumber(form.completed)" :custom-style="checkNumber(form.completed)">
|
||||
<u-text :text="info.unit" slot="suffix" margin="0 3px 0 0"></u-text>
|
||||
</u-input>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="report-item">
|
||||
<reportItem :picklist="picklist" title="领料返库" name="restore" @setFormItem="setFormItem"></reportItem>
|
||||
</view>
|
||||
<view class="report-item">
|
||||
<reportItem :picklist="picklist" title="加工货损" name="damage" @setFormItem="setFormItem"></reportItem>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- 提交申请 -->
|
||||
<view slot="actions" class="actions">
|
||||
<u-button type="primary" :hairline="true" text="提交报告" @click="submitReport"></u-button>
|
||||
<u-button type="error" :hairline="true" text="再看看" @click="closeReport"></u-button>
|
||||
</view>
|
||||
</uni-card>
|
||||
|
||||
<u-toast ref="uToast"></u-toast>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import reportItem from './work-report-item.vue';
|
||||
export default {
|
||||
components: {
|
||||
reportItem
|
||||
},
|
||||
inject: ['checkData'],
|
||||
props: {
|
||||
picklist: {
|
||||
type: Array,
|
||||
require: false,
|
||||
default: () => []
|
||||
},
|
||||
info: {
|
||||
type: Object,
|
||||
require: false,
|
||||
default: () => []
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
require: false,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
options: {
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
restoreSelectorShow: false,
|
||||
damageSelectorShow: false,
|
||||
form: {
|
||||
completed: 1,
|
||||
restore: [],
|
||||
damage: [],
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 提交完工报告
|
||||
submitReport() {
|
||||
let params = uni.$u.deepClone(this.form);
|
||||
console.log(params); // todo
|
||||
this.$emit("update:show", false);
|
||||
},
|
||||
// 再看看
|
||||
closeReport() {
|
||||
this.$emit("update:show", false);
|
||||
},
|
||||
// 更新表单数据
|
||||
setFormItem(obj) {
|
||||
this.form[obj.name] = obj.value;
|
||||
},
|
||||
// 输入框失去焦点事件
|
||||
formatNumber(number) {
|
||||
this.form.completed = this.$base.filterNonNumeric(number + '');
|
||||
return this.form.completed;
|
||||
},
|
||||
// 检测输入数字有效性
|
||||
checkNumber(val) {
|
||||
this.checkData(this,val);
|
||||
}
|
||||
},
|
||||
// watch:{
|
||||
// form: {
|
||||
// handler(newVal, oldVal) {
|
||||
// console.log(newVal);
|
||||
// },
|
||||
// deep: true
|
||||
// }
|
||||
// }
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../styles/base.scss";
|
||||
|
||||
.scrollbox {
|
||||
height: 500px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.report-item {
|
||||
margin-bottom: 15px;
|
||||
|
||||
.target {
|
||||
margin-top: 10px;
|
||||
@include flex-space-between(row);
|
||||
|
||||
.imgbox {
|
||||
@include imgbox(30, 30);
|
||||
}
|
||||
|
||||
.number {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.completed {
|
||||
@include flex-space-between(row);
|
||||
height: 45px;
|
||||
border: 1px solid #e4e4e4;
|
||||
margin-top: 10px;
|
||||
|
||||
&_item1 {
|
||||
flex: 1;
|
||||
background-color: #f5f5f5;
|
||||
color: #666;
|
||||
font-weight: 700;
|
||||
line-height: 45px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
&_item2 {
|
||||
flex: 1;
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
margin-bottom: 20px;
|
||||
@include flex-space-around(row);
|
||||
|
||||
::v-deep {
|
||||
.u-button {
|
||||
width: 100px;
|
||||
height: 35px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
After Width: | Height: | Size: 894 B |
@ -0,0 +1,85 @@
|
||||
{
|
||||
"id": "uni-data-select",
|
||||
"displayName": "uni-data-select 下拉框选择器",
|
||||
"version": "1.0.6",
|
||||
"description": "通过数据驱动的下拉框选择器",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"select",
|
||||
"uni-data-select",
|
||||
"下拉框",
|
||||
"下拉选"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.1"
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": ["uni-load-more"],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "u",
|
||||
"app-nvue": "n"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "u",
|
||||
"百度": "u",
|
||||
"字节跳动": "u",
|
||||
"QQ": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,177 @@
|
||||
<template>
|
||||
<view class="uni-calendar-item__weeks-box" :class="{
|
||||
'uni-calendar-item--disable':weeks.disable,
|
||||
'uni-calendar-item--before-checked-x':weeks.beforeMultiple,
|
||||
'uni-calendar-item--multiple': weeks.multiple,
|
||||
'uni-calendar-item--after-checked-x':weeks.afterMultiple,
|
||||
}" @click="choiceDate(weeks)" @mouseenter="handleMousemove(weeks)">
|
||||
<view class="uni-calendar-item__weeks-box-item" :class="{
|
||||
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && (calendar.userChecked || !checkHover),
|
||||
'uni-calendar-item--checked-range-text': checkHover,
|
||||
'uni-calendar-item--before-checked':weeks.beforeMultiple,
|
||||
'uni-calendar-item--multiple': weeks.multiple,
|
||||
'uni-calendar-item--after-checked':weeks.afterMultiple,
|
||||
'uni-calendar-item--disable':weeks.disable,
|
||||
}">
|
||||
<text v-if="selected && weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
|
||||
<text class="uni-calendar-item__weeks-box-text uni-calendar-item__weeks-box-text-disable uni-calendar-item--checked-text">{{weeks.date}}</text>
|
||||
</view>
|
||||
<view :class="{'uni-calendar-item--today': weeks.isToday}"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
weeks: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
calendar: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
selected: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
checkHover: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
choiceDate(weeks) {
|
||||
this.$emit('change', weeks)
|
||||
},
|
||||
handleMousemove(weeks) {
|
||||
this.$emit('handleMouse', weeks)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" >
|
||||
$uni-primary: #007aff !default;
|
||||
|
||||
.uni-calendar-item__weeks-box {
|
||||
flex: 1;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 1px 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.uni-calendar-item__weeks-box-text {
|
||||
font-size: 14px;
|
||||
// font-family: Lato-Bold, Lato;
|
||||
font-weight: bold;
|
||||
color: darken($color: $uni-primary, $amount: 40%);
|
||||
}
|
||||
|
||||
.uni-calendar-item__weeks-box-item {
|
||||
position: relative;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
/* #ifdef H5 */
|
||||
cursor: pointer;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
|
||||
.uni-calendar-item__weeks-box-circle {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 8px;
|
||||
background-color: #dd524d;
|
||||
|
||||
}
|
||||
|
||||
.uni-calendar-item__weeks-box .uni-calendar-item--disable {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.uni-calendar-item--disable .uni-calendar-item__weeks-box-text-disable {
|
||||
color: #D1D1D1;
|
||||
}
|
||||
|
||||
.uni-calendar-item--today {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 17%;
|
||||
background-color: #dd524d;
|
||||
width:6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.uni-calendar-item--extra {
|
||||
color: #dd524d;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.uni-calendar-item__weeks-box .uni-calendar-item--checked {
|
||||
background-color: $uni-primary;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
border: 3px solid #fff;
|
||||
}
|
||||
|
||||
.uni-calendar-item--checked .uni-calendar-item--checked-text {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.uni-calendar-item--multiple .uni-calendar-item--checked-range-text {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.uni-calendar-item--multiple {
|
||||
background-color: #F6F7FC;
|
||||
// color: #fff;
|
||||
}
|
||||
|
||||
.uni-calendar-item--multiple .uni-calendar-item--before-checked,
|
||||
.uni-calendar-item--multiple .uni-calendar-item--after-checked {
|
||||
background-color: $uni-primary;
|
||||
border-radius: 50%;
|
||||
box-sizing: border-box;
|
||||
border: 3px solid #F6F7FC;
|
||||
}
|
||||
|
||||
.uni-calendar-item--before-checked .uni-calendar-item--checked-text,
|
||||
.uni-calendar-item--after-checked .uni-calendar-item--checked-text {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.uni-calendar-item--before-checked-x {
|
||||
border-top-left-radius: 50px;
|
||||
border-bottom-left-radius: 50px;
|
||||
box-sizing: border-box;
|
||||
background-color: #F6F7FC;
|
||||
}
|
||||
|
||||
.uni-calendar-item--after-checked-x {
|
||||
border-top-right-radius: 50px;
|
||||
border-bottom-right-radius: 50px;
|
||||
background-color: #F6F7FC;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,22 @@
|
||||
{
|
||||
"uni-datetime-picker.selectDate": "select date",
|
||||
"uni-datetime-picker.selectTime": "select time",
|
||||
"uni-datetime-picker.selectDateTime": "select date and time",
|
||||
"uni-datetime-picker.startDate": "start date",
|
||||
"uni-datetime-picker.endDate": "end date",
|
||||
"uni-datetime-picker.startTime": "start time",
|
||||
"uni-datetime-picker.endTime": "end time",
|
||||
"uni-datetime-picker.ok": "ok",
|
||||
"uni-datetime-picker.clear": "clear",
|
||||
"uni-datetime-picker.cancel": "cancel",
|
||||
"uni-datetime-picker.year": "-",
|
||||
"uni-datetime-picker.month": "",
|
||||
"uni-calender.MON": "MON",
|
||||
"uni-calender.TUE": "TUE",
|
||||
"uni-calender.WED": "WED",
|
||||
"uni-calender.THU": "THU",
|
||||
"uni-calender.FRI": "FRI",
|
||||
"uni-calender.SAT": "SAT",
|
||||
"uni-calender.SUN": "SUN",
|
||||
"uni-calender.confirm": "confirm"
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import en from './en.json'
|
||||
import zhHans from './zh-Hans.json'
|
||||
import zhHant from './zh-Hant.json'
|
||||
export default {
|
||||
en,
|
||||
'zh-Hans': zhHans,
|
||||
'zh-Hant': zhHant
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
{
|
||||
"uni-datetime-picker.selectDate": "选择日期",
|
||||
"uni-datetime-picker.selectTime": "选择时间",
|
||||
"uni-datetime-picker.selectDateTime": "选择日期时间",
|
||||
"uni-datetime-picker.startDate": "开始日期",
|
||||
"uni-datetime-picker.endDate": "结束日期",
|
||||
"uni-datetime-picker.startTime": "开始时间",
|
||||
"uni-datetime-picker.endTime": "结束时间",
|
||||
"uni-datetime-picker.ok": "确定",
|
||||
"uni-datetime-picker.clear": "清除",
|
||||
"uni-datetime-picker.cancel": "取消",
|
||||
"uni-datetime-picker.year": "年",
|
||||
"uni-datetime-picker.month": "月",
|
||||
"uni-calender.SUN": "日",
|
||||
"uni-calender.MON": "一",
|
||||
"uni-calender.TUE": "二",
|
||||
"uni-calender.WED": "三",
|
||||
"uni-calender.THU": "四",
|
||||
"uni-calender.FRI": "五",
|
||||
"uni-calender.SAT": "六",
|
||||
"uni-calender.confirm": "确认"
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
{
|
||||
"uni-datetime-picker.selectDate": "選擇日期",
|
||||
"uni-datetime-picker.selectTime": "選擇時間",
|
||||
"uni-datetime-picker.selectDateTime": "選擇日期時間",
|
||||
"uni-datetime-picker.startDate": "開始日期",
|
||||
"uni-datetime-picker.endDate": "結束日期",
|
||||
"uni-datetime-picker.startTime": "開始时间",
|
||||
"uni-datetime-picker.endTime": "結束时间",
|
||||
"uni-datetime-picker.ok": "確定",
|
||||
"uni-datetime-picker.clear": "清除",
|
||||
"uni-datetime-picker.cancel": "取消",
|
||||
"uni-datetime-picker.year": "年",
|
||||
"uni-datetime-picker.month": "月",
|
||||
"uni-calender.SUN": "日",
|
||||
"uni-calender.MON": "一",
|
||||
"uni-calender.TUE": "二",
|
||||
"uni-calender.WED": "三",
|
||||
"uni-calender.THU": "四",
|
||||
"uni-calender.FRI": "五",
|
||||
"uni-calender.SAT": "六",
|
||||
"uni-calender.confirm": "確認"
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,453 @@
|
||||
class Calendar {
|
||||
constructor({
|
||||
selected,
|
||||
startDate,
|
||||
endDate,
|
||||
range,
|
||||
} = {}) {
|
||||
// 当前日期
|
||||
this.date = this.getDateObj(new Date()) // 当前初入日期
|
||||
// 打点信息
|
||||
this.selected = selected || [];
|
||||
// 起始时间
|
||||
this.startDate = startDate
|
||||
// 终止时间
|
||||
this.endDate = endDate
|
||||
// 是否范围选择
|
||||
this.range = range
|
||||
// 多选状态
|
||||
this.cleanMultipleStatus()
|
||||
// 每周日期
|
||||
this.weeks = {}
|
||||
this.lastHover = false
|
||||
}
|
||||
/**
|
||||
* 设置日期
|
||||
* @param {Object} date
|
||||
*/
|
||||
setDate(date) {
|
||||
const selectDate = this.getDateObj(date)
|
||||
this.getWeeks(selectDate.fullDate)
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理多选状态
|
||||
*/
|
||||
cleanMultipleStatus() {
|
||||
this.multipleStatus = {
|
||||
before: '',
|
||||
after: '',
|
||||
data: []
|
||||
}
|
||||
}
|
||||
|
||||
setStartDate(startDate) {
|
||||
this.startDate = startDate
|
||||
}
|
||||
|
||||
setEndDate(endDate) {
|
||||
this.endDate = endDate
|
||||
}
|
||||
|
||||
getPreMonthObj(date){
|
||||
date = fixIosDateFormat(date)
|
||||
date = new Date(date)
|
||||
|
||||
const oldMonth = date.getMonth()
|
||||
date.setMonth(oldMonth - 1)
|
||||
const newMonth = date.getMonth()
|
||||
if(oldMonth !== 0 && newMonth - oldMonth === 0){
|
||||
date.setMonth(newMonth - 1)
|
||||
}
|
||||
return this.getDateObj(date)
|
||||
}
|
||||
getNextMonthObj(date){
|
||||
date = fixIosDateFormat(date)
|
||||
date = new Date(date)
|
||||
|
||||
const oldMonth = date.getMonth()
|
||||
date.setMonth(oldMonth + 1)
|
||||
const newMonth = date.getMonth()
|
||||
if(newMonth - oldMonth > 1){
|
||||
date.setMonth(newMonth - 1)
|
||||
}
|
||||
return this.getDateObj(date)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定格式Date对象
|
||||
*/
|
||||
getDateObj(date) {
|
||||
date = fixIosDateFormat(date)
|
||||
date = new Date(date)
|
||||
|
||||
return {
|
||||
fullDate: getDate(date),
|
||||
year: date.getFullYear(),
|
||||
month: addZero(date.getMonth() + 1),
|
||||
date: addZero(date.getDate()),
|
||||
day: date.getDay()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上一个月日期集合
|
||||
*/
|
||||
getPreMonthDays(amount, dateObj) {
|
||||
const result = []
|
||||
for (let i = amount - 1; i >= 0; i--) {
|
||||
const month = dateObj.month > 1 ? dateObj.month -1 : 12
|
||||
const year = month === 12 ? dateObj.year - 1 : dateObj.year
|
||||
const date = new Date(year,month,-i).getDate()
|
||||
const fullDate = `${year}-${addZero(month)}-${addZero(date)}`
|
||||
let multiples = this.multipleStatus.data
|
||||
let multiplesStatus = -1
|
||||
if (this.range && multiples) {
|
||||
multiplesStatus = multiples.findIndex((item) => {
|
||||
return this.dateEqual(item, fullDate)
|
||||
})
|
||||
}
|
||||
const checked = multiplesStatus !== -1
|
||||
// 获取打点信息
|
||||
const extraInfo = this.selected && this.selected.find((item) => {
|
||||
if (this.dateEqual(fullDate, item.date)) {
|
||||
return item
|
||||
}
|
||||
})
|
||||
result.push({
|
||||
fullDate,
|
||||
year,
|
||||
month,
|
||||
date,
|
||||
multiple: this.range ? checked : false,
|
||||
beforeMultiple: this.isLogicBefore(fullDate, this.multipleStatus.before, this.multipleStatus.after),
|
||||
afterMultiple: this.isLogicAfter(fullDate, this.multipleStatus.before, this.multipleStatus.after),
|
||||
disable: (this.startDate && !dateCompare(this.startDate, fullDate)) || (this.endDate && !dateCompare(fullDate,this.endDate)),
|
||||
isToday: fullDate === this.date.fullDate,
|
||||
userChecked: false,
|
||||
extraInfo
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
/**
|
||||
* 获取本月日期集合
|
||||
*/
|
||||
getCurrentMonthDays(amount, dateObj) {
|
||||
const result = []
|
||||
const fullDate = this.date.fullDate
|
||||
for (let i = 1; i <= amount; i++) {
|
||||
const currentDate = `${dateObj.year}-${dateObj.month}-${addZero(i)}`
|
||||
const isToday = fullDate === currentDate
|
||||
// 获取打点信息
|
||||
const extraInfo = this.selected && this.selected.find((item) => {
|
||||
if (this.dateEqual(currentDate, item.date)) {
|
||||
return item
|
||||
}
|
||||
})
|
||||
|
||||
// 日期禁用
|
||||
let disableBefore = true
|
||||
let disableAfter = true
|
||||
if (this.startDate) {
|
||||
disableBefore = dateCompare(this.startDate, currentDate)
|
||||
}
|
||||
|
||||
if (this.endDate) {
|
||||
disableAfter = dateCompare(currentDate, this.endDate)
|
||||
}
|
||||
|
||||
let multiples = this.multipleStatus.data
|
||||
let multiplesStatus = -1
|
||||
if (this.range && multiples) {
|
||||
multiplesStatus = multiples.findIndex((item) => {
|
||||
return this.dateEqual(item, currentDate)
|
||||
})
|
||||
}
|
||||
const checked = multiplesStatus !== -1
|
||||
|
||||
result.push({
|
||||
fullDate: currentDate,
|
||||
year: dateObj.year,
|
||||
month: dateObj.month,
|
||||
date: i,
|
||||
multiple: this.range ? checked : false,
|
||||
beforeMultiple: this.isLogicBefore(currentDate, this.multipleStatus.before, this.multipleStatus.after),
|
||||
afterMultiple: this.isLogicAfter(currentDate, this.multipleStatus.before, this.multipleStatus.after),
|
||||
disable: (this.startDate && !dateCompare(this.startDate, currentDate)) || (this.endDate && !dateCompare(currentDate,this.endDate)),
|
||||
isToday,
|
||||
userChecked: false,
|
||||
extraInfo
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
/**
|
||||
* 获取下一个月日期集合
|
||||
*/
|
||||
_getNextMonthDays(amount, dateObj) {
|
||||
const result = []
|
||||
const month = dateObj.month + 1
|
||||
for (let i = 1; i <= amount; i++) {
|
||||
const month = dateObj.month === 12 ? 1 : dateObj.month*1 + 1
|
||||
const year = month === 1 ? dateObj.year + 1 : dateObj.year
|
||||
const fullDate = `${year}-${addZero(month)}-${addZero(i)}`
|
||||
let multiples = this.multipleStatus.data
|
||||
let multiplesStatus = -1
|
||||
if (this.range && multiples) {
|
||||
multiplesStatus = multiples.findIndex((item) => {
|
||||
return this.dateEqual(item, fullDate)
|
||||
})
|
||||
}
|
||||
const checked = multiplesStatus !== -1
|
||||
// 获取打点信息
|
||||
const extraInfo = this.selected && this.selected.find((item) => {
|
||||
if (this.dateEqual(fullDate, item.date)) {
|
||||
return item
|
||||
}
|
||||
})
|
||||
result.push({
|
||||
fullDate,
|
||||
year,
|
||||
date: i,
|
||||
month,
|
||||
multiple: this.range ? checked : false,
|
||||
beforeMultiple: this.isLogicBefore(fullDate, this.multipleStatus.before, this.multipleStatus.after),
|
||||
afterMultiple: this.isLogicAfter(fullDate, this.multipleStatus.before, this.multipleStatus.after),
|
||||
disable: (this.startDate && !dateCompare(this.startDate, fullDate)) || (this.endDate && !dateCompare(fullDate,this.endDate)),
|
||||
isToday: fullDate === this.date.fullDate,
|
||||
userChecked: false,
|
||||
extraInfo
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前日期详情
|
||||
* @param {Object} date
|
||||
*/
|
||||
getInfo(date) {
|
||||
if (!date) {
|
||||
date = new Date()
|
||||
}
|
||||
|
||||
return this.calendar.find(item => item.fullDate === this.getDateObj(date).fullDate)
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较时间是否相等
|
||||
*/
|
||||
dateEqual(before, after) {
|
||||
before = new Date(fixIosDateFormat(before))
|
||||
after = new Date(fixIosDateFormat(after))
|
||||
return before.valueOf() === after.valueOf()
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较真实起始日期
|
||||
*/
|
||||
|
||||
isLogicBefore(currentDate, before, after) {
|
||||
let logicBefore = before
|
||||
if (before && after) {
|
||||
logicBefore = dateCompare(before, after) ? before : after
|
||||
}
|
||||
return this.dateEqual(logicBefore, currentDate)
|
||||
}
|
||||
|
||||
isLogicAfter(currentDate, before, after) {
|
||||
let logicAfter = after
|
||||
if (before && after) {
|
||||
logicAfter = dateCompare(before, after) ? after : before
|
||||
}
|
||||
return this.dateEqual(logicAfter, currentDate)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取日期范围内所有日期
|
||||
* @param {Object} begin
|
||||
* @param {Object} end
|
||||
*/
|
||||
geDateAll(begin, end) {
|
||||
var arr = []
|
||||
var ab = begin.split('-')
|
||||
var ae = end.split('-')
|
||||
var db = new Date()
|
||||
db.setFullYear(ab[0], ab[1] - 1, ab[2])
|
||||
var de = new Date()
|
||||
de.setFullYear(ae[0], ae[1] - 1, ae[2])
|
||||
var unixDb = db.getTime() - 24 * 60 * 60 * 1000
|
||||
var unixDe = de.getTime() - 24 * 60 * 60 * 1000
|
||||
for (var k = unixDb; k <= unixDe;) {
|
||||
k = k + 24 * 60 * 60 * 1000
|
||||
arr.push(this.getDateObj(new Date(parseInt(k))).fullDate)
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取多选状态
|
||||
*/
|
||||
setMultiple(fullDate) {
|
||||
if (!this.range) return
|
||||
|
||||
let {
|
||||
before,
|
||||
after
|
||||
} = this.multipleStatus
|
||||
if (before && after) {
|
||||
if (!this.lastHover) {
|
||||
this.lastHover = true
|
||||
return
|
||||
}
|
||||
this.multipleStatus.before = fullDate
|
||||
this.multipleStatus.after = ''
|
||||
this.multipleStatus.data = []
|
||||
this.multipleStatus.fulldate = ''
|
||||
this.lastHover = false
|
||||
} else {
|
||||
if (!before) {
|
||||
this.multipleStatus.before = fullDate
|
||||
this.lastHover = false
|
||||
} else {
|
||||
this.multipleStatus.after = fullDate
|
||||
if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
|
||||
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus
|
||||
.after);
|
||||
} else {
|
||||
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus
|
||||
.before);
|
||||
}
|
||||
this.lastHover = true
|
||||
}
|
||||
}
|
||||
this.getWeeks(fullDate)
|
||||
}
|
||||
|
||||
/**
|
||||
* 鼠标 hover 更新多选状态
|
||||
*/
|
||||
setHoverMultiple(fullDate) {
|
||||
if (!this.range || this.lastHover) return
|
||||
|
||||
const { before } = this.multipleStatus
|
||||
|
||||
if (!before) {
|
||||
this.multipleStatus.before = fullDate
|
||||
} else {
|
||||
this.multipleStatus.after = fullDate
|
||||
if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
|
||||
this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
|
||||
} else {
|
||||
this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
|
||||
}
|
||||
}
|
||||
this.getWeeks(fullDate)
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新默认值多选状态
|
||||
*/
|
||||
setDefaultMultiple(before, after) {
|
||||
this.multipleStatus.before = before
|
||||
this.multipleStatus.after = after
|
||||
if (before && after) {
|
||||
if (dateCompare(before, after)) {
|
||||
this.multipleStatus.data = this.geDateAll(before, after);
|
||||
this.getWeeks(after)
|
||||
} else {
|
||||
this.multipleStatus.data = this.geDateAll(after, before);
|
||||
this.getWeeks(before)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取每周数据
|
||||
* @param {Object} dateData
|
||||
*/
|
||||
getWeeks(dateData) {
|
||||
const {
|
||||
year,
|
||||
month,
|
||||
} = this.getDateObj(dateData)
|
||||
|
||||
const preMonthDayAmount = new Date(year, month - 1, 1).getDay()
|
||||
const preMonthDays = this.getPreMonthDays(preMonthDayAmount, this.getDateObj(dateData))
|
||||
|
||||
const currentMonthDayAmount = new Date(year, month, 0).getDate()
|
||||
const currentMonthDays = this.getCurrentMonthDays(currentMonthDayAmount, this.getDateObj(dateData))
|
||||
|
||||
const nextMonthDayAmount = 42 - preMonthDayAmount - currentMonthDayAmount
|
||||
const nextMonthDays = this._getNextMonthDays(nextMonthDayAmount, this.getDateObj(dateData))
|
||||
|
||||
const calendarDays = [...preMonthDays, ...currentMonthDays, ...nextMonthDays]
|
||||
|
||||
const weeks = new Array(6)
|
||||
for (let i = 0; i < calendarDays.length; i++) {
|
||||
const index = Math.floor(i / 7)
|
||||
if(!weeks[index]){
|
||||
weeks[index] = new Array(7)
|
||||
}
|
||||
weeks[index][i % 7] = calendarDays[i]
|
||||
}
|
||||
|
||||
this.calendar = calendarDays
|
||||
this.weeks = weeks
|
||||
}
|
||||
}
|
||||
|
||||
function getDateTime(date, hideSecond){
|
||||
return `${getDate(date)} ${getTime(date, hideSecond)}`
|
||||
}
|
||||
|
||||
function getDate(date) {
|
||||
date = fixIosDateFormat(date)
|
||||
date = new Date(date)
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth()+1
|
||||
const day = date.getDate()
|
||||
return `${year}-${addZero(month)}-${addZero(day)}`
|
||||
}
|
||||
|
||||
function getTime(date, hideSecond){
|
||||
date = fixIosDateFormat(date)
|
||||
date = new Date(date)
|
||||
const hour = date.getHours()
|
||||
const minute = date.getMinutes()
|
||||
const second = date.getSeconds()
|
||||
return hideSecond ? `${addZero(hour)}:${addZero(minute)}` : `${addZero(hour)}:${addZero(minute)}:${addZero(second)}`
|
||||
}
|
||||
|
||||
function addZero(num) {
|
||||
if(num < 10){
|
||||
num = `0${num}`
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
function getDefaultSecond(hideSecond) {
|
||||
return hideSecond ? '00:00' : '00:00:00'
|
||||
}
|
||||
|
||||
function dateCompare(startDate, endDate) {
|
||||
startDate = new Date(fixIosDateFormat(startDate))
|
||||
endDate = new Date(fixIosDateFormat(endDate))
|
||||
return startDate <= endDate
|
||||
}
|
||||
|
||||
function checkDate(date){
|
||||
const dateReg = /((19|20)\d{2})(-|\/)\d{1,2}(-|\/)\d{1,2}/g
|
||||
return date.match(dateReg)
|
||||
}
|
||||
|
||||
const dateTimeReg = /^\d{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])( [0-5]?[0-9]:[0-5]?[0-9]:[0-5]?[0-9])?$/
|
||||
function fixIosDateFormat(value) {
|
||||
if (typeof value === 'string' && dateTimeReg.test(value)) {
|
||||
value = value.replace(/-/g, '/')
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
export {Calendar, getDateTime, getDate, getTime, addZero, getDefaultSecond, dateCompare, checkDate, fixIosDateFormat}
|
@ -0,0 +1,87 @@
|
||||
{
|
||||
"id": "uni-datetime-picker",
|
||||
"displayName": "uni-datetime-picker 日期选择器",
|
||||
"version": "2.2.24",
|
||||
"description": "uni-datetime-picker 日期时间选择器,支持日历,支持范围选择",
|
||||
"keywords": [
|
||||
"uni-datetime-picker",
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"日期时间选择器",
|
||||
"日期时间"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uni-scss",
|
||||
"uni-icons"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "n"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"uni-load-more.contentdown": "Pull up to show more",
|
||||
"uni-load-more.contentrefresh": "loading...",
|
||||
"uni-load-more.contentnomore": "No more data"
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import en from './en.json'
|
||||
import zhHans from './zh-Hans.json'
|
||||
import zhHant from './zh-Hant.json'
|
||||
export default {
|
||||
en,
|
||||
'zh-Hans': zhHans,
|
||||
'zh-Hant': zhHant
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"uni-load-more.contentdown": "上拉显示更多",
|
||||
"uni-load-more.contentrefresh": "正在加载...",
|
||||
"uni-load-more.contentnomore": "没有更多数据了"
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"uni-load-more.contentdown": "上拉顯示更多",
|
||||
"uni-load-more.contentrefresh": "正在加載...",
|
||||
"uni-load-more.contentnomore": "沒有更多數據了"
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,86 @@
|
||||
{
|
||||
"id": "uni-load-more",
|
||||
"displayName": "uni-load-more 加载更多",
|
||||
"version": "1.3.3",
|
||||
"description": "LoadMore 组件,常用在列表里面,做滚动加载使用。",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"加载更多",
|
||||
"load-more"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"category": [
|
||||
"前端组件",
|
||||
"通用组件"
|
||||
],
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": ["uni-scss"],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<!-- #ifdef H5 -->
|
||||
<tbody>
|
||||
<slot></slot>
|
||||
</tbody>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef H5 -->
|
||||
<view><slot></slot></view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'uniBody',
|
||||
options: {
|
||||
virtualHost: true
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
created() {},
|
||||
methods: {}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<!-- #ifdef H5 -->
|
||||
<td class="uni-table-td" :rowspan="rowspan" :colspan="colspan" :class="{'table--border':border}" :style="{width:width + 'px','text-align':align}">
|
||||
<slot></slot>
|
||||
</td>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef H5 -->
|
||||
<!-- :class="{'table--border':border}" -->
|
||||
<view class="uni-table-td" :class="{'table--border':border}" :style="{width:width + 'px','text-align':align}">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Td 单元格
|
||||
* @description 表格中的标准单元格组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=3270
|
||||
* @property {Number} align = [left|center|right] 单元格对齐方式
|
||||
*/
|
||||
export default {
|
||||
name: 'uniTd',
|
||||
options: {
|
||||
virtualHost: true
|
||||
},
|
||||
props: {
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
align: {
|
||||
type: String,
|
||||
default: 'left'
|
||||
},
|
||||
rowspan: {
|
||||
type: [Number,String],
|
||||
default: 1
|
||||
},
|
||||
colspan: {
|
||||
type: [Number,String],
|
||||
default: 1
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
border: false
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.root = this.getTable()
|
||||
this.border = this.root.border
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 获取父元素实例
|
||||
*/
|
||||
getTable() {
|
||||
let parent = this.$parent;
|
||||
let parentName = parent.$options.name;
|
||||
while (parentName !== 'uniTable') {
|
||||
parent = parent.$parent;
|
||||
if (!parent) return false;
|
||||
parentName = parent.$options.name;
|
||||
}
|
||||
return parent;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
$border-color:#EBEEF5;
|
||||
|
||||
.uni-table-td {
|
||||
display: table-cell;
|
||||
padding: 8px 10px;
|
||||
font-size: 14px;
|
||||
border-bottom: 1px $border-color solid;
|
||||
font-weight: 400;
|
||||
color: #606266;
|
||||
line-height: 23px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.table--border {
|
||||
border-right: 1px $border-color solid;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,511 @@
|
||||
<template>
|
||||
<view class="uni-filter-dropdown">
|
||||
<view class="dropdown-btn" @click="onDropdown">
|
||||
<view class="icon-select" :class="{active: canReset}" v-if="isSelect || isRange"></view>
|
||||
<view class="icon-search" :class="{active: canReset}" v-if="isSearch">
|
||||
<view class="icon-search-0"></view>
|
||||
<view class="icon-search-1"></view>
|
||||
</view>
|
||||
<view class="icon-calendar" :class="{active: canReset}" v-if="isDate">
|
||||
<view class="icon-calendar-0"></view>
|
||||
<view class="icon-calendar-1"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="uni-dropdown-cover" v-if="isOpened" @click="handleClose"></view>
|
||||
<view class="dropdown-popup dropdown-popup-right" v-if="isOpened" @click.stop>
|
||||
<!-- select-->
|
||||
<view v-if="isSelect" class="list">
|
||||
<label class="flex-r a-i-c list-item" v-for="(item,index) in dataList" :key="index"
|
||||
@click="onItemClick($event, index)">
|
||||
<check-box class="check" :checked="item.checked" />
|
||||
<view class="checklist-content">
|
||||
<text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text>
|
||||
</view>
|
||||
</label>
|
||||
</view>
|
||||
<view v-if="isSelect" class="flex-r opera-area">
|
||||
<view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleSelectReset">
|
||||
{{resource.reset}}</view>
|
||||
<view class="flex-f btn btn-submit" @click="handleSelectSubmit">{{resource.submit}}</view>
|
||||
</view>
|
||||
<!-- search -->
|
||||
<view v-if="isSearch" class="search-area">
|
||||
<input class="search-input" v-model="filterValue" />
|
||||
</view>
|
||||
<view v-if="isSearch" class="flex-r opera-area">
|
||||
<view class="flex-f btn btn-submit" @click="handleSearchSubmit">{{resource.search}}</view>
|
||||
<view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleSearchReset">
|
||||
{{resource.reset}}</view>
|
||||
</view>
|
||||
<!-- range -->
|
||||
<view v-if="isRange">
|
||||
<view class="input-label">{{resource.gt}}</view>
|
||||
<input class="input" v-model="gtValue" />
|
||||
<view class="input-label">{{resource.lt}}</view>
|
||||
<input class="input" v-model="ltValue" />
|
||||
</view>
|
||||
<view v-if="isRange" class="flex-r opera-area">
|
||||
<view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleRangeReset">
|
||||
{{resource.reset}}</view>
|
||||
<view class="flex-f btn btn-submit" @click="handleRangeSubmit">{{resource.submit}}</view>
|
||||
</view>
|
||||
<!-- date -->
|
||||
<view v-if="isDate">
|
||||
<uni-datetime-picker ref="datetimepicker" :value="dateRange" type="datetimerange" return-type="timestamp" @change="datetimechange" @maskClick="timepickerclose">
|
||||
<view></view>
|
||||
</uni-datetime-picker>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import checkBox from '../uni-tr/table-checkbox.vue'
|
||||
|
||||
const resource = {
|
||||
"reset": "重置",
|
||||
"search": "搜索",
|
||||
"submit": "确定",
|
||||
"filter": "筛选",
|
||||
"gt": "大于等于",
|
||||
"lt": "小于等于",
|
||||
"date": "日期范围"
|
||||
}
|
||||
|
||||
const DropdownType = {
|
||||
Select: "select",
|
||||
Search: "search",
|
||||
Range: "range",
|
||||
Date: "date",
|
||||
Timestamp: "timestamp"
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'FilterDropdown',
|
||||
emits:['change'],
|
||||
components: {
|
||||
checkBox
|
||||
},
|
||||
options: {
|
||||
virtualHost: true
|
||||
},
|
||||
props: {
|
||||
filterType: {
|
||||
type: String,
|
||||
default: DropdownType.Select
|
||||
},
|
||||
filterData: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'default'
|
||||
},
|
||||
map: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {
|
||||
text: 'text',
|
||||
value: 'value'
|
||||
}
|
||||
}
|
||||
},
|
||||
filterDefaultValue: {
|
||||
type: [Array,String],
|
||||
default () {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
canReset() {
|
||||
if (this.isSearch) {
|
||||
return this.filterValue.length > 0
|
||||
}
|
||||
if (this.isSelect) {
|
||||
return this.checkedValues.length > 0
|
||||
}
|
||||
if (this.isRange) {
|
||||
return (this.gtValue.length > 0 && this.ltValue.length > 0)
|
||||
}
|
||||
if (this.isDate) {
|
||||
return this.dateSelect.length > 0
|
||||
}
|
||||
return false
|
||||
},
|
||||
isSelect() {
|
||||
return this.filterType === DropdownType.Select
|
||||
},
|
||||
isSearch() {
|
||||
return this.filterType === DropdownType.Search
|
||||
},
|
||||
isRange() {
|
||||
return this.filterType === DropdownType.Range
|
||||
},
|
||||
isDate() {
|
||||
return (this.filterType === DropdownType.Date || this.filterType === DropdownType.Timestamp)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
filterData(newVal) {
|
||||
this._copyFilters()
|
||||
},
|
||||
indeterminate(newVal) {
|
||||
this.isIndeterminate = newVal
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
resource,
|
||||
enabled: true,
|
||||
isOpened: false,
|
||||
dataList: [],
|
||||
filterValue: this.filterDefaultValue,
|
||||
checkedValues: [],
|
||||
gtValue: '',
|
||||
ltValue: '',
|
||||
dateRange: [],
|
||||
dateSelect: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this._copyFilters()
|
||||
},
|
||||
methods: {
|
||||
_copyFilters() {
|
||||
let dl = JSON.parse(JSON.stringify(this.filterData))
|
||||
for (let i = 0; i < dl.length; i++) {
|
||||
if (dl[i].checked === undefined) {
|
||||
dl[i].checked = false
|
||||
}
|
||||
}
|
||||
this.dataList = dl
|
||||
},
|
||||
openPopup() {
|
||||
this.isOpened = true
|
||||
if (this.isDate) {
|
||||
this.$nextTick(() => {
|
||||
if (!this.dateRange.length) {
|
||||
this.resetDate()
|
||||
}
|
||||
this.$refs.datetimepicker.show()
|
||||
})
|
||||
}
|
||||
},
|
||||
closePopup() {
|
||||
this.isOpened = false
|
||||
},
|
||||
handleClose(e) {
|
||||
this.closePopup()
|
||||
},
|
||||
resetDate() {
|
||||
let date = new Date()
|
||||
let dateText = date.toISOString().split('T')[0]
|
||||
this.dateRange = [dateText + ' 0:00:00', dateText + ' 23:59:59']
|
||||
},
|
||||
onDropdown(e) {
|
||||
this.openPopup()
|
||||
},
|
||||
onItemClick(e, index) {
|
||||
let items = this.dataList
|
||||
let listItem = items[index]
|
||||
if (listItem.checked === undefined) {
|
||||
items[index].checked = true
|
||||
} else {
|
||||
items[index].checked = !listItem.checked
|
||||
}
|
||||
|
||||
let checkvalues = []
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i]
|
||||
if (item.checked) {
|
||||
checkvalues.push(item.value)
|
||||
}
|
||||
}
|
||||
this.checkedValues = checkvalues
|
||||
},
|
||||
datetimechange(e) {
|
||||
this.closePopup()
|
||||
this.dateRange = e
|
||||
this.dateSelect = e
|
||||
this.$emit('change', {
|
||||
filterType: this.filterType,
|
||||
filter: e
|
||||
})
|
||||
},
|
||||
timepickerclose(e) {
|
||||
this.closePopup()
|
||||
},
|
||||
handleSelectSubmit() {
|
||||
this.closePopup()
|
||||
this.$emit('change', {
|
||||
filterType: this.filterType,
|
||||
filter: this.checkedValues
|
||||
})
|
||||
},
|
||||
handleSelectReset() {
|
||||
if (!this.canReset) {
|
||||
return;
|
||||
}
|
||||
var items = this.dataList
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
let item = items[i]
|
||||
this.$set(item, 'checked', false)
|
||||
}
|
||||
this.checkedValues = []
|
||||
this.handleSelectSubmit()
|
||||
},
|
||||
handleSearchSubmit() {
|
||||
this.closePopup()
|
||||
this.$emit('change', {
|
||||
filterType: this.filterType,
|
||||
filter: this.filterValue
|
||||
})
|
||||
},
|
||||
handleSearchReset() {
|
||||
if (!this.canReset) {
|
||||
return;
|
||||
}
|
||||
this.filterValue = ''
|
||||
this.handleSearchSubmit()
|
||||
},
|
||||
handleRangeSubmit(isReset) {
|
||||
this.closePopup()
|
||||
this.$emit('change', {
|
||||
filterType: this.filterType,
|
||||
filter: isReset === true ? [] : [parseInt(this.gtValue), parseInt(this.ltValue)]
|
||||
})
|
||||
},
|
||||
handleRangeReset() {
|
||||
if (!this.canReset) {
|
||||
return;
|
||||
}
|
||||
this.gtValue = ''
|
||||
this.ltValue = ''
|
||||
this.handleRangeSubmit(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
$uni-primary: #1890ff !default;
|
||||
|
||||
.flex-r {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.flex-f {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.a-i-c {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.j-c-c {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon-select {
|
||||
width: 14px;
|
||||
height: 16px;
|
||||
border: solid 6px transparent;
|
||||
border-top: solid 6px #ddd;
|
||||
border-bottom: none;
|
||||
background-color: #ddd;
|
||||
background-clip: content-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.icon-select.active {
|
||||
background-color: $uni-primary;
|
||||
border-top-color: $uni-primary;
|
||||
}
|
||||
|
||||
.icon-search {
|
||||
width: 12px;
|
||||
height: 16px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.icon-search-0 {
|
||||
border: 2px solid #ddd;
|
||||
border-radius: 8px;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
|
||||
.icon-search-1 {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 0;
|
||||
width: 1px;
|
||||
height: 7px;
|
||||
background-color: #ddd;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.icon-search.active .icon-search-0 {
|
||||
border-color: $uni-primary;
|
||||
}
|
||||
|
||||
.icon-search.active .icon-search-1 {
|
||||
background-color: $uni-primary;
|
||||
}
|
||||
|
||||
.icon-calendar {
|
||||
color: #ddd;
|
||||
width: 14px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.icon-calendar-0 {
|
||||
height: 4px;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 1px;
|
||||
background-color: #ddd;
|
||||
border-radius: 2px 2px 1px 1px;
|
||||
position: relative;
|
||||
}
|
||||
.icon-calendar-0:before, .icon-calendar-0:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
width: 4px;
|
||||
height: 3px;
|
||||
border-radius: 1px;
|
||||
background-color: #ddd;
|
||||
}
|
||||
.icon-calendar-0:before {
|
||||
left: 2px;
|
||||
}
|
||||
.icon-calendar-0:after {
|
||||
right: 2px;
|
||||
}
|
||||
|
||||
.icon-calendar-1 {
|
||||
height: 9px;
|
||||
background-color: #ddd;
|
||||
border-radius: 1px 1px 2px 2px;
|
||||
}
|
||||
|
||||
.icon-calendar.active {
|
||||
color: $uni-primary;
|
||||
}
|
||||
|
||||
.icon-calendar.active .icon-calendar-0,
|
||||
.icon-calendar.active .icon-calendar-1,
|
||||
.icon-calendar.active .icon-calendar-0:before,
|
||||
.icon-calendar.active .icon-calendar-0:after {
|
||||
background-color: $uni-primary;
|
||||
}
|
||||
|
||||
.uni-filter-dropdown {
|
||||
position: relative;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.dropdown-popup {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d;
|
||||
min-width: 150px;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.dropdown-popup-left {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.dropdown-popup-right {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.uni-dropdown-cover {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: transparent;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.list {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.list-item {
|
||||
padding: 5px 10px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.list-item:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.check {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.search-area {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
font-size: 12px;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 3px;
|
||||
padding: 2px 5px;
|
||||
min-width: 150px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
margin: 10px 10px 5px 10px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.input {
|
||||
font-size: 12px;
|
||||
border: 1px solid #f0f0f0;
|
||||
border-radius: 3px;
|
||||
margin: 10px;
|
||||
padding: 2px 5px;
|
||||
min-width: 150px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.opera-area {
|
||||
cursor: default;
|
||||
border-top: 1px solid #ddd;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.opera-area .btn {
|
||||
font-size: 12px;
|
||||
border-radius: 3px;
|
||||
margin: 5px;
|
||||
padding: 4px 4px;
|
||||
}
|
||||
|
||||
.btn-default {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.btn-default.disable {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.btn-submit {
|
||||
background-color: $uni-primary;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<!-- #ifdef H5 -->
|
||||
<thead class="uni-table-thead">
|
||||
<tr class="uni-table-tr">
|
||||
<th :rowspan="rowspan" colspan="1" class="checkbox" :class="{ 'tr-table--border': border }">
|
||||
<table-checkbox :indeterminate="indeterminate" :checked="checked" @checkboxSelected="checkboxSelected"></table-checkbox>
|
||||
</th>
|
||||
</tr>
|
||||
<slot></slot>
|
||||
</thead>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef H5 -->
|
||||
<view class="uni-table-thead"><slot></slot></view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import tableCheckbox from '../uni-tr/table-checkbox.vue'
|
||||
export default {
|
||||
name: 'uniThead',
|
||||
components: {
|
||||
tableCheckbox
|
||||
},
|
||||
options: {
|
||||
virtualHost: true
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
border: false,
|
||||
selection: false,
|
||||
rowspan: 1,
|
||||
indeterminate: false,
|
||||
checked: false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.root = this.getTable()
|
||||
// #ifdef H5
|
||||
this.root.theadChildren = this
|
||||
// #endif
|
||||
this.border = this.root.border
|
||||
this.selection = this.root.type
|
||||
},
|
||||
methods: {
|
||||
init(self) {
|
||||
this.rowspan++
|
||||
},
|
||||
checkboxSelected(e) {
|
||||
this.indeterminate = false
|
||||
const backIndexData = this.root.backIndexData
|
||||
const data = this.root.trChildren.filter(v => !v.disabled && v.keyValue)
|
||||
if (backIndexData.length === data.length) {
|
||||
this.checked = false
|
||||
this.root.clearSelection()
|
||||
} else {
|
||||
this.checked = true
|
||||
this.root.selectionAll()
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 获取父元素实例
|
||||
*/
|
||||
getTable(name = 'uniTable') {
|
||||
let parent = this.$parent
|
||||
let parentName = parent.$options.name
|
||||
while (parentName !== name) {
|
||||
parent = parent.$parent
|
||||
if (!parent) return false
|
||||
parentName = parent.$options.name
|
||||
}
|
||||
return parent
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
$border-color: #ebeef5;
|
||||
|
||||
.uni-table-thead {
|
||||
display: table-header-group;
|
||||
}
|
||||
|
||||
.uni-table-tr {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: table-row;
|
||||
transition: all 0.3s;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
border: 1px red solid;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
padding: 0 8px;
|
||||
width: 26px;
|
||||
padding-left: 12px;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
/* #endif */
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
border-bottom: 1px $border-color solid;
|
||||
font-size: 14px;
|
||||
// text-align: center;
|
||||
}
|
||||
|
||||
.tr-table--border {
|
||||
border-right: 1px $border-color solid;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-table-tr {
|
||||
::v-deep .uni-table-th {
|
||||
&.table--border:last-child {
|
||||
// border-right: none;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .uni-table-td {
|
||||
&.table--border:last-child {
|
||||
// border-right: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<view class="uni-table-checkbox" @click="selected">
|
||||
<view v-if="!indeterminate" class="checkbox__inner" :class="{'is-checked':isChecked,'is-disable':isDisabled}">
|
||||
<view class="checkbox__inner-icon"></view>
|
||||
</view>
|
||||
<view v-else class="checkbox__inner checkbox--indeterminate">
|
||||
<view class="checkbox__inner-icon"></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'TableCheckbox',
|
||||
emits:['checkboxSelected'],
|
||||
props: {
|
||||
indeterminate: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
checked: {
|
||||
type: [Boolean,String],
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
cellData: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
checked(newVal){
|
||||
if(typeof this.checked === 'boolean'){
|
||||
this.isChecked = newVal
|
||||
}else{
|
||||
this.isChecked = true
|
||||
}
|
||||
},
|
||||
indeterminate(newVal){
|
||||
this.isIndeterminate = newVal
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isChecked: false,
|
||||
isDisabled: false,
|
||||
isIndeterminate:false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if(typeof this.checked === 'boolean'){
|
||||
this.isChecked = this.checked
|
||||
}
|
||||
this.isDisabled = this.disabled
|
||||
},
|
||||
methods: {
|
||||
selected() {
|
||||
if (this.isDisabled) return
|
||||
this.isIndeterminate = false
|
||||
this.isChecked = !this.isChecked
|
||||
this.$emit('checkboxSelected', {
|
||||
checked: this.isChecked,
|
||||
data: this.cellData
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
$uni-primary: #007aff !default;
|
||||
$border-color: #DCDFE6;
|
||||
$disable:0.4;
|
||||
|
||||
.uni-table-checkbox {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
margin: 5px 0;
|
||||
cursor: pointer;
|
||||
|
||||
// 多选样式
|
||||
.checkbox__inner {
|
||||
/* #ifndef APP-NVUE */
|
||||
flex-shrink: 0;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
position: relative;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 1px solid $border-color;
|
||||
border-radius: 2px;
|
||||
background-color: #fff;
|
||||
z-index: 1;
|
||||
|
||||
.checkbox__inner-icon {
|
||||
position: absolute;
|
||||
/* #ifdef APP-NVUE */
|
||||
top: 2px;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
top: 2px;
|
||||
/* #endif */
|
||||
left: 5px;
|
||||
height: 7px;
|
||||
width: 3px;
|
||||
border: 1px solid #fff;
|
||||
border-left: 0;
|
||||
border-top: 0;
|
||||
opacity: 0;
|
||||
transform-origin: center;
|
||||
transform: rotate(45deg);
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
&.checkbox--indeterminate {
|
||||
border-color: $uni-primary;
|
||||
background-color: $uni-primary;
|
||||
|
||||
.checkbox__inner-icon {
|
||||
position: absolute;
|
||||
opacity: 1;
|
||||
transform: rotate(0deg);
|
||||
height: 2px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0;
|
||||
width: auto;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
transform: scale(0.5);
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
&:hover{
|
||||
border-color: $uni-primary;
|
||||
}
|
||||
// 禁用
|
||||
&.is-disable {
|
||||
/* #ifdef H5 */
|
||||
cursor: not-allowed;
|
||||
/* #endif */
|
||||
background-color: #F2F6FC;
|
||||
border-color: $border-color;
|
||||
}
|
||||
|
||||
// 选中
|
||||
&.is-checked {
|
||||
border-color: $uni-primary;
|
||||
background-color: $uni-primary;
|
||||
|
||||
.checkbox__inner-icon {
|
||||
opacity: 1;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
// 选中禁用
|
||||
&.is-disable {
|
||||
opacity: $disable;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<!-- #ifdef H5 -->
|
||||
<tr class="uni-table-tr">
|
||||
<th v-if="selection === 'selection' && ishead" class="checkbox" :class="{ 'tr-table--border': border }">
|
||||
<table-checkbox :checked="checked" :indeterminate="indeterminate" :disabled="disabled" @checkboxSelected="checkboxSelected"></table-checkbox>
|
||||
</th>
|
||||
<slot></slot>
|
||||
<!-- <uni-th class="th-fixed">123</uni-th> -->
|
||||
</tr>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef H5 -->
|
||||
<view class="uni-table-tr">
|
||||
<view v-if="selection === 'selection' " class="checkbox" :class="{ 'tr-table--border': border }">
|
||||
<table-checkbox :checked="checked" :indeterminate="indeterminate" :disabled="disabled" @checkboxSelected="checkboxSelected"></table-checkbox>
|
||||
</view>
|
||||
<slot></slot>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import tableCheckbox from './table-checkbox.vue'
|
||||
/**
|
||||
* Tr 表格行组件
|
||||
* @description 表格行组件 仅包含 th,td 组件
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=
|
||||
*/
|
||||
export default {
|
||||
name: 'uniTr',
|
||||
components: { tableCheckbox },
|
||||
props: {
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
keyValue: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
options: {
|
||||
virtualHost: true
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: false,
|
||||
border: false,
|
||||
selection: false,
|
||||
widthThArr: [],
|
||||
ishead: true,
|
||||
checked: false,
|
||||
indeterminate:false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.root = this.getTable()
|
||||
this.head = this.getTable('uniThead')
|
||||
if (this.head) {
|
||||
this.ishead = false
|
||||
this.head.init(this)
|
||||
}
|
||||
this.border = this.root.border
|
||||
this.selection = this.root.type
|
||||
this.root.trChildren.push(this)
|
||||
const rowData = this.root.data.find(v => v[this.root.rowKey] === this.keyValue)
|
||||
if(rowData){
|
||||
this.rowData = rowData
|
||||
}
|
||||
this.root.isNodata()
|
||||
},
|
||||
mounted() {
|
||||
if (this.widthThArr.length > 0) {
|
||||
const selectionWidth = this.selection === 'selection' ? 50 : 0
|
||||
this.root.minWidth = this.widthThArr.reduce((a, b) => Number(a) + Number(b)) + selectionWidth
|
||||
}
|
||||
},
|
||||
// #ifndef VUE3
|
||||
destroyed() {
|
||||
const index = this.root.trChildren.findIndex(i => i === this)
|
||||
this.root.trChildren.splice(index, 1)
|
||||
this.root.isNodata()
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
unmounted() {
|
||||
const index = this.root.trChildren.findIndex(i => i === this)
|
||||
this.root.trChildren.splice(index, 1)
|
||||
this.root.isNodata()
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
minWidthUpdate(width) {
|
||||
this.widthThArr.push(width)
|
||||
},
|
||||
// 选中
|
||||
checkboxSelected(e) {
|
||||
let rootData = this.root.data.find(v => v[this.root.rowKey] === this.keyValue)
|
||||
this.checked = e.checked
|
||||
this.root.check(rootData||this, e.checked,rootData? this.keyValue:null)
|
||||
},
|
||||
change(e) {
|
||||
this.root.trChildren.forEach(item => {
|
||||
if (item === this) {
|
||||
this.root.check(this, e.detail.value.length > 0 ? true : false)
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 获取父元素实例
|
||||
*/
|
||||
getTable(name = 'uniTable') {
|
||||
let parent = this.$parent
|
||||
let parentName = parent.$options.name
|
||||
while (parentName !== name) {
|
||||
parent = parent.$parent
|
||||
if (!parent) return false
|
||||
parentName = parent.$options.name
|
||||
}
|
||||
return parent
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
$border-color: #ebeef5;
|
||||
|
||||
.uni-table-tr {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: table-row;
|
||||
transition: all 0.3s;
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
padding: 0 8px;
|
||||
width: 26px;
|
||||
padding-left: 12px;
|
||||
/* #ifndef APP-NVUE */
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
/* #endif */
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
border-bottom: 1px $border-color solid;
|
||||
font-size: 14px;
|
||||
// text-align: center;
|
||||
}
|
||||
|
||||
.tr-table--border {
|
||||
border-right: 1px $border-color solid;
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
.uni-table-tr {
|
||||
::v-deep .uni-table-th {
|
||||
&.table--border:last-child {
|
||||
// border-right: none;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep .uni-table-td {
|
||||
&.table--border:last-child {
|
||||
// border-right: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"filter-dropdown.reset": "Reset",
|
||||
"filter-dropdown.search": "Search",
|
||||
"filter-dropdown.submit": "Submit",
|
||||
"filter-dropdown.filter": "Filter",
|
||||
"filter-dropdown.gt": "Greater or equal to",
|
||||
"filter-dropdown.lt": "Less than or equal to",
|
||||
"filter-dropdown.date": "Date"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"filter-dropdown.reset": "Reiniciar",
|
||||
"filter-dropdown.search": "Búsqueda",
|
||||
"filter-dropdown.submit": "Entregar",
|
||||
"filter-dropdown.filter": "Filtrar",
|
||||
"filter-dropdown.gt": "Mayor o igual a",
|
||||
"filter-dropdown.lt": "Menos que o igual a",
|
||||
"filter-dropdown.date": "Fecha"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"filter-dropdown.reset": "Réinitialiser",
|
||||
"filter-dropdown.search": "Chercher",
|
||||
"filter-dropdown.submit": "Soumettre",
|
||||
"filter-dropdown.filter": "Filtre",
|
||||
"filter-dropdown.gt": "Supérieur ou égal à",
|
||||
"filter-dropdown.lt": "Inférieur ou égal à",
|
||||
"filter-dropdown.date": "Date"
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
import en from './en.json'
|
||||
import es from './es.json'
|
||||
import fr from './fr.json'
|
||||
import zhHans from './zh-Hans.json'
|
||||
import zhHant from './zh-Hant.json'
|
||||
export default {
|
||||
en,
|
||||
es,
|
||||
fr,
|
||||
'zh-Hans': zhHans,
|
||||
'zh-Hant': zhHant
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"filter-dropdown.reset": "重置",
|
||||
"filter-dropdown.search": "搜索",
|
||||
"filter-dropdown.submit": "确定",
|
||||
"filter-dropdown.filter": "筛选",
|
||||
"filter-dropdown.gt": "大于等于",
|
||||
"filter-dropdown.lt": "小于等于",
|
||||
"filter-dropdown.date": "日期范围"
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"filter-dropdown.reset": "重置",
|
||||
"filter-dropdown.search": "搜索",
|
||||
"filter-dropdown.submit": "確定",
|
||||
"filter-dropdown.filter": "篩選",
|
||||
"filter-dropdown.gt": "大於等於",
|
||||
"filter-dropdown.lt": "小於等於",
|
||||
"filter-dropdown.date": "日期範圍"
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
{
|
||||
"id": "uni-table",
|
||||
"displayName": "uni-table 表格",
|
||||
"version": "1.2.3",
|
||||
"description": "表格组件,多用于展示多条结构类似的数据,如",
|
||||
"keywords": [
|
||||
"uni-ui",
|
||||
"uniui",
|
||||
"table",
|
||||
"表格"
|
||||
],
|
||||
"repository": "https://github.com/dcloudio/uni-ui",
|
||||
"engines": {
|
||||
"HBuilderX": ""
|
||||
},
|
||||
"directories": {
|
||||
"example": "../../temps/example_temps"
|
||||
},
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": ["uni-scss","uni-datetime-picker"],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "n"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "n",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "n",
|
||||
"联盟": "n"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue