Files
jnpf_app/components/Jnpf/DateCalculate/index.vue
2026-01-04 11:09:06 +08:00

221 lines
4.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="jnpf-calculation jnpf-calculation-right">
<u-input input-align='right' :modelValue="jnpf.toDate(innerValue, format)" disabled placeholder='' />
</view>
</template>
<script>
import {
dayjs
} from '@/uni_modules/iRainna-dayjs/js_sdk/dayjs.min.js'
const calcRPN = rpnExps => {
rpnExps = rpnExps.concat()
const calc = (x, y, type) => {
let a1 = Number(x),
a2 = Number(y)
switch (type) {
case '+':
return a1 + a2;
case '-':
return a1 - a2;
case '×':
return a1 * a2;
case '÷':
return a1 / a2;
}
}
for (let i = 2; i < rpnExps.length; i++) {
if ('+-×÷'.includes(rpnExps[i])) {
let val = calc(rpnExps[i - 2], rpnExps[i - 1], rpnExps[i])
rpnExps.splice(i - 2, 3, val)
i = i - 2
}
}
return rpnExps[0]
}
const mergeNumberOfExps = expressions => {
const res = []
const isNumChar = n => /^[\d|\.]$/.test(n)
for (let i = 0; i < expressions.length; i++) {
if (i > 0 && isNumChar(expressions[i - 1]) && isNumChar(expressions[i])) {
res[res.length - 1] += expressions[i]
continue
}
res.push(expressions[i])
}
return res
}
export default {
name: 'jnpf-date-calculation',
props: {
modelValue: {
type: [String, Number],
default: ''
},
expression: {
type: Array,
default: []
},
formData: {
type: Object,
default: {}
},
rowIndex: {
type: [String, Number],
default: ''
},
startRelationField: String,
startTimeValue: [String, Number],
startTimeType: {
default: 1,
type: Number,
},
format: {
default: 'yyyy-MM-dd',
type: String,
},
},
data() {
return {
innerValue: '',
startTime: new Date(),
}
},
computed: {
getExp() {
return mergeNumberOfExps(this.expression)
},
},
watch: {
formData: {
handler(val, oldVal) {
setTimeout(() => {
this.execRPN()
}, 0)
},
deep: true,
immediate: true
},
modelValue: {
handler(val, oldVal) {
this.innerValue = val
},
deep: true,
immediate: true
},
},
methods: {
/**
* 计算表达式
*/
execRPN() {
const temp = this.getExp.map(t => typeof t === 'object' ? this.getFormVal(t.__vModel__) : t)
if (this.startTimeType == 1) this.startTime = this.startTimeValue;
if (this.startTimeType == 2) this.startTime = this.getFormVal(this.startRelationField);
this.innerValue = this.calcDate(this.startTime, this.getDateInfo(temp));
this.$emit('update:modelValue', this.innerValue)
},
getDateInfo(exp) {
let days = 0;
let months = 0;
let years = 0;
let hours = 0;
let minutes = 0;
let seconds = 0;
for (let i = 0; i < exp.length; i += 3) {
const sign = exp[i];
const value = Number.parseInt(exp[i + 1], 10);
const unit = exp[i + 2];
const factor = sign === '+' ? 1 : -1;
switch (unit) {
case 'd': {
days += factor * value;
break;
}
case 'h': {
hours += factor * value;
break;
}
case 'M': {
months += factor * value;
break;
}
case 'm': {
minutes += factor * value;
break;
}
case 's': {
seconds += factor * value;
break;
}
case 'Y': {
years += factor * value;
break;
}
}
}
return {
days,
hours,
minutes,
months,
seconds,
years
};
},
calcDate(date, change) {
if (!date) return '';
const newDate = new Date(date);
newDate.setFullYear(newDate.getFullYear() + change.years);
newDate.setMonth(newDate.getMonth() + change.months);
newDate.setDate(newDate.getDate() + change.days);
newDate.setHours(newDate.getHours() + change.hours);
newDate.setMinutes(newDate.getMinutes() + change.minutes);
newDate.setSeconds(newDate.getSeconds() + change.seconds);
return dayjs(newDate).startOf(this.jnpf.getDateTimeUnit(this.format)).valueOf();
},
/**
* 获取指定组件的值
*/
getFormVal(vModel) {
try {
if (vModel.indexOf('.') > -1) {
let [tableVModel, cmpVModel] = vModel.split('.');
if (typeof this.rowIndex === 'number') {
if (!Array.isArray(this.formData[tableVModel]) || this.formData[tableVModel].length < this
.rowIndex + 1) return 0;
return this.formData[tableVModel][this.rowIndex][cmpVModel] || 0;
} else {
if (!this.formData[tableVModel].length) return 0;
return this.formData[tableVModel].reduce((sum, c) => (c[cmpVModel] ? Number(c[cmpVModel]) :
0) + sum, 0);
}
}
return this.formData[vModel] || 0
} catch (error) {
console.warn('计算公式出错, 可能包含无效的组件值', error)
return 0
}
},
}
}
</script>
<style lang="scss" scoped>
.jnpf-calculation {
width: 100%;
&.jnpf-calculation-right {
text-align: right;
}
.tips {
color: #999999;
line-height: 40rpx;
}
.unit {
padding-left: 10rpx;
}
}
</style>