Commit 10e13acc authored by 刘杰's avatar 刘杰

企业微信前端

parent f0fdce6d
<template>
<view class="dateTime" style="width: 100%;">
<view class="flex_sb" @click="open">
<text v-if="dateTimeValue">{{dateTimeValue}}</text>
<text v-else class="input-tip">{{placeholder}}</text>
<slot name="rightIcon"></slot>
</view>
<u-popup :show="show" @close="close" @open="open">
<view class="popup-box">
<view class="popup-header">
<view class="popup-title">请选择日期时间</view>
<view class="close">
<u-icon name="close" color="#8C8C8C" size="32" @click="close"></u-icon>
</view>
</view>
<u-tabs v-if="list.length>0" :list="list" @click="switchTab"></u-tabs>
<DateTimePicker
v-show="tabIndex === 0"
@onChange="onChangeDate"
:minDate="minDate"
:defaultDate="defaultDate"
:mode="DATE_TYPES.YMD"
/>
<DateTimePicker
@onChange="onChangeTime"
v-show="tabIndex === 1"
:defaultDate="defaultTime"
:mode="DATE_TYPES.HMS"
/>
<view class="footer-btns">
<button class="primary-btn" @click="confirm">确定</button>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import DateTimePicker from './dateTimePicker/index.vue'
import { DATE_TYPES } from './constant'
import {dateTransformYMDhms,formatGMT} from '../../../utils/util'
export default{
options: { styleIsolation: 'shared' },
components:{DateTimePicker},
data() {
return {
DATE_TYPES,
defaultDate:"",
defaultTime:"",
dateValue:"",
timeValue:"",
minDate: new Date().getFullYear().toString(),
show:false,
tabIndex:0,
dateTimeValue:""
}
},
props:{
placeholder:{
type:String,
default:"请选择日期时间"
},
type:{
type:String,
default:'dateTime' //date 只选择日期 dateTime选择日期时间
},
value:""
},
computed:{
list(){
let tabs =[]
if(this.type == 'dateTime'){
tabs = [
{
name:'日期'
},
{
name:'时间'
},
]
}
return tabs
}
},
watch: {
value:{
handler(val){
let res = formatGMT(val);
if(this.type == 'date'){
res = formatGMT(val,'D');
}
this.dateTimeValue = res ? res : '';
},
immediate:true
}
},
created() {
this.setDefaultDateTime();
},
methods: {
open(){
this.show = true
},
close(){
this.show = false
},
switchTab(val){
this.tabIndex = val.index
},
confirm(){
this.close()
let date = ''
this.dateValue = this.defaultDate;
if(this.type == 'date'){
date = new Date(`${this.defaultDate} 00:00:00`)
}else{
this.timeValue = this.defaultTime;
date = new Date(`${this.defaultDate} ${this.defaultTime}`)
}
this.$emit('input',date);
},
setDefaultDateTime(){
const {Y,M,D,h,m,s} = dateTransformYMDhms(new Date());
this.defaultDate = `${Y}-${M}-${D}`;
this.defaultTime = this.type == 'date' ? '' : `${h}:${m}:${s}`;
},
onChangeDate(date){
this.defaultDate = date;
},
onChangeTime(time){
this.defaultTime = time;
}
}
}
</script>
<style lang="scss">
.popup-box {
position: relative;
background: #fff;
border-radius: 32rpx 32rpx 0rpx 0rpx;
padding-bottom: 0rpx;
.popup-header{
padding-top: 24rpx;
}
.popup-title{
font-size: 32rpx;
text-align: center;
margin-bottom: 18rpx;
}
.close{
position: absolute;
top: 24rpx;
right: 24rpx;
display: inline-block;
width: 40rpx;
height: 40rpx;
}
/deep/.uicon-close{
font-size: 32rpx !important;
}
/deep/ .u-icon{
width: 32rpx !important;
position:absolute !important;
top: 24rpx !important;
right: 24rpx !important;
}
/deep/.u-tabs{
padding:0 64rpx;
}
}
.dateTime{
/deep/.u-popup__content {
border-radius: 32rpx 32rpx 0 0 !important;
padding-bottom: 50rpx !important;
}
}
uni-picker-view {
display: block;
}
uni-picker-view .uni-picker-view-wrapper {
display: flex;
position: relative;
overflow: hidden;
height: 100%;
background-color: white;
}
uni-picker-view[hidden] {
display: none;
}
picker-view {
width: 100%;
height: 600upx;
margin-top:20upx;
}
.item {
line-height: 100upx;
text-align: center;
}
.input-tip{
font-size: 14px;
color: #BFBFBF;
}
</style>
\ No newline at end of file
// 日期模式
export const DATE_TYPES = {
// 年月日
YMD: 1,
// 年月
YM: 2,
// 年份
Y: 3,
// 年月日时分秒
'YMD-HMS': 4,
// 时分秒
HMS: 5,
// 时分
HM: 6
};
.picker-view {
height: 356rpx;
}
.picker-view-column {
font-size: 14px;
line-height: 34px;
text-align: center;
color: #333;
}
/* 覆盖默认样式,样式可以按需自己改 */
.uni-picker-view-indicator {
background-color: rgba(106, 123, 255, 0.1);
}
.uni-picker-view-indicator::before,
.uni-picker-view-indicator::after {
content: none;
}
export default {
data() {
return {};
},
props: {
// 所有列选项数据
columns: {
type: Array,
default: () => []
},
// 每一列默认选中值数组,不传默认选中第一项
selectVals: {
type: Array,
default: () => []
}
},
computed: {
// 每一列选中项的索引,当默认选中值变化的时候这个值也要变化
indexArr: {
// 多维数组,深度监听
cache: false,
get() {
if (this.selectVals.length > 0) {
return this.columns.map((col, cIdx) => {
return col.findIndex((i) => i == this.selectVals[cIdx]);
});
} else {
return [].fill(0, 0, this.columns.length);
}
}
}
},
methods: {
onChange(e) {
const { value } = e.detail;
let ret = this.columns.map((item, index) => {
let idx = value[index];
if (idx < 0) {
idx = 0;
}
if (idx > item.length - 1) {
idx = item.length - 1;
}
return item[idx];
});
this.$emit('onChange', {
value: ret
});
}
}
};
<template>
<picker-view class="picker-view" :value="indexArr" @change="onChange">
<picker-view-column class="picker-view-column" v-for="(col, colIdx) in columns" :key="colIdx">
<view v-for="(item, idx) in col" :key="idx">{{ item }}</view>
</picker-view-column>
</picker-view>
</template>
<script src="./index.js"></script>
<style lang="css" scoped src="./index.css"></style>
/**
* 日期时间格式化
* @param {Date} date 要格式化的日期对象
* @param {String} fmt 格式化字符串,eg:YYYY-MM-DD HH:mm:ss
* @returns 格式化后的日期字符串
*/
function formatDate(date, fmt) {
if (typeof date == 'string') {
date = new Date(handleDateStr(date));
}
const o = {
'M+': date.getMonth() + 1, // 月份
'd+': date.getDate(), // 日
'D+': date.getDate(), // 日
'H+': date.getHours(), // 小时
'h+': date.getHours(), // 小时
'm+': date.getMinutes(), // 分
's+': date.getSeconds(), // 秒
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
S: date.getMilliseconds() // 毫秒
};
if (/([y|Y]+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').slice(4 - RegExp.$1.length));
}
for (const k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).slice(('' + o[k]).length));
}
}
return fmt;
}
/**
* 处理时间字符串,兼容ios下new Date()返回NaN问题
* @param {*} dateStr 日期字符串
* @returns
*/
function handleDateStr(dateStr) {
return dateStr.replace(/\-/g, '/');
}
/**
* 判断日期1是否在日期2之前,即日期1小于日期2
* @param {Date} date1
* @param {Date} date2
* @returns
*/
function isBefore(date1, date2) {
if (typeof date1 == 'string') {
date1 = new Date(handleDateStr(date1));
}
if (typeof date2 == 'string') {
date2 = new Date(handleDateStr(date2));
}
return date1.getTime() < date2.getTime();
}
/**
* 判断日期1是否在日期2之后,即日期1大于日期2
* @param {Date} date1
* @param {Date} date2
* @returns
*/
function isAfter(date1, date2) {
if (typeof date1 == 'string') {
date1 = new Date(handleDateStr(date1));
}
if (typeof date2 == 'string') {
date2 = new Date(handleDateStr(date2));
}
return date1.getTime() > date2.getTime();
}
/**
* 检查传入的字符串是否能转换为有效的Date对象
* @param {String} date
* @returns {Boolean}
*/
function isValid(date) {
return new Date(date) !== 'Invalid Date' && !isNaN(new Date(date));
}
export default {
formatDate,
handleDateStr,
isBefore,
isAfter,
isValid
};
import CustomPickerView from '../customPickerView/index.vue';
import DateUtil from './dateUtil';
import { DATE_TYPES } from '../constant';
export default {
components: {
CustomPickerView
},
props: {
// 日期模式,1:年月日(默认),2:年月,3:年份,4:年月日时分秒,5:时分秒,6:时分
mode: {
type: Number,
default: DATE_TYPES.YMD
},
// 可选的最小日期,默认十年前
minDate: {
type: String,
default: ''
},
// 可选的最大日期,默认十年后
maxDate: {
type: String,
default: ''
},
// 默认选中日期(注意要跟日期模式对应)
defaultDate: {
type: String,
default: ''
}
},
data() {
return {
selectYear: new Date().getFullYear(),
selectMonth: new Date().getMonth() + 1, // 选中的月份,1~12
selectDay: new Date().getDate(),
selectHour: new Date().getHours(),
selectMinute: new Date().getMinutes(),
selectSecond: new Date().getSeconds()
};
},
watch: {
defaultDate: {
immediate: true,
handler(val) {
if (val) {
if (this.mode == DATE_TYPES.YM && val.replace(/\-/g, '/').split('/').length == 2) {
// 日期模式为年月时有可能传进来的defaultDate是2022-02这样的格式,在ios下new Date会报错,加上日期部分做兼容
val += '-01';
} else if (this.mode == DATE_TYPES.HMS || this.mode == DATE_TYPES.HM) {
// 只有时分秒或者只有时分是不能调用new Date生成Date对象的,先加上一个假设的年月日(就取当年一月一日)来兼容
const now = new Date();
val = `${now.getFullYear()}-01-01 ${val}`;
}
let date = new Date(DateUtil.handleDateStr(val));
this.selectYear = date.getFullYear();
this.selectMonth = date.getMonth() + 1;
this.selectDay = date.getDate();
this.selectHour = date.getHours();
this.selectMinute = date.getMinutes();
this.selectSecond = date.getSeconds();
}
}
}
},
computed: {
minDateObj() {
let minDate = this.minDate;
if (minDate) {
if (this.mode == DATE_TYPES.YM && minDate.replace(/\-/g, '/').split('/').length == 2) {
// 日期模式为年月时有可能传进来的minDate是2022-02这样的格式,在ios下new Date会报错,加上日期部分做兼容
minDate += '-01';
} else if (this.mode == DATE_TYPES.HMS || this.mode == DATE_TYPES.HM) {
// 只有时分秒或者只有时分是不能调用new Date生成Date对象的,先加上一个假设的年月日(就取当年一月一日)来兼容
const now = new Date();
minDate = `${now.getFullYear()}-01-01 ${minDate}`;
}
return new Date(DateUtil.handleDateStr(minDate));
} else {
// 没有传最小日期,默认十年前
let year = new Date().getFullYear() - 10;
minDate = new Date(year, 0, 1);
return minDate;
}
},
maxDateObj() {
let maxDate = this.maxDate;
if (maxDate) {
if (this.mode == DATE_TYPES.YM && maxDate.replace(/\-/g, '/').split('/').length == 2) {
// 日期模式为年月时有可能传进来的maxDate是2022-02这样的格式,在ios下new Date会报错,加上日期部分做兼容
maxDate += '-01';
} else if (this.mode == DATE_TYPES.HMS || this.mode == DATE_TYPES.HM) {
// 只有时分秒或者只有时分是不能调用new Date生成Date对象的,先加上一个假设的年月日(就取当年一月一日)来兼容
const now = new Date();
maxDate = `${now.getFullYear()}-01-01 ${maxDate}`;
}
return new Date(DateUtil.handleDateStr(maxDate));
} else {
// 没有传最大日期,默认十年后
let year = new Date().getFullYear() + 10;
maxDate = new Date(year, 11, 31);
return maxDate;
}
},
years() {
let years = [];
let minYear = this.minDateObj.getFullYear();
let maxYear = this.maxDateObj.getFullYear();
for (let i = minYear; i <= maxYear; i++) {
years.push(i);
}
return years;
},
months() {
let months = [];
let minMonth = 1;
let maxMonth = 12;
// 如果选中的年份刚好是最小可选日期的年份,那月份就要从最小日期的月份开始
if (this.selectYear == this.minDateObj.getFullYear()) {
minMonth = this.minDateObj.getMonth() + 1;
}
// 如果选中的年份刚好是最大可选日期的年份,那月份就要在最大日期的月份结束
if (this.selectYear == this.maxDateObj.getFullYear()) {
maxMonth = this.maxDateObj.getMonth() + 1;
}
for (let i = minMonth; i <= maxMonth; i++) {
months.push(i);
}
return months;
},
days() {
// 一年中12个月每个月的天数
let monthDaysConfig = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
// 闰年2月有29天
if (this.selectMonth == 2 && this.selectYear % 4 == 0) {
monthDaysConfig[1] = 29;
}
let minDay = 1;
let maxDay = monthDaysConfig[this.selectMonth - 1];
if (this.selectYear == this.minDateObj.getFullYear() && this.selectMonth == this.minDateObj.getMonth() + 1) {
minDay = this.minDateObj.getDate();
}
if (this.selectYear == this.maxDateObj.getFullYear() && this.selectMonth == this.maxDateObj.getMonth() + 1) {
maxDay = this.maxDateObj.getDate();
}
let days = [];
for (let i = minDay; i <= maxDay; i++) {
days.push(i);
}
return days;
},
hours() {
let hours = [];
let minHour = 0;
let maxHour = 23;
if (
this.selectYear == this.minDateObj.getFullYear() &&
this.selectMonth == this.minDateObj.getMonth() + 1 &&
this.selectDay == this.minDateObj.getDate()
) {
minHour = this.minDateObj.getHours();
}
if (
this.selectYear == this.maxDateObj.getFullYear() &&
this.selectMonth == this.maxDateObj.getMonth() + 1 &&
this.selectDay == this.maxDateObj.getDate()
) {
maxHour = this.maxDateObj.getHours();
}
for (let i = minHour; i <= maxHour; i++) {
hours.push(i);
}
return hours;
},
minutes() {
let mins = [];
let minMin = 0;
let maxMin = 59;
if (
this.selectYear == this.minDateObj.getFullYear() &&
this.selectMonth == this.minDateObj.getMonth() + 1 &&
this.selectDay == this.minDateObj.getDate() &&
this.selectHour == this.minDateObj.getHours()
) {
minMin = this.minDateObj.getMinutes();
}
if (
this.selectYear == this.maxDateObj.getFullYear() &&
this.selectMonth == this.maxDateObj.getMonth() + 1 &&
this.selectDay == this.maxDateObj.getDate() &&
this.selectHour == this.maxDateObj.getHours()
) {
maxMin = this.maxDateObj.getMinutes();
}
for (let i = minMin; i <= maxMin; i++) {
mins.push(i);
}
return mins;
},
seconds() {
let seconds = [];
let minSecond = 0;
let maxSecond = 59;
if (
this.selectYear == this.minDateObj.getFullYear() &&
this.selectMonth == this.minDateObj.getMonth() + 1 &&
this.selectDay == this.minDateObj.getDate() &&
this.selectHour == this.minDateObj.getHours() &&
this.selectMinute == this.minDateObj.getMinutes()
) {
minSecond = this.minDateObj.getSeconds();
}
if (
this.selectYear == this.maxDateObj.getFullYear() &&
this.selectMonth == this.maxDateObj.getMonth() + 1 &&
this.selectDay == this.maxDateObj.getDate() &&
this.selectHour == this.maxDateObj.getHours() &&
this.selectMinute == this.maxDateObj.getMinutes()
) {
maxSecond = this.maxDateObj.getSeconds();
}
for (let i = minSecond; i <= maxSecond; i++) {
seconds.push(i);
}
return seconds;
},
// 传给pickerView组件的数组,根据mode来生成不同的数据
dateConfig() {
let years = this.years.map((y) => y + '年');
let months = this.months.map((m) => m + '月');
let days = this.days.map((d) => d + '日');
let hours = this.hours.map((h) => h + '时');
let minutes = this.minutes.map((m) => m + '分');
let seconds = this.seconds.map((s) => s + '秒');
let ret = [];
switch (this.mode) {
case DATE_TYPES.YM:
ret = [years, months];
break;
case DATE_TYPES.Y:
ret = [years];
break;
case DATE_TYPES['YMD-HMS']:
ret = [years, months, days, hours, minutes, seconds];
break;
case DATE_TYPES.HMS:
ret = [hours, minutes, seconds];
break;
case DATE_TYPES.HM:
ret = [hours, minutes];
break;
default:
ret = [years, months, days];
break;
}
return ret;
},
selectVals() {
let ret = [];
switch (this.mode) {
case DATE_TYPES.YM:
ret = [this.selectYear + '年', this.selectMonth + '月'];
break;
case DATE_TYPES.Y:
ret = [this.selectYear + '年'];
break;
case DATE_TYPES['YMD-HMS']:
ret = [
this.selectYear + '年',
this.selectMonth + '月',
this.selectDay + '日',
this.selectHour + '时',
this.selectMinute + '分',
this.selectSecond + '秒'
];
break;
case DATE_TYPES.HMS:
ret = [this.selectHour + '时', this.selectMinute + '分', this.selectSecond + '秒'];
break;
case DATE_TYPES.HM:
ret = [this.selectHour + '时', this.selectMinute + '分'];
break;
default:
ret = [this.selectYear + '年', this.selectMonth + '月', this.selectDay + '日'];
break;
}
return ret;
}
},
methods: {
onChangePickerValue(e) {
const { value } = e;
if (this.mode == DATE_TYPES.YM && value[0] && value[1]) {
// 年月模式
this.selectYear = Number(value[0].replace('年', ''));
this.selectMonth = Number(value[1].replace('月', ''));
} else if (this.mode == DATE_TYPES.Y && value[0]) {
// 只有年份模式
this.selectYear = Number(value[0].replace('年', ''));
} else if (this.mode == DATE_TYPES['YMD-HMS'] && value[0] && value[1] && value[2] != '' && value[3] && value[4] && value[5]) {
// 年月日时分秒模式
this.selectYear = Number(value[0].replace('年', ''));
this.selectMonth = Number(value[1].replace('月', ''));
this.selectDay = Number(value[2].replace('日', ''));
this.selectHour = Number(value[3].replace('时', ''));
this.selectMinute = Number(value[4].replace('分', ''));
this.selectSecond = Number(value[5].replace('秒', ''));
} else if (this.mode == DATE_TYPES.HMS && value[0] && value[1] && value[2]) {
// 时分秒模式
this.selectHour = Number(value[0].replace('时', ''));
this.selectMinute = Number(value[1].replace('分', ''));
this.selectSecond = Number(value[2].replace('秒', ''));
} else if (this.mode == DATE_TYPES.HM && value[0] && value[1]) {
// 时分模式
this.selectHour = Number(value[0].replace('时', ''));
this.selectMinute = Number(value[1].replace('分', ''));
} else if (value[0] && value[1] && value[2]) {
// 默认,年月日模式
this.selectYear = Number(value[0].replace('年', ''));
this.selectMonth = Number(value[1].replace('月', ''));
this.selectDay = Number(value[2].replace('日', ''));
} else {
// 其他情况可能是pickerView返回的数据有问题,不处理
console.log('onChangePickerValue其他情况');
return;
}
let formatTmpl = 'YYYY-MM-DD';
switch (this.mode) {
case DATE_TYPES.YM:
formatTmpl = 'YYYY-MM';
break;
case DATE_TYPES.Y:
formatTmpl = 'YYYY';
break;
case DATE_TYPES['YMD-HMS']:
formatTmpl = 'YYYY-MM-DD HH:mm:ss';
break;
case DATE_TYPES.HMS:
formatTmpl = 'HH:mm:ss';
break;
case DATE_TYPES.HM:
formatTmpl = 'HH:mm';
break;
default:
break;
}
this.$emit(
'onChange',
DateUtil.formatDate(
new Date(`${this.selectYear}/${this.selectMonth}/${this.selectDay} ${this.selectHour}:${this.selectMinute}:${this.selectSecond}`),
formatTmpl
)
);
}
}
};
<template>
<view class="datetime-picker">
<CustomPickerView :columns="dateConfig" :selectVals="selectVals" @onChange="onChangePickerValue" />
</view>
</template>
<script src="./index.js"></script>
<style scoped lang="css"></style>
<template>
<view class="popupRadio">
<u-popup
:show="radioShow"
:mode="mode"
:closeable="closeable"
:closeOnClickOverlay="true"
@close="() => $emit('cancel')">
<view v-if="title" class="popupRadioTitle">
<text>{{title}}</text>
</view>
<!-- <view v-if="!radioList.length" style="height: 10vh; line-height: 10vh; text-align: center;">
暂无数据选择
</view> -->
<u-radio-group :value="currentSelect" placement="column" iconPlacement="right" @change="onChange" >
<u-radio
size="40" labelSize="28" iconSize="28"
labelColor="#434343"
:customStyle="{marginBottom: '8px'}"
v-for="(item, index) in radioList"
:key="index"
:label="item.label"
:name="item.value">
</u-radio>
</u-radio-group>
<view class="popupRadioFoot" v-if="showbtn">
<button @click="cancel">取消</button>
<button @click="confirm">确定</button>
</view>
</u-popup>
</view>
</template>
<script>
export default {
options: {
styleIsolation: 'shared'
},
props: {
radioShow: {
type: Boolean,
default: false
},
radioList: {
type: Array,
default: []
},
mode: {
type: String,
default: "bottom"
},
title: {
type: String,
default: ""
},
currentSelect: {
type: String,
default: ""
},
showbtn:{
type: Boolean,
default: false
},
closeable:{
type: Boolean,
default: false
},
},
name: "popupRadio",
data() {
return {
currentSelectName: ""
};
},
onLoad: function(options) {
console.log(this.radioList)
},
onShow() {
console.log(1)
console.log(this.radioList)
},
methods: {
confirm() {
this.$emit('confirm', this.currentSelectName)
},
cancel(){
this.$emit('cancel')
},
onChange(value){
this.currentSelectName = value
this.$emit('onChange',value)
},
},
mounted() {
}
}
</script>
<style lang="scss" scoped>
.popupRadio {
opacity: 1;
/deep/.uicon-close{
font-size: 32rpx !important;
}
/deep/.u-popup__content {
border-radius: 32rpx 32rpx 0 0;
padding-bottom: 250rpx;
}
.popupRadioTitle {
margin-top: 48rpx;
text-align: center;
color: #8C8C8C;
font-size: 32rpx;
}
/deep/.u-radio-group {
margin: 48rpx;
margin-bottom: 0rpx;
max-height: 50vh;
overflow-y: scroll;
.u-radio {
height: 45rpx;
line-height: 45rpx;
}
.u-radio__text {
font-size: 32rpx !important;
}
.u-radio__icon-wrap {
height: 32rpx !important;
width: 32rpx !important;
line-height: 32rpx;
}
}
/deep/.popupRadioFoot{
display: flex;
justify-content: space-between;
bottom: 100rpx;
width: 100%;
button{
width: 339rpx;
height: 88rpx;
line-height: 88rpx;
border-radius: 44rpx;
color: #2E75E6;
padding: 0 24rpx;
border: 3rpx solid transparent;
position: relative;
background-clip: padding-box, border-box;
background-origin: padding-box, border-box;
background-image: linear-gradient(90deg, #FAFAFA, #FAFAFA), linear-gradient(90deg, #2E75E6, #5E58EE);
&:after{
content: "";
}
&:last-child{
background-image: linear-gradient(90deg, #2E75E6, #5E58EE), linear-gradient(90deg, #2E75E6, #5E58EE);
color: #FFFFFF;
}
}
}
}
</style>
<template>
<view class="header">
<view class="search-input">
<view class="filter-container">
<!-- 报告人输入框 -->
<text class="label">报告人:</text>
<u-input v-model="filterReporter" placeholder="提交人" class="filter-input"></u-input>
</view>
<view class="filter-container">
<!-- 日期输入框 -->
<text class="label">日期:</text>
<view class="search-time">
<bs-dateTimePicker2 class="date-picker" v-model="filterTime" type="date" placeholder="请选择报告日期">
<u-icon slot="rightIcon" name="arrow-right" />
</bs-dateTimePicker2>
</view>
</view>
<button class="search-btn" @click="performSearch">搜索</button>
<button class="clear-btn" @click="clearSearch">清空</button>
</view>
<view class="daily-report" style="top: 155px;">
<scroll-view class="report-list" scroll-y>
<view class="report-card" v-for="(report, index) in dailyReportList" :key="index">
<view class="card-header">
<view class="left">
<text class="name">员工:{{ report.reporter }}</text>
<text class="status" :class="getStatusClass(report.is_over_time)">
{{ report.is_over_time }}
</text>
</view>
<text class="time">{{ report.date_str || '-' }}</text>
</view>
<view class="card-content">
<view class="work-item">
<view class="work-header">
<text class="work-title">本周重点工作</text>
</view>
<view class="work-content">{{ report.week_work }}</view>
</view>
<view class="work-item">
<view class="work-header">
<text class="work-title">今日重点工作</text>
</view>
<view class="work-content">{{ report.today_work }}</view>
</view>
<view class="work-item">
<view class="work-header">
<text class="work-title">是否请假</text>
</view>
<view class="work-content">{{ report.is_leave }}</view>
</view>
<view class="work-item" v-if="report.is_leave==='是'">
<view class="work-header">
<text class="work-title">请假原因</text>
</view>
<view class="work-content">{{ report.leave_reason ||''}}</view>
</view>
</view>
</view>
<view style="height: 10vh;"></view>
</scroll-view>
</view>
<!-- 新增按钮 -->
<!-- <button class="add-button" @click="addNewReport">新增</button> -->
</view>
</template>
<script>
import {
queryDailyReport
} from '../../api/apiList'
import {
formatGMT
} from '../../utils/util'
export default {
data() {
return {
searchStatus: "all",
staffCode: "",
staffKind: "",
searchDatas: {},
commonName: "",
dailyReportList: [],
filterReporter: '', // 用于报告人筛选的输入
filterTime: '' // 用于时间筛选的输入
}
},
mounted() {
console.log("onShow")
this.onReload()
},
onShow() {
console.log("onShow")
this.onReload(); // 页面显示时调用数据加载方法
},
onPullDownRefresh: function() {
console.log("下拉刷新")
this.onReload()
},
onLoad() {
this.onReload(); // 页面加载时调用数据加载方法
},
methods: {
addNewReport() {
uni.navigateTo({
url: '/pages/dailyReportCreate/dailyReportCreate'
});
},
clearSearch(){
this.filterTime=""
this.filterReporter=""
this.dailyReportList = []
this.initData()
},
performSearch() {
this.dailyReportList = []
this.initData()
},
convertTime(timestamp) {
if (!timestamp) return
const nowDate = new Date(timestamp)
var year = nowDate.getFullYear();
var month = String(nowDate.getMonth() + 1).padStart(2, '0');
var date = nowDate.getDate();
return `${year}-${month}-${date}`
},
initData() {
const data = this.createSelectData()
uni.showLoading({
title: '加载中...',
});
queryDailyReport(data).then(res => {
uni.stopPullDownRefresh();
const data = res.data.data.datas;
data.map(item => { //格式化时间
item.insert_date = formatGMT(item.insert_date, 'T')
})
this.dailyReportList = data
}).catch(err => {
console.error('获取日报数据失败:', err);
uni.showToast({
title: '获取数据失败',
icon: 'none'
});
}).finally(() => {
uni.hideLoading();
});
},
createSelectData() {
this.staffCode = uni.getStorageSync('staffCode');
this.staffKind = uni.getStorageSync('uc_staff_kind');
const time = this.convertTime(this.filterTime)
let fields = []
var num = 0;
if (time) {
fields.push({
"name": "date_str",
"label": "上报批次",
"ignore": false,
"caseSensitive": true,
"quickFilterField": "date_str",
"restriction": "eq",
"value": time,
"num": num
})
num = num + 1
}
if (this.filterReporter) {
fields.push({
"name": "reporter",
"label": "报告人",
"ignore": false,
"caseSensitive": true,
"quickFilterField": "reporter",
"restriction": "like",
"value": this.filterReporter,
"num": num
})
num = num + 1
}
if (this.staffKind === 'President' || this.staffKind === 'VicePresident' || this.staffKind ===
'PresidentHelp') {
fields.push({
"name": "staff__uc_staff_kind",
"label": "员工_员工分类",
"ignore": false,
"caseSensitive": true,
"quickFilterField": "staff__uc_staff_kind",
"restriction": "eq",
"value": "simulatedBoss",
"num": num
})
num = num + 1
}
if (this.staffKind === 'Leader' || this.staffKind === 'simulatedBoss') {
fields.push({
"name": "reporterTo__code",
"label": "汇报对象编码",
"ignore": false,
"caseSensitive": true,
"quickFilterField": "reporterTo__code",
"restriction": "eq",
"value": this.staffCode,
"num": num
})
num = num + 1
}
const data = {
"getTotalBy": "count",
"fields": [],
"keyword": {
"value": "",
"exact": false,
"partialMatchMode": "contain",
"caseSensitive": true
},
"filter": {
"fields": []
},
"refFields": [],
"order": [],
"quickFilter": {
"relationDataset": "zcgyl_dailyreport_boss_search__quickFilterDataSet",
"fields": fields
},
"tableHeaderFilter": {
"relationDataset": "zcgyl_dailyreport_boss_search__tableHeaderFilterDataSet",
"fields": []
},
"pageNum": 1,
"pageSize": 50,
"aggregation": {}
}
return data
},
onReload() {
this.dailyReportList = []
this.initData()
},
getStatusClass(status) {
const classMap = {
'超时': 'status-pending',
'准时': 'status-completed'
}
return classMap[status] || ''
},
}
}
</script>
<style lang="scss">
html,
body {
height: 95%;
/* 确保 html 和 body 高度为 100% */
margin: 0;
/* 去掉默认的 margin */
overfl: hidden;
/* 禁用滚动条 */
}
.status {
padding: 4px 6px;
border-radius: 10px;
font-size: 12px;
&.status-pending {
background: rgba(250, 173, 20, 0.1);
color: #FF4D4F;
border: 1px solid rgba(250, 173, 20, 0.2);
}
&.status-processing {
background: rgba(24, 144, 255, 0.1);
color: #fadf0d;
border: 1px solid rgba(24, 144, 255, 0.2);
}
&.status-completed {
background: rgba(82, 196, 26, 0.1);
color: #52C41A;
border: 1px solid rgba(82, 196, 26, 0.2);
}
}
.filter-input {
flex: 1;
border: 1px solid #ddd;
border-radius: 4px;
padding: 10px;
font-size: 14px;
}
.date-picker {
flex: 1;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
.header {
.search-input {
background: #fff;
// border-radius: 8px;
position: fixed;
z-index: 999;
width: 100%;
top: 0;
.search-time {
flex-grow: 1;
/* 输入框扩展以填充剩余空间 */
position: relative;
.uni-text {
width: 100%;
padding: 8px 12px;
border: 1px solid #ccc;
&::placeholder {
color: #aaa;
font-size: 14px;
}
&--focus {
border-color: #4e9dff;
outline: none;
}
}
}
}
.search-btn {
background-color: #375dcded;
color: white;
border-radius: 4px;
font-size: 16px;
float: right;
width: 72px;
margin-right: 5%;
margin-bottom: 10px;
}
.clear-btn {
background-color: #29cd04ed;
color: white;
border-radius: 4px;
font-size: 16px;
float: right;
width: 72px;
margin-right: 5%;
margin-bottom: 10px;
}
.search-btn:hover {
background-color: #375dcded;
/* 悬停时的背景色 */
}
}
.contont {
margin-top: 30%;
}
.filter-container {
display: flex;
justify-content: space-between;
padding: 10px;
}
.picker {
.picker-text {
line-height: 40px;
color: #333;
}
}
.label {
width: 80px;
font-size: 16px;
color: #333;
padding: 10px;
}
.add-button {
position: fixed;
bottom: 20px;
left: 0;
right: 0;
background-color: #3278e9;
color: white;
border: none;
border-radius: 24px;
padding: 8px;
font-size: 16px;
font-weight: bolder;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
cursor: pointer;
z-index: 1000;
width: 40%;
}
.add-button:hover {
background-color: #40a9ff;
/* 悬停时的背景色 */
}
.daily-report {
background: #f5f7fa;
min-height: calc(100vh - 60px);
position: relative;
padding-bottom: 60px;
padding: 20px 15px;
border-radius: 8px;
.report-list {
.report-card {
display: block;
background: #fff;
border-radius: 8px;
padding: 15px;
margin-top: 15px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
.left {
display: flex;
align-items: center;
gap: 10px;
.name {
font-size: 16px;
font-weight: bold;
color: #333;
position: relative;
padding-left: 12px;
&:before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 16px;
background: #1890ff;
border-radius: 2px;
}
}
.status {
padding: 4px 12px;
border-radius: 10px;
font-size: 12px;
&.submitted {
background: rgba(82, 196, 26, 0.1);
color: #52c41a;
border: 1px solid rgba(82, 196, 26, 0.2);
}
&.unSubmitted {
background: rgba(255, 77, 79, 0.1);
color: #ff4d4f;
border: 1px solid rgba(255, 77, 79, 0.2);
}
}
}
.time {
font-size: 14px;
color: #999;
}
}
.card-content {
.work-item {
display: block;
border-top: 1px solid #f0f0f0;
padding-top: 10px;
margin-bottom: 10px;
.work-header {
display: flex;
align-items: center;
margin-bottom: 8px;
position: relative;
padding-left: 12px;
&:before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 14px;
background: #1890ff;
opacity: 1;
border-radius: 1.5px;
}
}
.work-title {
font-size: 14px;
color: #333;
font-weight: 500;
}
.work-content {
font-size: 14px;
color: #666;
line-height: 1.6;
padding: 12px 15px;
background: #fafafa;
border-radius: 4px;
white-space: pre-wrap;
word-break: break-all;
text-align: justify;
}
}
}
}
}
}
</style>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment