feat: 库存查询

property-only-app
wx-jincw 3 months ago
parent 944a245f8a
commit 53bf699166

@ -0,0 +1,19 @@
import request from '@/utils/request.js';
// 库存列表
export function getStockList(params) {
return request.get(
'autogencode/ckcargostock/newList',
params,
{ useAdminUrl: true }
);
}
// 库存明细
export function getStockDetail(params) {
return request.get(
'autogencode/ckcargostock/list',
params,
{ useAdminUrl: true }
);
}

@ -8,7 +8,8 @@
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
//移动端商城API
let domain = 'https://fzbfwy.com/mobile-api'
// let domain = 'https://fzbfwy.com/mobile-api'
let domain = 'http://crmebxcx.test.jiutianda.cn'
module.exports = {
// 请求域名 格式: https://您的域名
@ -17,7 +18,8 @@ module.exports = {
// #ifdef MP
HTTP_REQUEST_URL: domain,
// #endif
HTTP_ADMIN_URL:'https://fzbfwy.com/prod-api', //PC后台的API请求地址上传图片用,影响h5上传头像
HTTP_ADMIN_URL:'https://crmeb.test.jiutianda.cn',
// HTTP_ADMIN_URL:'https://fzbfwy.com/prod-api', //PC后台的API请求地址上传图片用,影响h5上传头像
// #ifdef H5
//H5接口是浏览器地址
// HTTP_REQUEST_URL: window.location.protocol+"//"+window.location.host,

@ -238,6 +238,18 @@
// #endif
}
},
{
"path": "stock/detail",
"style": {
"navigationBarTitleText": "库存明细",
"navigationBarBackgroundColor": "#409EFF",
"navigationBarTextStyle": "white"
// #ifdef H5
,
"navigationStyle": "custom"
// #endif
}
},
{
"path": "approval/index",
"style": {

@ -75,25 +75,25 @@
<image class="image" src="/static/images/wg/wg_buy.png"></image>
</view>
<view class="menu-txt">采购操作</view>
</navigator>
</navigator> -->
<navigator class='item' url='/pages/supply_chain/stock/index' hover-class='none'>
<view class='pictrue picsmall'>
<image class="image" src="/static/images/wg/wg_stock.png"></image>
</view>
<view class="menu-txt">库存查询</view>
</navigator>
<navigator class='item' url='/pages/supply_chain/approval/index' hover-class='none'>
<!-- <navigator class='item' url='/pages/supply_chain/approval/index' hover-class='none'>
<view class='pictrue picsmall'>
<image class="image" src="/static/images/wg/wg_audit.png"></image>
</view>
<view class="menu-txt">审批处理</view>
</navigator>
</navigator> -->
<navigator class='item' url='/pages/supply_chain/material_receipt/index' hover-class='none'>
<view class='pictrue picsmall'>
<image class="image" src="/static/images/wg/wg_get.png"></image>
</view>
<view class="menu-txt">物资领用</view>
</navigator> -->
</navigator>
<navigator class='item' url='/pages/supply_chain/complaint/index' hover-class='none'>
<view class='pictrue picsmall'>
<image class="image" src="/static/images/wg/wg_jy.png"></image>

@ -0,0 +1,215 @@
<template>
<view class="detail-page">
<view class="content">
<view class="header">
<view class="back-btn" @click="goBack">
<text class="iconfont icon-xiangzuo"></text>
<text>返回</text>
</view>
<view class="title">库存变化明细</view>
</view>
<!-- 明细列表 -->
<view class="detail-section">
<view class="detail-list" v-if="detailItems.length > 0">
<view class="detail-item" v-for="(item, index) in detailItems" :key="index">
<view class="item-header">
<text class="item-date">{{ formatDate(item.stockDate) }}</text>
<text class="item-bill">{{ item.billNumber }}</text>
</view>
<view class="item-body">
<view class="info-item">
<text class="label">仓库名称</text>
<text class="value">{{ item.stockName }}</text>
</view>
<view class="info-item">
<text class="label">供应商</text>
<text class="value">{{ item.custName }}</text>
</view>
<view class="info-item">
<text class="label">商品名称</text>
<text class="value">{{ item.cargoName }}</text>
</view>
<view class="info-item">
<text class="label">商品编号</text>
<text class="value">{{ item.hsCode }}</text>
</view>
<view class="info-item">
<text class="label">商品数量</text>
<text class="value">{{ item.cargoWt }}</text>
</view>
<view class="info-item">
<text class="label">商品价值</text>
<text class="value">{{ item.cargoValue }}</text>
</view>
</view>
</view>
</view>
<view class="empty-list" v-else>
<text>暂无明细数据</text>
</view>
</view>
</view>
</view>
</template>
<script>
import { getStockDetail } from '@/api/stock';
export default {
data() {
return {
detailItems: [],
loading: false,
cargoId: '',
custId: '',
queryParams: {
pageNum: 1,
pageSize: 10,
cargoId: null,
custId: null
}
};
},
onLoad(options) {
if (options.cargoId && options.custId) {
this.cargoId = options.cargoId;
this.custId = options.custId;
this.queryParams.cargoId = options.cargoId;
this.queryParams.custId = options.custId;
this.getDetailList();
}
},
methods: {
//
formatDate(timestamp) {
if (!timestamp) return '';
const date = new Date(timestamp);
return date.toISOString().split('T')[0];
},
//
getDetailList() {
this.loading = true;
// API
getStockDetail(this.queryParams).then((res) => {
this.detailItems = res.data.list || [];
this.loading = false;
}).catch((err) => {
console.error('获取明细列表失败:', err);
this.loading = false;
});
},
//
goBack() {
uni.navigateBack();
}
}
};
</script>
<style lang="scss">
.detail-page {
.content {
.header {
display: flex;
align-items: center;
padding: 30rpx;
background-color: #fff;
border-bottom: 1rpx solid #eee;
.back-btn {
display: flex;
align-items: center;
padding: 10rpx;
.iconfont {
font-size: 28rpx;
color: #333;
margin-right: 10rpx;
}
text {
font-size: 24rpx;
color: #333;
}
}
.title {
flex: 1;
font-size: 28rpx;
font-weight: 600;
color: #333;
text-align: center;
margin-right: 60rpx;
}
}
.detail-section {
padding: 30rpx;
.detail-list {
.detail-item {
background-color: #fff;
border-radius: 10rpx;
padding: 20rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
.item-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 15rpx;
padding-bottom: 15rpx;
border-bottom: 1rpx solid #eee;
.item-date {
font-size: 24rpx;
color: #333;
font-weight: 600;
}
.item-bill {
font-size: 22rpx;
color: #666;
}
}
.item-body {
.info-item {
display: flex;
margin-bottom: 10rpx;
.label {
width: 140rpx;
font-size: 24rpx;
color: #666;
}
.value {
flex: 1;
font-size: 24rpx;
color: #333;
}
}
}
}
}
.empty-list {
display: flex;
align-items: center;
justify-content: center;
height: 200rpx;
background-color: #f5f5f5;
border-radius: 10rpx;
text {
font-size: 24rpx;
color: #999;
}
}
}
}
}
</style>

@ -4,117 +4,180 @@
<!-- 搜索和筛选 -->
<view class="search-section">
<view class="search-box">
<input type="text" v-model="searchKeyword" placeholder="搜索物资名称" />
<input type="text" v-model="queryParams.gdsSeqno" placeholder="搜索商品名称、编码、供应商" />
<view class="search-btn" @click="searchStock"></view>
</view>
<view class="filter-box">
<view class="filter-item" @click="toggleFilter('category')">
<text>{{ selectedCategory || '全部类别' }}</text>
<text class="iconfont icon-xiangxia"></text>
<view class="filter-item" @click="toggleSortMenu">
<text>{{ sortText }}</text>
<text class="iconfont" :class="sortIcon"></text>
</view>
<view class="filter-item" @click="toggleFilter('location')">
<text>{{ selectedLocation || '全部位置' }}</text>
<text class="iconfont icon-xiangxia"></text>
<view class="filter-item">
<view class="date-picker-container">
<view v-if="selectedDate" class="clear-btn" @click.stop="clearDate">
<text class="iconfont icon-cha"></text>
</view>
<view class="date-text" @click="openCalendar">
<text>{{ selectedDate || '入库日期' }}</text>
<text class="iconfont icon-xiangxia"></text>
</view>
</view>
</view>
</view>
</view>
<!-- 库存预警 -->
<view class="alert-section" v-if="alertItems.length > 0">
<view class="alert-title">
<text class="iconfont icon-jinggao"></text>
<text>库存预警</text>
</view>
<view class="alert-list">
<view class="alert-item" v-for="(item, index) in alertItems" :key="index">
<text class="item-name">{{ item.name }}</text>
<text class="item-stock">当前库存{{ item.stock }}</text>
<text class="item-min">最低库存{{ item.minStock }}</text>
</view>
<!-- 排序菜单 -->
<view class="sort-menu" v-if="showSortMenu">
<view class="sort-item" @click="setSort('')"></view>
<view class="sort-item" @click="setSort('asc')"></view>
<view class="sort-item" @click="setSort('desc')"></view>
</view>
</view>
<!-- 库存列表 -->
<view class="stock-section">
<view class="stock-title">库存列表</view>
<view class="stock-list">
<view class="stock-list" v-if="stockItems.length > 0">
<view class="stock-item" v-for="(item, index) in stockItems" :key="index">
<view class="item-header">
<text class="item-name">{{ item.name }}</text>
<text class="item-status" :class="item.stock <= item.minStock ? 'status-warning' : 'status-normal'">
{{ item.stock <= item.minStock ? '库存不足' : '库存正常' }}
</text>
<text class="item-name">{{ item.cargoName }}</text>
</view>
<view class="item-body">
<view class="info-item">
<text class="label">当前库存</text>
<text class="value">{{ item.stock }}</text>
<text class="label">商品编码</text>
<text class="value">{{ item.hsCode }}</text>
</view>
<view class="info-item">
<text class="label">最低库存</text>
<text class="value">{{ item.minStock }}</text>
<text class="label">供应商</text>
<text class="value">{{ item.custName }}</text>
</view>
<view class="info-item">
<text class="label">库存位置</text>
<text class="value">{{ item.location }}</text>
<text class="label">库存数量</text>
<text class="value">{{ item.cargoWt }}</text>
</view>
<view class="info-item">
<text class="label">物资类别</text>
<text class="value">{{ item.category }}</text>
</view>
<view class="info-item">
<text class="label">最后更新</text>
<text class="value">{{ item.updateTime }}</text>
<text class="label">入库日期</text>
<text class="value">{{ formatDate(item.stockDate) }}</text>
</view>
</view>
<view class="item-footer">
<view class="detail-btn" @click="viewStockDetail(item.id)"></view>
<view class="detail-btn" @click="viewStockDetail(item)"></view>
</view>
</view>
</view>
<view class="empty-list" v-else>
<text>暂无库存数据</text>
</view>
</view>
</view>
<!-- 日历组件 -->
<uni-calendar
ref="calendar"
:insert="false"
:range="false"
:start-date="'2020-01-01'"
:end-date="'2030-12-31'"
@confirm="confirm"
></uni-calendar>
</view>
</template>
<script>
import { getStockList } from '@/api/stock';
export default {
data() {
return {
searchKeyword: '',
selectedCategory: '',
selectedLocation: '',
alertItems: [
{ id: 1, name: '有机蔬菜', stock: 20, minStock: 30, location: '仓库A区', category: '食材' },
{ id: 3, name: '肉类食材', stock: 15, minStock: 20, location: '冷库C区', category: '食材' }
],
stockItems: [
{ id: 1, name: '有机蔬菜', stock: 20, minStock: 30, location: '仓库A区', category: '食材', updateTime: '2026-03-07 10:00' },
{ id: 2, name: '新鲜水果', stock: 40, minStock: 25, location: '仓库B区', category: '食材', updateTime: '2026-03-07 09:30' },
{ id: 3, name: '肉类食材', stock: 15, minStock: 20, location: '冷库C区', category: '食材', updateTime: '2026-03-06 18:00' },
{ id: 4, name: '海鲜产品', stock: 25, minStock: 15, location: '冷库D区', category: '食材', updateTime: '2026-03-06 17:30' },
{ id: 5, name: '维修耗材', stock: 50, minStock: 20, location: '仓库E区', category: '耗材', updateTime: '2026-03-05 14:00' },
{ id: 6, name: '办公用品', stock: 30, minStock: 15, location: '仓库F区', category: '办公', updateTime: '2026-03-05 13:30' }
]
sortOrder: '', // '''asc''desc'
sortField: 'cargoWt', //
sortText: '排序',
sortIcon: 'icon-xiangxia',
showSortMenu: false,
selectedDate: '',
stockItems: [],
loading: false,
queryParams: {
pageNum: 1,
pageSize: 10,
gdsSeqno: null,
stockDateStr: null,
sortField: null,
sortOrder: null
}
};
},
mounted() {
this.getStockList();
},
methods: {
searchStock() {
uni.showToast({
title: '搜索功能开发中',
icon: 'none'
});
//
formatDate(dateStr) {
if (!dateStr) return '';
// 10
return dateStr.toString().substring(0, 10);
},
toggleFilter(type) {
uni.showToast({
title: '筛选功能开发中',
icon: 'none'
//
getStockList() {
this.loading = true;
// API
getStockList(this.queryParams).then((res) => {
this.stockItems = res.data.list || [];
this.loading = false;
}).catch((err) => {
console.error('获取库存列表失败:', err);
this.loading = false;
});
},
viewStockDetail(id) {
uni.showToast({
title: '查看库存详情',
icon: 'none'
//
searchStock() {
this.queryParams.pageNum = 1;
this.getStockList();
},
//
toggleSortMenu() {
this.showSortMenu = !this.showSortMenu;
if (this.showSortMenu) {
this.showDatePicker = false;
}
},
//
setSort(order) {
this.sortOrder = order;
if (order === '') {
this.sortText = '排序';
this.sortIcon = 'icon-xiangxia';
this.queryParams.sortField = null;
this.queryParams.sortOrder = null;
} else {
this.sortText = `库存数量${order === 'asc' ? '升序' : '降序'}`;
this.sortIcon = order === 'asc' ? 'icon-xiangshang' : 'icon-xiangxia';
this.queryParams.sortField = this.sortField;
this.queryParams.sortOrder = order;
}
this.showSortMenu = false;
this.getStockList();
},
//
openCalendar() {
this.$refs.calendar.open();
},
//
confirm(e) {
// console.log(e);
this.selectedDate = e.fulldate;
this.queryParams.stockDateStr = e.fulldate;
this.getStockList();
},
//
clearDate() {
this.selectedDate = '';
this.queryParams.stockDateStr = null;
this.getStockList();
},
//
viewStockDetail(item) {
uni.navigateTo({
url: `./detail?id=${item.id}&cargoId=${item.cargoId}&custId=${item.custId}`
});
}
}
@ -128,6 +191,7 @@ export default {
.search-section {
margin-bottom: 30rpx;
position: relative;
.search-box {
display: flex;
@ -167,6 +231,43 @@ export default {
border-radius: 20rpx;
margin-right: 20rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
cursor: pointer;
.date-picker-container {
display: flex;
align-items: center;
.date-text {
display: flex;
align-items: center;
text {
font-size: 24rpx;
color: #333;
margin-right: 10rpx;
}
.iconfont {
font-size: 20rpx;
color: #666;
transition: transform 0.3s;
}
}
.clear-btn {
margin-right: 10rpx;
padding: 5rpx;
.iconfont {
font-size: 24rpx;
color: #999;
&:hover {
color: #ff4d4f;
}
}
}
}
text {
font-size: 24rpx;
@ -177,61 +278,35 @@ export default {
.iconfont {
font-size: 20rpx;
color: #666;
transition: transform 0.3s;
}
}
}
}
.alert-section {
background-color: #FFF7E6;
border-radius: 10rpx;
padding: 20rpx;
margin-bottom: 30rpx;
border-left: 4rpx solid #FA8C16;
.alert-title {
display: flex;
align-items: center;
margin-bottom: 15rpx;
.iconfont {
font-size: 28rpx;
color: #FA8C16;
margin-right: 10rpx;
}
//
.sort-menu {
position: absolute;
top: 100%;
left: 0;
background-color: #fff;
border-radius: 10rpx;
box-shadow: 0 5rpx 15rpx rgba(0, 0, 0, 0.1);
z-index: 100;
margin-top: 10rpx;
width: 200rpx;
text {
font-size: 26rpx;
font-weight: 600;
.sort-item {
padding: 15rpx 20rpx;
font-size: 24rpx;
color: #333;
}
}
.alert-list {
.alert-item {
display: flex;
align-items: center;
background-color: #fff;
border-radius: 8rpx;
padding: 15rpx;
margin-bottom: 10rpx;
.item-name {
flex: 1;
font-size: 24rpx;
color: #333;
font-weight: 600;
}
border-bottom: 1rpx solid #eee;
.item-stock {
font-size: 22rpx;
color: #FA8C16;
margin-right: 20rpx;
&:last-child {
border-bottom: none;
}
.item-min {
font-size: 22rpx;
color: #666;
&:hover {
background-color: #f5f5f5;
}
}
}
@ -256,7 +331,6 @@ export default {
.item-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 15rpx;
.item-name {
@ -264,22 +338,6 @@ export default {
font-weight: 600;
color: #333;
}
.item-status {
padding: 5rpx 15rpx;
border-radius: 15rpx;
font-size: 20rpx;
}
.status-warning {
background-color: #FFF7E6;
color: #FA8C16;
}
.status-normal {
background-color: #F6FFED;
color: #52C41A;
}
}
.item-body {
@ -290,7 +348,7 @@ export default {
margin-bottom: 10rpx;
.label {
width: 120rpx;
width: 140rpx;
font-size: 24rpx;
color: #666;
}
@ -317,7 +375,23 @@ export default {
}
}
}
.empty-list {
display: flex;
align-items: center;
justify-content: center;
height: 200rpx;
background-color: #f5f5f5;
border-radius: 10rpx;
text {
font-size: 24rpx;
color: #999;
}
}
}
}
}
</style>

@ -0,0 +1,30 @@
## 1.4.122024-09-21
- 修复 calendar在选择日期范围后重新选择日期需要点两次的Bug
## 1.4.112024-01-10
- 修复 回到今天时,月份显示不一致问题
## 1.4.102023-04-10
- 修复 某些情况 monthSwitch 未触发的Bug
## 1.4.92023-02-02
- 修复 某些情况切换月份错误的Bug
## 1.4.82023-01-30
- 修复 某些情况切换月份错误的Bug [详情](https://ask.dcloud.net.cn/question/161964)
## 1.4.72022-09-16
- 优化 支持使用 uni-scss 控制主题色
## 1.4.62022-09-08
- 修复 表头年月切换导致改变当前日期为选择月1号且未触发change事件的Bug
## 1.4.52022-02-25
- 修复 条件编译 nvue 不支持的 css 样式的Bug
## 1.4.42022-02-25
- 修复 条件编译 nvue 不支持的 css 样式的Bug
## 1.4.32021-09-22
- 修复 startDate、 endDate 属性失效的Bug
## 1.4.22021-08-24
- 新增 支持国际化
## 1.4.12021-08-05
- 修复 弹出层被 tabbar 遮盖的Bug
## 1.4.02021-07-30
- 组件兼容 vue3如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
## 1.3.162021-05-12
- 新增 组件示例地址
## 1.3.152021-02-04
- 调整为uni_modules目录规范

@ -351,10 +351,8 @@ var calendar = {
s = '\u521d\u5341'; break
case 20:
s = '\u4e8c\u5341'; break
break
case 30:
s = '\u4e09\u5341'; break
break
default :
s = this.nStr2[Math.floor(d / 10)]
s += this.nStr1[d % 10]

@ -0,0 +1,12 @@
{
"uni-calender.ok": "ok",
"uni-calender.cancel": "cancel",
"uni-calender.today": "today",
"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"
}

@ -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,12 @@
{
"uni-calender.ok": "确定",
"uni-calender.cancel": "取消",
"uni-calender.today": "今日",
"uni-calender.SUN": "日",
"uni-calender.MON": "一",
"uni-calender.TUE": "二",
"uni-calender.WED": "三",
"uni-calender.THU": "四",
"uni-calender.FRI": "五",
"uni-calender.SAT": "六"
}

@ -0,0 +1,12 @@
{
"uni-calender.ok": "確定",
"uni-calender.cancel": "取消",
"uni-calender.today": "今日",
"uni-calender.SUN": "日",
"uni-calender.MON": "一",
"uni-calender.TUE": "二",
"uni-calender.WED": "三",
"uni-calender.THU": "四",
"uni-calender.FRI": "五",
"uni-calender.SAT": "六"
}

@ -1,152 +1,187 @@
<template>
<view class="uni-calendar-item__weeks-box" :class="{
'uni-calendar-item--disable':weeks.disable,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':(calendar.fullDate === weeks.fullDate && !weeks.isDay) ,
'uni-calendar-item--multiple': weeks.multiple
}"
@click="choiceDate(weeks)">
<view class="uni-calendar-item__weeks-box-item">
<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
<text class="uni-calendar-item__weeks-box-text" :class="{
'uni-calendar-item--isDay-text': weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--disable':weeks.disable,
}">{{weeks.date}}</text>
<text v-if="!lunar&&!weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text" :class="{
'uni-calendar-item--isDay-text':weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--multiple': weeks.multiple,
}">今天</text>
<text v-if="lunar&&!weeks.extraInfo" class="uni-calendar-item__weeks-lunar-text" :class="{
'uni-calendar-item--isDay-text':weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--disable':weeks.disable,
}">{{weeks.isDay?'今天': (weeks.lunar.IDayCn === '初一'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}</text>
<text v-if="weeks.extraInfo&&weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text" :class="{
'uni-calendar-item--extra':weeks.extraInfo.info,
'uni-calendar-item--isDay-text':weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--disable':weeks.disable,
}">{{weeks.extraInfo.info}}</text>
</view>
</view>
</template>
<script>
export default {
props: {
weeks: {
type: Object,
default () {
return {}
}
},
calendar: {
type: Object,
default: () => {
return {}
}
},
selected: {
type: Array,
default: () => {
return []
}
},
lunar: {
type: Boolean,
default: false
}
},
methods: {
choiceDate(weeks) {
this.$emit('change', weeks)
}
}
}
</script>
<style lang="scss" scoped>
.uni-calendar-item__weeks-box {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
}
.uni-calendar-item__weeks-box-text {
font-size: $uni-font-size-base;
color: $uni-text-color;
}
.uni-calendar-item__weeks-lunar-text {
font-size: $uni-font-size-sm;
color: $uni-text-color;
}
.uni-calendar-item__weeks-box-item {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
width: 100rpx;
height: 100rpx;
}
.uni-calendar-item__weeks-box-circle {
position: absolute;
top: 5px;
right: 5px;
width: 8px;
height: 8px;
border-radius: 8px;
background-color: $uni-color-error;
}
.uni-calendar-item--disable {
background-color: rgba(249, 249, 249, $uni-opacity-disabled);
color: $uni-text-color-disable;
}
.uni-calendar-item--isDay-text {
color: $uni-color-primary;
}
.uni-calendar-item--isDay {
background-color: $uni-color-primary;
opacity: 0.8;
color: #fff;
}
.uni-calendar-item--extra {
color: $uni-color-error;
opacity: 0.8;
}
.uni-calendar-item--checked {
background-color: $uni-color-primary;
color: #fff;
opacity: 0.8;
}
.uni-calendar-item--multiple {
background-color: $uni-color-primary;
color: #fff;
opacity: 0.8;
}
</style>
<template>
<view class="uni-calendar-item__weeks-box" :class="{
'uni-calendar-item--disable':weeks.disable,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':(calendar.fullDate === weeks.fullDate && !weeks.isDay) ,
'uni-calendar-item--before-checked':weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked':weeks.afterMultiple,
}"
@click="choiceDate(weeks)">
<view class="uni-calendar-item__weeks-box-item">
<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
<text class="uni-calendar-item__weeks-box-text" :class="{
'uni-calendar-item--isDay-text': weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'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,
}">{{weeks.date}}</text>
<text v-if="!lunar&&!weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text" :class="{
'uni-calendar-item--isDay-text':weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'uni-calendar-item--before-checked':weeks.beforeMultiple,
'uni-calendar-item--multiple': weeks.multiple,
'uni-calendar-item--after-checked':weeks.afterMultiple,
}">{{todayText}}</text>
<text v-if="lunar&&!weeks.extraInfo" class="uni-calendar-item__weeks-lunar-text" :class="{
'uni-calendar-item--isDay-text':weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'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,
}">{{weeks.isDay ? todayText : (weeks.lunar.IDayCn === '初一'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}</text>
<text v-if="weeks.extraInfo&&weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text" :class="{
'uni-calendar-item--extra':weeks.extraInfo.info,
'uni-calendar-item--isDay-text':weeks.isDay,
'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
'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,
}">{{weeks.extraInfo.info}}</text>
</view>
</view>
</template>
<script>
import { initVueI18n } from '@dcloudio/uni-i18n'
import i18nMessages from './i18n/index.js'
const { t } = initVueI18n(i18nMessages)
export default {
emits:['change'],
props: {
weeks: {
type: Object,
default () {
return {}
}
},
calendar: {
type: Object,
default: () => {
return {}
}
},
selected: {
type: Array,
default: () => {
return []
}
},
lunar: {
type: Boolean,
default: false
}
},
computed: {
todayText() {
return t("uni-calender.today")
},
},
methods: {
choiceDate(weeks) {
this.$emit('change', weeks)
}
}
}
</script>
<style lang="scss" scoped>
$uni-font-size-base:14px;
$uni-text-color:#333;
$uni-font-size-sm:12px;
$uni-color-error: #e43d33;
$uni-opacity-disabled: 0.3;
$uni-text-color-disable:#c0c0c0;
$uni-primary: #2979ff !default;
.uni-calendar-item__weeks-box {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
}
.uni-calendar-item__weeks-box-text {
font-size: $uni-font-size-base;
color: $uni-text-color;
}
.uni-calendar-item__weeks-lunar-text {
font-size: $uni-font-size-sm;
color: $uni-text-color;
}
.uni-calendar-item__weeks-box-item {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
width: 100rpx;
height: 100rpx;
}
.uni-calendar-item__weeks-box-circle {
position: absolute;
top: 5px;
right: 5px;
width: 8px;
height: 8px;
border-radius: 8px;
background-color: $uni-color-error;
}
.uni-calendar-item--disable {
background-color: rgba(249, 249, 249, $uni-opacity-disabled);
color: $uni-text-color-disable;
}
.uni-calendar-item--isDay-text {
color: $uni-primary;
}
.uni-calendar-item--isDay {
background-color: $uni-primary;
opacity: 0.8;
color: #fff;
}
.uni-calendar-item--extra {
color: $uni-color-error;
opacity: 0.8;
}
.uni-calendar-item--checked {
background-color: $uni-primary;
color: #fff;
opacity: 0.8;
}
.uni-calendar-item--multiple {
background-color: $uni-primary;
color: #fff;
opacity: 0.8;
}
.uni-calendar-item--before-checked {
background-color: #ff5a5f;
color: #fff;
}
.uni-calendar-item--after-checked {
background-color: #ff5a5f;
color: #fff;
}
</style>

@ -1,327 +1,360 @@
import CALENDAR from './calendar.js'
class Calendar {
constructor({
date,
selected,
startDate,
endDate,
range
} = {}) {
// 当前日期
this.date = this.getDate(date) // 当前初入日期
// 打点信息
this.selected = selected || [];
// 范围开始
this.startDate = startDate
// 范围结束
this.endDate = endDate
this.range = range
// 多选状态
this.multipleStatus = {
before: '',
after: '',
data: []
}
// 每周日期
this.weeks = {}
this._getWeek(this.date.fullDate)
}
/**
* 获取任意时间
*/
getDate(date, AddDayCount = 0, str = 'day') {
if (!date) {
date = new Date()
}
if (typeof date !== 'object') {
date = date.replace(/-/g, '/')
}
const dd = new Date(date)
switch (str) {
case 'day':
dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
break
case 'month':
if (dd.getDate() === 31) {
dd.setDate(dd.getDate() + AddDayCount)
} else {
dd.setMonth(dd.getMonth() + AddDayCount) // 获取AddDayCount天后的日期
}
break
case 'year':
dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
break
}
const y = dd.getFullYear()
const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期不足10补0
const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号不足10补0
return {
fullDate: y + '-' + m + '-' + d,
year: y,
month: m,
date: d,
day: dd.getDay()
}
}
/**
* 获取上月剩余天数
*/
_getLastMonthDays(firstDay, full) {
let dateArr = []
for (let i = firstDay; i > 0; i--) {
const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
dateArr.push({
date: beforeDate,
month: full.month - 1,
lunar: this.getlunar(full.year, full.month - 1, beforeDate),
disable: true
})
}
return dateArr
}
/**
* 获取本月天数
*/
_currentMonthDys(dateData, full) {
let dateArr = []
let fullDate = this.date.fullDate
for (let i = 1; i <= dateData; i++) {
let isinfo = false
let nowDate = full.year + '-' + (full.month < 10 ?
full.month : full.month) + '-' + (i < 10 ?
'0' + i : i)
// 是否今天
let isDay = fullDate === nowDate
// 获取打点信息
let info = this.selected && this.selected.find((item) => {
if (this.dateEqual(nowDate, item.date)) {
return item
}
})
// 日期禁用
let disableBefore = true
let disableAfter = true
if (this.startDate) {
let dateCompBefore = this.dateCompare(this.startDate, fullDate)
disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
}
if (this.endDate) {
let dateCompAfter = this.dateCompare(fullDate, this.endDate)
disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
}
let multiples = this.multipleStatus.data
let checked = false
let multiplesStatus = -1
if (this.range) {
if (multiples) {
multiplesStatus = multiples.findIndex((item) => {
return this.dateEqual(item, nowDate)
})
}
if (multiplesStatus !== -1) {
checked = true
}
}
let data = {
fullDate: nowDate,
year: full.year,
date: i,
multiple: this.range ? checked : false,
month: full.month,
lunar: this.getlunar(full.year, full.month, i),
disable: !disableBefore || !disableAfter,
isDay
}
if (info) {
data.extraInfo = info
}
dateArr.push(data)
}
return dateArr
}
/**
* 获取下月天数
*/
_getNextMonthDays(surplus, full) {
let dateArr = []
for (let i = 1; i < surplus + 1; i++) {
dateArr.push({
date: i,
month: Number(full.month) + 1,
lunar: this.getlunar(full.year, Number(full.month) + 1, i),
disable: true
})
}
return dateArr
}
/**
* 设置日期
* @param {Object} date
*/
setDate(date) {
this._getWeek(date)
}
/**
* 获取当前日期详情
* @param {Object} date
*/
getInfo(date) {
if (!date) {
date = new Date()
}
const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
return dateInfo
}
/**
* 比较时间大小
*/
dateCompare(startDate, endDate) {
// 计算截止时间
startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
// 计算详细项的截止时间
endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
if (startDate <= endDate) {
return true
} else {
return false
}
}
/**
* 比较时间是否相等
*/
dateEqual(before, after) {
// 计算截止时间
before = new Date(before.replace('-', '/').replace('-', '/'))
// 计算详细项的截止时间
after = new Date(after.replace('-', '/').replace('-', '/'))
if (before.getTime() - after.getTime() === 0) {
return true
} else {
return false
}
}
/**
* 获取日期范围内所有日期
* @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.getDate(new Date(parseInt(k))).fullDate)
}
return arr
}
/**
* 计算阴历日期显示
*/
getlunar(year, month, date) {
return CALENDAR.solar2lunar(year, month, date)
}
/**
* 设置打点
*/
setSelectInfo(data, value) {
this.selected = value
this._getWeek(data)
}
/**
* 获取多选状态
*/
setMultiple(fullDate) {
let {
before,
after
} = this.multipleStatus
if (!this.range) return
if (before && after) {
this.multipleStatus.before = ''
this.multipleStatus.after = ''
this.multipleStatus.data = []
this._getWeek(fullDate)
} else {
if (!before) {
this.multipleStatus.before = fullDate
} else {
this.multipleStatus.after = fullDate
if (this.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._getWeek(fullDate)
}
}
}
/**
* 获取每周数据
* @param {Object} dateData
*/
_getWeek(dateData) {
const {
fullDate,
year,
month,
date,
day
} = this.getDate(dateData)
let firstDay = new Date(year, month - 1, 1).getDay()
let currentDay = new Date(year, month, 0).getDate()
let dates = {
lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
nextMonthDays: [], // 下个月开始几天
weeks: []
}
let canlender = []
const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
let weeks = {}
// 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天
for (let i = 0; i < canlender.length; i++) {
if (i % 7 === 0) {
weeks[parseInt(i / 7)] = new Array(7)
}
weeks[parseInt(i / 7)][i % 7] = canlender[i]
}
this.canlender = canlender
this.weeks = weeks
}
//静态方法
// static init(date) {
// if (!this.instance) {
// this.instance = new Calendar(date);
// }
// return this.instance;
// }
}
export default Calendar
import CALENDAR from './calendar.js'
class Calendar {
constructor({
date,
selected,
startDate,
endDate,
range
} = {}) {
// 当前日期
this.date = this.getDate(new Date()) // 当前初入日期
// 打点信息
this.selected = selected || [];
// 范围开始
this.startDate = startDate
// 范围结束
this.endDate = endDate
this.range = range
// 多选状态
this.cleanMultipleStatus()
// 每周日期
this.weeks = {}
// this._getWeek(this.date.fullDate)
}
/**
* 设置日期
* @param {Object} date
*/
setDate(date) {
this.selectDate = this.getDate(date)
this._getWeek(this.selectDate.fullDate)
}
/**
* 清理多选状态
*/
cleanMultipleStatus() {
this.multipleStatus = {
before: '',
after: '',
data: []
}
}
/**
* 重置开始日期
*/
resetSatrtDate(startDate) {
// 范围开始
this.startDate = startDate
}
/**
* 重置结束日期
*/
resetEndDate(endDate) {
// 范围结束
this.endDate = endDate
}
/**
* 获取任意时间
*/
getDate(date, AddDayCount = 0, str = 'day') {
if (!date) {
date = new Date()
}
if (typeof date !== 'object') {
date = date.replace(/-/g, '/')
}
const dd = new Date(date)
switch (str) {
case 'day':
dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
break
case 'month':
if (dd.getDate() === 31 && AddDayCount>0) {
dd.setDate(dd.getDate() + AddDayCount)
} else {
const preMonth = dd.getMonth()
dd.setMonth(preMonth + AddDayCount) // 获取AddDayCount天后的日期
const nextMonth = dd.getMonth()
// 处理 pre 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
if(AddDayCount<0 && preMonth!==0 && nextMonth-preMonth>AddDayCount){
dd.setMonth(nextMonth+(nextMonth-preMonth+AddDayCount))
}
// 处理 next 切换月份目标月份为2月没有当前日(30 31) 切换错误问题
if(AddDayCount>0 && nextMonth-preMonth>AddDayCount){
dd.setMonth(nextMonth-(nextMonth-preMonth-AddDayCount))
}
}
break
case 'year':
dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
break
}
const y = dd.getFullYear()
const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期不足10补0
const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号不足10补0
return {
fullDate: y + '-' + m + '-' + d,
year: y,
month: m,
date: d,
day: dd.getDay()
}
}
/**
* 获取上月剩余天数
*/
_getLastMonthDays(firstDay, full) {
let dateArr = []
for (let i = firstDay; i > 0; i--) {
const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
dateArr.push({
date: beforeDate,
month: full.month - 1,
lunar: this.getlunar(full.year, full.month - 1, beforeDate),
disable: true
})
}
return dateArr
}
/**
* 获取本月天数
*/
_currentMonthDys(dateData, full) {
let dateArr = []
let fullDate = this.date.fullDate
for (let i = 1; i <= dateData; i++) {
let nowDate = full.year + '-' + (full.month < 10 ?
full.month : full.month) + '-' + (i < 10 ?
'0' + i : i)
// 是否今天
let isDay = fullDate === nowDate
// 获取打点信息
let info = this.selected && this.selected.find((item) => {
if (this.dateEqual(nowDate, item.date)) {
return item
}
})
// 日期禁用
let disableBefore = true
let disableAfter = true
if (this.startDate) {
// let dateCompBefore = this.dateCompare(this.startDate, fullDate)
// disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
disableBefore = this.dateCompare(this.startDate, nowDate)
}
if (this.endDate) {
// let dateCompAfter = this.dateCompare(fullDate, this.endDate)
// disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
disableAfter = this.dateCompare(nowDate, this.endDate)
}
let multiples = this.multipleStatus.data
let checked = false
let multiplesStatus = -1
if (this.range) {
if (multiples) {
multiplesStatus = multiples.findIndex((item) => {
return this.dateEqual(item, nowDate)
})
}
if (multiplesStatus !== -1) {
checked = true
}
}
let data = {
fullDate: nowDate,
year: full.year,
date: i,
multiple: this.range ? checked : false,
beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate),
afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate),
month: full.month,
lunar: this.getlunar(full.year, full.month, i),
disable: !(disableBefore && disableAfter),
isDay
}
if (info) {
data.extraInfo = info
}
dateArr.push(data)
}
return dateArr
}
/**
* 获取下月天数
*/
_getNextMonthDays(surplus, full) {
let dateArr = []
for (let i = 1; i < surplus + 1; i++) {
dateArr.push({
date: i,
month: Number(full.month) + 1,
lunar: this.getlunar(full.year, Number(full.month) + 1, i),
disable: true
})
}
return dateArr
}
/**
* 获取当前日期详情
* @param {Object} date
*/
getInfo(date) {
if (!date) {
date = new Date()
}
const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
return dateInfo
}
/**
* 比较时间大小
*/
dateCompare(startDate, endDate) {
// 计算截止时间
startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
// 计算详细项的截止时间
endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
if (startDate <= endDate) {
return true
} else {
return false
}
}
/**
* 比较时间是否相等
*/
dateEqual(before, after) {
// 计算截止时间
before = new Date(before.replace('-', '/').replace('-', '/'))
// 计算详细项的截止时间
after = new Date(after.replace('-', '/').replace('-', '/'))
if (before.getTime() - after.getTime() === 0) {
return true
} else {
return false
}
}
/**
* 获取日期范围内所有日期
* @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.getDate(new Date(parseInt(k))).fullDate)
}
return arr
}
/**
* 计算阴历日期显示
*/
getlunar(year, month, date) {
return CALENDAR.solar2lunar(year, month, date)
}
/**
* 设置打点
*/
setSelectInfo(data, value) {
this.selected = value
this._getWeek(data)
}
/**
* 获取多选状态
*/
setMultiple(fullDate) {
let {
before,
after
} = this.multipleStatus
if (!this.range) return
if (before && after) {
this.multipleStatus.before = fullDate
this.multipleStatus.after = ''
this.multipleStatus.data = []
} else {
if (!before) {
this.multipleStatus.before = fullDate
} else {
this.multipleStatus.after = fullDate
if (this.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._getWeek(fullDate)
}
/**
* 获取每周数据
* @param {Object} dateData
*/
_getWeek(dateData) {
const {
year,
month
} = this.getDate(dateData)
let firstDay = new Date(year, month - 1, 1).getDay()
let currentDay = new Date(year, month, 0).getDate()
let dates = {
lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
nextMonthDays: [], // 下个月开始几天
weeks: []
}
let canlender = []
const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
let weeks = {}
// 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天
for (let i = 0; i < canlender.length; i++) {
if (i % 7 === 0) {
weeks[parseInt(i / 7)] = new Array(7)
}
weeks[parseInt(i / 7)][i % 7] = canlender[i]
}
this.canlender = canlender
this.weeks = weeks
}
//静态方法
// static init(date) {
// if (!this.instance) {
// this.instance = new Calendar(date);
// }
// return this.instance;
// }
}
export default Calendar

@ -0,0 +1,86 @@
{
"id": "uni-calendar",
"displayName": "uni-calendar 日历",
"version": "1.4.12",
"description": "日历组件",
"keywords": [
"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": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y",
"alipay": "n"
},
"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,103 @@
## Calendar 日历
> **组件名uni-calendar**
> 代码块: `uCalendar`
日历组件
> **注意事项**
> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
> - 本组件农历转换使用的js是 [@1900-2100区间内的公历、农历互转](https://github.com/jjonline/calendar.js)
> - 仅支持自定义组件模式
> - `date`属性传入的应该是一个 String ,如: 2019-06-27 ,而不是 new Date()
> - 通过 `insert` 属性来确定当前的事件是 @change 还是 @confirm 。理应合并为一个事件,但是为了区分模式,现使用两个事件,这里需要注意
> - 弹窗模式下无法阻止后面的元素滚动,如有需要阻止,请在弹窗弹出后,手动设置滚动元素为不可滚动
### 安装方式
本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
### 基本用法
在 ``template`` 中使用组件
```html
<view>
<uni-calendar
:insert="true"
:lunar="true"
:start-date="'2019-3-2'"
:end-date="'2019-5-20'"
@change="change"
/>
</view>
```
### 通过方法打开日历
需要设置 `insert``false`
```html
<view>
<uni-calendar
ref="calendar"
:insert="false"
@confirm="confirm"
/>
<button @click="open">打开日历</button>
</view>
```
```javascript
export default {
data() {
return {};
},
methods: {
open(){
this.$refs.calendar.open();
},
confirm(e) {
console.log(e);
}
}
};
```
## API
### Calendar Props
| 属性名 | 类型 | 默认值| 说明 |
| - | - | - | - |
| date | String |- | 自定义当前时间,默认为今天 |
| lunar | Boolean | false | 显示农历 |
| startDate | String |- | 日期选择范围-开始日期 |
| endDate | String |- | 日期选择范围-结束日期 |
| range | Boolean | false | 范围选择 |
| insert | Boolean | false | 插入模式,可选值ture插入模式false弹窗模式默认为插入模式 |
|clearDate |Boolean |true |弹窗模式是否清空上次选择内容 |
| selected | Array |- | 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}] |
|showMonth | Boolean | true | 是否显示月份为背景 |
### Calendar Events
| 事件名 | 说明 |返回值|
| - | - | - |
| open | 弹出日历组件,`insert :false` 时生效|- |
## 组件示例
点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar](https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar)
Loading…
Cancel
Save