@@ -12,3 +12,5 @@ yarn-error.log* | |||||
*.ntvs* | *.ntvs* | ||||
*.njsproj | *.njsproj | ||||
*.sln | *.sln | ||||
dist.* |
@@ -0,0 +1,181 @@ | |||||
import request from '@/utils/request' | |||||
// 查询统计报列表 | |||||
export function listReporttitle(query) { | |||||
return request({ | |||||
url: '/entity/reporttitle/list', | |||||
method: 'get', | |||||
params: query | |||||
}) | |||||
} | |||||
// 导出统计报 | |||||
export function exportReporttitle(query) { | |||||
return request({ | |||||
url: '/entity/reporttitle/export', | |||||
method: 'get', | |||||
params: query | |||||
}) | |||||
} | |||||
// 查询统计报详细 | |||||
export function getReporttitle(id) { | |||||
return request({ | |||||
url: '/entity/reporttitle/get/' + id, | |||||
method: 'get' | |||||
}) | |||||
} | |||||
// 新增统计报 | |||||
export function addReporttitle(data) { | |||||
return request({ | |||||
url: '/entity/reporttitle/add', | |||||
method: 'post', | |||||
data: data | |||||
}) | |||||
} | |||||
// 修改统计报 | |||||
export function updateReporttitle(data) { | |||||
return request({ | |||||
url: '/entity/reporttitle/edit', | |||||
method: 'post', | |||||
data: data | |||||
}) | |||||
} | |||||
// 删除统计报 | |||||
export function delReporttitle(id) { | |||||
return request({ | |||||
url: '/entity/reporttitle/remove/' + id, | |||||
method: 'get' | |||||
}) | |||||
} | |||||
// 启用统计报 | |||||
export function enableReporttitle(id) { | |||||
return request({ | |||||
url: '/entity/reporttitle/enable/' + id, | |||||
method: 'post' | |||||
}) | |||||
} | |||||
// 禁用统计报 | |||||
export function disableReporttitle(id) { | |||||
return request({ | |||||
url: '/entity/reporttitle/disable/' + id, | |||||
method: 'post' | |||||
}) | |||||
} | |||||
// 获取模板 | |||||
export function getReportTemplate(id) { | |||||
return request({ | |||||
url: '/entity/reporttitle/template/' + id, | |||||
method: 'get' | |||||
}) | |||||
} | |||||
// 获取横向模板 | |||||
export function getReportHorizontalTemplate(id) { | |||||
return request({ | |||||
url: '/entity/reporttitle/horizontalTemplate/' + id, | |||||
method: 'get' | |||||
}) | |||||
} | |||||
// 查询统计填报列表 | |||||
export function listReport(query) { | |||||
return request({ | |||||
url: '/entity/report/list', | |||||
method: 'get', | |||||
params: query | |||||
}) | |||||
} | |||||
// 导出统计填报 | |||||
export function exportReport(query) { | |||||
return request({ | |||||
url: '/entity/report/export', | |||||
method: 'get', | |||||
params: query | |||||
}) | |||||
} | |||||
// 查询统计填报详细 | |||||
export function getReport(id) { | |||||
return request({ | |||||
url: '/entity/report/get/' + id, | |||||
method: 'get' | |||||
}) | |||||
} | |||||
// 新增统计填报 | |||||
export function addReport(data) { | |||||
return request({ | |||||
url: '/entity/report/add', | |||||
method: 'post', | |||||
data: data | |||||
}) | |||||
} | |||||
// 修改统计填报 | |||||
export function updateReport(data) { | |||||
return request({ | |||||
url: '/entity/report/edit', | |||||
method: 'post', | |||||
data: data | |||||
}) | |||||
} | |||||
// 删除统计填报 | |||||
export function delReport(id) { | |||||
return request({ | |||||
url: '/entity/report/remove/' + id, | |||||
method: 'get' | |||||
}) | |||||
} | |||||
// 导出统计填报 | |||||
export function reportExport(id) { | |||||
return request({ | |||||
url: '/entity/report/reportExport/' + id, | |||||
method: 'get', | |||||
}) | |||||
} | |||||
// 竖向统计 | |||||
export function summaryStatistics(query) { | |||||
return request({ | |||||
url: '/entity/report/summaryStatistics', | |||||
method: 'get', | |||||
params: query | |||||
}) | |||||
} | |||||
// 导出竖向统计 | |||||
export function summaryStatisticsExport(query) { | |||||
return request({ | |||||
url: '/entity/report/summaryStatisticsExport', | |||||
method: 'get', | |||||
params: query | |||||
}) | |||||
} | |||||
// 横向统计 | |||||
export function horizontalSummaryStatistics(query) { | |||||
return request({ | |||||
url: '/entity/report/horizontalSummaryStatistics', | |||||
method: 'get', | |||||
params: query | |||||
}) | |||||
} | |||||
// 导出横向统计 | |||||
export function horizontalSummaryStatisticsExport(query) { | |||||
return request({ | |||||
url: '/entity/report/horizontalSummaryStatisticsExport', | |||||
method: 'get', | |||||
params: query | |||||
}) | |||||
} |
@@ -14,18 +14,33 @@ | |||||
:rules="rules" | :rules="rules" | ||||
:required="required" | :required="required" | ||||
:label-width="labelWidth || 'auto'" | :label-width="labelWidth || 'auto'" | ||||
:input-align="inputAlign || 'left'" | |||||
> | > | ||||
<!-- <template #button> | <!-- <template #button> | ||||
<van-icon name="notes-o" size="20"/> | <van-icon name="notes-o" size="20"/> | ||||
</template>--> | </template>--> | ||||
</van-field> | </van-field> | ||||
<van-popup v-model="popupVisible" position="bottom"> | |||||
<van-popup v-model="popupVisible" position="bottom" v-if="type === 'year'"> | |||||
<van-picker | |||||
ref="picker" | |||||
:title="label" | |||||
show-toolbar | |||||
:columns="yearColumns" | |||||
:readonly="readonly" | |||||
v-model="internalValue" | |||||
@confirm="onConfirm" | |||||
@cancel="onCancel" | |||||
@change="onChanged" | |||||
/> | |||||
</van-popup> | |||||
<van-popup v-model="popupVisible" position="bottom" v-else> | |||||
<van-datetime-picker | <van-datetime-picker | ||||
ref="picker" | ref="picker" | ||||
v-model="internalValue" | v-model="internalValue" | ||||
:type="type || 'date'" | :type="type || 'date'" | ||||
:readonly="readonly" | :readonly="readonly" | ||||
:title="label" | |||||
:title="label || ''" | |||||
@confirm="onConfirm" | @confirm="onConfirm" | ||||
@cancel="onCancel" | @cancel="onCancel" | ||||
@change="onChanged" | @change="onChanged" | ||||
@@ -37,14 +52,16 @@ | |||||
<script> | <script> | ||||
import { formatDate } from "element-ui/src/utils/date-util.js" | import { formatDate } from "element-ui/src/utils/date-util.js" | ||||
import {strtotime} from "@/utils"; | |||||
export default { | export default { | ||||
name: "fieldDatePicker", | name: "fieldDatePicker", | ||||
props: [ | props: [ | ||||
'name', 'readonly', 'value', 'label', 'placeholder', 'required', 'rules', 'labelWidth', | |||||
'type', // 类型, 仅支持 datetime date time year-month month-day datehour | |||||
'name', 'readonly', 'value', 'label', 'placeholder', 'required', 'rules', 'labelWidth', 'inputAlign', | |||||
'type', // 类型, 仅支持 datetime date time year-month month-day datehour, 额外支持year(但formatter必须为yyyy, 可以提供yearRangeLength=<Number>指定年范围) | |||||
'formatter', // value的格式化 String|Function|undefined 字符串为格式字符串, 函数则必须有返回 undefined则不转换 | 'formatter', // value的格式化 String|Function|undefined 字符串为格式字符串, 函数则必须有返回 undefined则不转换 | ||||
'clearable', // 点击取消时清空绑定值 | 'clearable', // 点击取消时清空绑定值 | ||||
'yearRangeLength', // type === 'year' 时生成的年份数量范围 [YEAR - yearRangeLength, YEAR + yearRangeLength] | |||||
], | ], | ||||
watch: { | watch: { | ||||
value: function (newVal, oldVal) { | value: function (newVal, oldVal) { | ||||
@@ -75,7 +92,7 @@ export default { | |||||
openPopup() { | openPopup() { | ||||
if(!this.readonly) | if(!this.readonly) | ||||
{ | { | ||||
console.log(this.internalValue); | |||||
//console.log(this.internalValue); | |||||
this.popupVisible = true; | this.popupVisible = true; | ||||
this.$nextTick(() => { | this.$nextTick(() => { | ||||
try | try | ||||
@@ -83,8 +100,9 @@ export default { | |||||
if(1) | if(1) | ||||
{ | { | ||||
let values = (this.visibleValue || this.getValue(new Date)).split(/\D+/); //TODO: 按非数字符号粗略分割解析初始值, 仅对于类似yyyy-MM-dd | let values = (this.visibleValue || this.getValue(new Date)).split(/\D+/); //TODO: 按非数字符号粗略分割解析初始值, 仅对于类似yyyy-MM-dd | ||||
console.log(values); | |||||
this.$refs.picker.getPicker().setValues(values); | |||||
//console.log(values); | |||||
let picker = this.$refs.picker.getPicker ? this.$refs.picker.getPicker() : this.$refs.picker; | |||||
picker.setValues(values); | |||||
} | } | ||||
else { | else { | ||||
//TODO: 打开时保存初始值, 取消或点击遮罩未确定的时候恢复该初始值到v-model | //TODO: 打开时保存初始值, 取消或点击遮罩未确定的时候恢复该初始值到v-model | ||||
@@ -132,7 +150,39 @@ export default { | |||||
this.internalValue = data; | this.internalValue = data; | ||||
this.visibleValue = this.getValue(data); | this.visibleValue = this.getValue(data); | ||||
}, | }, | ||||
genYearColumns(num) { | |||||
let d; | |||||
try | |||||
{ | |||||
if(this.value) | |||||
{ | |||||
d = strtotime(this.value, 'yyyy'); | |||||
} | |||||
else | |||||
d = new Date; | |||||
} | |||||
catch(e) | |||||
{ | |||||
d = new Date; | |||||
} | |||||
let y = d.getFullYear(); | |||||
let arr = ['' + y]; | |||||
for(let i = 1; i <= num; i++) | |||||
{ | |||||
arr.push('' + (y + i)); | |||||
arr.splice(0, 0, '' + (y - i)); | |||||
} | |||||
return arr; | |||||
}, | |||||
strtotime, | |||||
}, | }, | ||||
computed: { | |||||
yearColumns() { | |||||
if(this.type !== 'year') | |||||
return []; | |||||
return this.genYearColumns(this.yearRangeLength || 100); | |||||
}, | |||||
} | |||||
} | } | ||||
</script> | </script> | ||||
@@ -3444,6 +3444,24 @@ export const constantRoutes = [ | |||||
}, | }, | ||||
component: (resolve) => require(['@/views/sunVillage_info/list_register_detail'], resolve) | component: (resolve) => require(['@/views/sunVillage_info/list_register_detail'], resolve) | ||||
}, | }, | ||||
{ // 综合填报 | |||||
path: '/sunVillage_info/entityReportList', | |||||
name: 'entityReportList', | |||||
meta: { | |||||
title: '综合填报', | |||||
hidden: true, | |||||
}, | |||||
component: (resolve) => require(['@/views/sunVillage_info/entityReport/reportList'], resolve) | |||||
}, | |||||
{ // 综合填报 | |||||
path: '/sunVillage_info/entityReportView', | |||||
name: 'entityReportView', | |||||
meta: { | |||||
title: '综合填报', | |||||
hidden: true, | |||||
}, | |||||
component: (resolve) => require(['@/views/sunVillage_info/entityReport/reportView'], resolve) | |||||
}, | |||||
{ // 统计填报 | { // 统计填报 | ||||
path: '/sunVillage_info/statistical_report', | path: '/sunVillage_info/statistical_report', | ||||
name: 'sunVillageInfoStatisticalReport', | name: 'sunVillageInfoStatisticalReport', | ||||
@@ -0,0 +1,512 @@ | |||||
export const Expression = function(_str, _flag = 0, _placeholderValueMap = {}) | |||||
{ | |||||
this.pos = 0; // 当前解析表达式字符串的位置 | |||||
this.str = _str; // 表达式 | |||||
this.errno = Expression.NO_ERROR; // 当前错误码 | |||||
this.placeholderValueMap = _placeholderValueMap; // 占位符值字典 | |||||
this.flag = _flag | Expression.PARSE_FLAG_ERROR_HANDLE_SCHEME_THROW_EXCEPTION; // 行为标记 | |||||
this.placeholders = []; | |||||
} | |||||
Expression.NO_ERROR = 0; | |||||
Expression.ERROR = 1; | |||||
Expression.NULL_STRING = 2; | |||||
Expression.BY_ZERO = 3; | |||||
Expression.MISSING_DIGIT = 4; | |||||
Expression.MISSING_RIGHT_PARENT = 5; | |||||
Expression.MISSING_OPERATOR = 6; | |||||
Expression.INVALID_CHARACTER = 7; | |||||
Expression.MISSING_PLACEHOLDER = 8; | |||||
Expression.INVALID_DIGIT = 9; | |||||
Expression.INVALID_PLACEHOLDER = 10; | |||||
Expression.MISSING_RIGHT_PLACEHOLDER_END = 11; | |||||
Expression.INVALID_PLACEHOLDER_FUNCTION = 12; | |||||
Expression.MISSING_COMPARE_OPERATOR = 13; | |||||
Expression.INVALID_COMPARE_OPERATOR = 14; | |||||
Expression.INCOMPLETE = 15; | |||||
Expression.ErrorStr = [ | |||||
"", | |||||
"错误", | |||||
"空字符串", | |||||
"除0", | |||||
"缺失数字", | |||||
"缺失右括号", | |||||
"缺失运算符", | |||||
"无效字符", | |||||
"缺失占位符", | |||||
"无效数字", | |||||
"无效占位符", | |||||
"缺失占位符结尾标识", | |||||
"无效占位符内置函数", | |||||
"缺失比较运算符", | |||||
"无效比较运算符", | |||||
"表达式不完整", | |||||
]; | |||||
Expression.PARSE_FLAG_NONE = 0; | |||||
Expression.PARSE_FLAG_ERROR_HANDLE_SCHEME_RETURN_ZERO = 1; // 解析到错误则当前部分返回0 | |||||
Expression.PARSE_FLAG_ERROR_HANDLE_SCHEME_THROW_EXCEPTION = 1 << 1; // 解析到错误则抛出异常 | |||||
Expression.PARSE_FLAG_ALL_NUMBER_AS_PLACEHOLDER = 1 << 3; // 所有数字都作为占位符 | |||||
Expression.PARSE_FLAG_IGNORE_ERROR_MISSING_PLACEHOLDER = 1 << 4; // 忽略占位符缺失 | |||||
Expression.PARSE_FLAG_IGNORE_ERROR_BY_ZERO = 1 << 5; // 忽略除0 | |||||
// 是否读取到字符串结尾 | |||||
Expression.prototype.__EOF = function() | |||||
{ | |||||
return !this.str || this.pos >= this.str.length; | |||||
}; | |||||
// 字符串转为数字 | |||||
Expression.prototype.__StrTo = function(numStr) | |||||
{ | |||||
return Number(numStr) | |||||
}; | |||||
// 开始解析, 重置状态 | |||||
Expression.prototype.__Ready = function() | |||||
{ | |||||
this.pos = 0; | |||||
this.errno = Expression.NO_ERROR; | |||||
this.placeholders = []; | |||||
let err = this.__CheckStr(); | |||||
return (err === Expression.NO_ERROR); | |||||
}; | |||||
// 解析 值 括号 占位符 的优先级最高的表达式 | |||||
Expression.prototype.__EvalV = function() | |||||
{ | |||||
if(this.__EOF()) | |||||
{ | |||||
return this.__FatalError(Expression.INCOMPLETE); | |||||
} | |||||
this.__SkipBlank(); | |||||
let nStr = this.str.substring(this.pos); | |||||
let p = 0; | |||||
let nag = false; | |||||
let result = 0; | |||||
if(nStr.charAt(p) === '-') | |||||
{ | |||||
nag = true; | |||||
this.pos++; | |||||
p++; | |||||
} | |||||
p += this.__SkipBlank(); | |||||
if(nStr.charAt(p) === '(') // 括号表达式 | |||||
{ | |||||
p++; | |||||
this.pos++; | |||||
result = this.__EvalP(); | |||||
if(this.str.charAt(this.pos) !== ')') | |||||
{ | |||||
return this.__FatalError(Expression.MISSING_RIGHT_PARENT); | |||||
} | |||||
this.pos++; | |||||
} | |||||
else if(nStr.charAt(p) === '{') // 占位符 | |||||
{ | |||||
p++; | |||||
this.pos++; | |||||
p += this.__SkipBlank(); | |||||
let d = ''; | |||||
let size = 0; | |||||
let ch = nStr.charAt(p); | |||||
while("`~@#%^&*()-+=,/?:;\"'|\\[{]}".indexOf(ch) === -1) // 中文支持 | |||||
{ | |||||
size++; | |||||
d += ch; | |||||
p++; | |||||
this.pos++; | |||||
if(p >= nStr.length) | |||||
{ | |||||
return this.__FatalError(Expression.MISSING_RIGHT_PLACEHOLDER_END); | |||||
} | |||||
ch = nStr.charAt(p); | |||||
} | |||||
p += this.__SkipBlank(); | |||||
if(this.str.charAt(this.pos) !== '}') | |||||
{ | |||||
return this.__FatalError(Expression.MISSING_RIGHT_PLACEHOLDER_END); | |||||
} | |||||
this.pos++; | |||||
if(size > 0) | |||||
{ | |||||
result = this.__ParsePlaceholder(d); | |||||
} | |||||
else | |||||
{ | |||||
return this.__NormalError(Expression.MISSING_PLACEHOLDER); | |||||
} | |||||
} | |||||
else // 纯数字 | |||||
{ | |||||
let d = ''; | |||||
let size = 0; | |||||
let ch = nStr.charAt(p); | |||||
while((ch >= '0' && ch <= '9') || ch === '.') | |||||
{ | |||||
size++; | |||||
d += ch; | |||||
p++; | |||||
this.pos++; | |||||
if(p >= nStr.length) | |||||
break; | |||||
ch = nStr.charAt(p); | |||||
} | |||||
if(size > 0) | |||||
{ | |||||
let m = d.indexOf("."); | |||||
if(m !== -1) | |||||
{ | |||||
let n = d.lastIndexOf("."); | |||||
if(n !== -1 && m !== n) | |||||
{ | |||||
return this.__FatalError(Expression.INVALID_DIGIT); | |||||
} | |||||
if(m === 0 || m === d.length - 1) | |||||
d = d.substr(0, m) + d.substr(m + 1); | |||||
} | |||||
if(this.flag & Expression.PARSE_FLAG_ALL_NUMBER_AS_PLACEHOLDER) | |||||
result = this.__ParsePlaceholder(d); | |||||
else | |||||
result = this.__StrTo(d); | |||||
} | |||||
else | |||||
{ | |||||
return this.__FatalError(Expression.MISSING_DIGIT); | |||||
} | |||||
} | |||||
if(nag) | |||||
result = -result; | |||||
return result; | |||||
}; | |||||
// 解析* /的优先级相对较高的表达式 | |||||
Expression.prototype.__EvalM = function() | |||||
{ | |||||
if(this.__EOF()) | |||||
{ | |||||
return this.__FatalError(Expression.INCOMPLETE); | |||||
} | |||||
let first = this.__EvalV(); | |||||
let result = first; | |||||
this.__SkipBlank(); | |||||
let nStr = this.str.substring(this.pos); | |||||
while(nStr.length > 0) | |||||
{ | |||||
let ch = nStr.charAt(0); | |||||
if(ch !== '*' && ch !== '/') | |||||
return result; | |||||
else | |||||
{ | |||||
this.pos++; | |||||
let second = this.__EvalV(); | |||||
if(ch === '*') | |||||
result = result *second; | |||||
else | |||||
{ | |||||
if(second === 0) | |||||
{ | |||||
return this.__NormalError(Expression.BY_ZERO); | |||||
} | |||||
result = result / second; | |||||
} | |||||
} | |||||
nStr = this.str.substring(this.pos); | |||||
} | |||||
return result; | |||||
}; | |||||
// 解析+ -的优先级最低的表达式 | |||||
Expression.prototype.__EvalP = function() | |||||
{ | |||||
if(this.__EOF()) | |||||
{ | |||||
return this.__FatalError(Expression.INCOMPLETE); | |||||
} | |||||
this.__SkipBlank(); | |||||
let first = this.__EvalM(); | |||||
let result = first; | |||||
let nStr = this.str.substring(this.pos); | |||||
while(nStr.length > 0) | |||||
{ | |||||
let ch = nStr.charAt(0); | |||||
if(ch !== '+' && ch !== '-') | |||||
return result; | |||||
else | |||||
{ | |||||
this.pos++; | |||||
let second = this.__EvalM(); | |||||
if(ch === '+') | |||||
result = result + second; | |||||
else | |||||
result = result - second; | |||||
} | |||||
nStr = this.str.substring(this.pos); | |||||
} | |||||
return result; | |||||
}; | |||||
// 解析比较运算符 | |||||
Expression.prototype.__EvalCmp = function() | |||||
{ | |||||
if(this.__EOF()) | |||||
{ | |||||
return this.__FatalError(Expression.MISSING_COMPARE_OPERATOR); | |||||
} | |||||
this.__SkipBlank(); | |||||
let result = ''; | |||||
let nStr = this.str.substring(this.pos); | |||||
while(nStr.length > 0) | |||||
{ | |||||
let ch = nStr.charAt(0); | |||||
if(ch !== '=' && ch !== '!' && ch !== '>' && ch !== '<') | |||||
break; | |||||
else | |||||
{ | |||||
if(result.length === 0) | |||||
{ | |||||
result += ch; | |||||
this.pos++; | |||||
} | |||||
else // === 1 | |||||
{ | |||||
if(result !== "=") // 如果第一个字符不是=, 第二个字符必定是= | |||||
{ | |||||
if(ch !== '=') | |||||
return this.__FatalError(Expression.INVALID_COMPARE_OPERATOR); | |||||
} | |||||
else // 如果第一个字符是=, 第二个字符可以是= | |||||
{ | |||||
if(ch === '=') | |||||
result += ch; | |||||
else | |||||
{ | |||||
break; | |||||
} | |||||
} | |||||
result += ch; | |||||
this.pos++; | |||||
} | |||||
} | |||||
if(result.length >= 2) | |||||
break; | |||||
nStr = this.str.substring(this.pos); | |||||
} | |||||
if(result === "=") | |||||
result = "=="; | |||||
return result; | |||||
}; | |||||
// 开始计算 | |||||
Expression.prototype.Calc = function() | |||||
{ | |||||
if(!this.__Ready()) | |||||
return this.__OnError(0); | |||||
return this.__EvalP(); | |||||
}; | |||||
// 判断表达式断言 | |||||
Expression.prototype.Predicate = function() | |||||
{ | |||||
if(!this.__Ready()) | |||||
return this.__OnError(false); | |||||
let a = this.__EvalP(); | |||||
if(this.HasError()) | |||||
return this.__OnError(false); | |||||
let op = this.__EvalCmp(); | |||||
if(this.HasError()) | |||||
return this.__OnError(false); | |||||
let b = this.__EvalP(); | |||||
if(this.HasError()) | |||||
return this.__OnError(false); | |||||
//console.log(a + op + b); | |||||
return eval(a + op + b); | |||||
}; | |||||
Expression.prototype.FLAG = function(flags) | |||||
{ | |||||
for(let i of arguments) | |||||
{ | |||||
if((this.flag & i) === i) | |||||
return true; | |||||
} | |||||
return false; | |||||
} | |||||
// 普通错误, 仅设置可允许忽略的错误时调用, 错误被忽略时不设置错误码 | |||||
Expression.prototype.__NormalError = function(err) | |||||
{ | |||||
switch(err) | |||||
{ | |||||
case Expression.BY_ZERO: | |||||
if(this.FLAG(Expression.PARSE_FLAG_IGNORE_ERROR_BY_ZERO)) | |||||
return 0; | |||||
break; | |||||
case Expression.MISSING_PLACEHOLDER: | |||||
if(this.FLAG(Expression.PARSE_FLAG_IGNORE_ERROR_MISSING_PLACEHOLDER)) | |||||
return 0; | |||||
break; | |||||
case Expression.INVALID_DIGIT: | |||||
if(this.FLAG(Expression.PARSE_FLAG_IGNORE_ERROR_INVALID_DIGIT)) | |||||
return 0; | |||||
break; | |||||
} | |||||
return this.__FatalError(err); | |||||
}; | |||||
// 全局错误处理 | |||||
Expression.prototype.__OnError = function(ifError) | |||||
{ | |||||
if(this.FLAG(Expression.PARSE_FLAG_ERROR_HANDLE_SCHEME_THROW_EXCEPTION)) // 抛异常 | |||||
{ | |||||
throw new Error(this.Error()); | |||||
} | |||||
else // 返回0 | |||||
{ | |||||
return ifError; | |||||
} | |||||
}; | |||||
// 计算是否有错误 | |||||
Expression.prototype.HasError = function() | |||||
{ | |||||
return this.errno !== Expression.NO_ERROR; | |||||
}; | |||||
// 返回计算的错误, 并清除错误 | |||||
Expression.prototype.GetError = function() | |||||
{ | |||||
let e = this.errno; | |||||
this.errno = Expression.NO_ERROR; | |||||
return e; | |||||
} | |||||
// 获取当前错误的字符串 | |||||
Expression.prototype.Error = function() | |||||
{ | |||||
return Expression.ErrorStr[this.errno]; | |||||
} | |||||
// 致命错误 | |||||
Expression.prototype.__FatalError = function(err) | |||||
{ | |||||
this.errno = err; | |||||
throw new Error(this.Error()); | |||||
}; | |||||
Expression.prototype.ParsedPlaceholders = function() | |||||
{ | |||||
return this.placeholders; | |||||
} | |||||
// 解析占位符 | |||||
Expression.prototype.__ParsePlaceholder = function(name) | |||||
{ | |||||
this.placeholders.push(name); | |||||
if(!this.placeholderValueMap) | |||||
{ | |||||
return this.__NormalError(Expression.MISSING_PLACEHOLDER); | |||||
} | |||||
if(name.startsWith("$")) // 特殊环境变量 | |||||
return this.__ParseNumber(this.placeholderValueMap[name]); | |||||
let ptr = this.placeholderValueMap; | |||||
let d = null; | |||||
let notFetch = false; | |||||
let i = 0; | |||||
do | |||||
{ | |||||
let index = name.indexOf(".", i); | |||||
let s = index === -1 ? name.substring(i) : name.substring(i, index); | |||||
i += s.length + 1; | |||||
s = s.trim(); | |||||
if(s.startsWith("$")) // 函数管线 | |||||
{ | |||||
if(!notFetch) // 此时当前值应该是数字, 不再继续向下取Object/Map | |||||
{ | |||||
d = this.__ParseNumber(ptr); // 当前值转换为数字 | |||||
notFetch = true; // 此时当前值应该是数字, 不再继续向下取Object/Map | |||||
} | |||||
switch(s.substring(1).toLowerCase()) | |||||
{ | |||||
case "abs": | |||||
d = Math.abs(d); | |||||
break; | |||||
case "neg": | |||||
d = -d; | |||||
break; | |||||
case "lt0": | |||||
if(d >= 0) | |||||
return 0; | |||||
break; | |||||
case "gt0": | |||||
if(d <= 0) | |||||
return 0; | |||||
break; | |||||
default: | |||||
return this.__FatalError(Expression.INVALID_PLACEHOLDER_FUNCTION); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
if(notFetch/*null != d*/) // TODO: 被管线函数处理过, 占位符表达式书写不应该出现该情况, 管线函数应都在表达式尾部, 并且不在表达式起始 | |||||
return d; | |||||
ptr = ptr[s]; | |||||
if(null === ptr || undefined === ptr) | |||||
{ | |||||
return this.__NormalError(Expression.MISSING_PLACEHOLDER); | |||||
} | |||||
} | |||||
} while(i < name.length); | |||||
if(null == d) | |||||
return this.__ParseNumber(ptr); | |||||
else | |||||
return d; | |||||
}; | |||||
// 检查表达式字符串 | |||||
Expression.prototype.__CheckStr = function() | |||||
{ | |||||
if(!this.str) | |||||
{ | |||||
return Expression.NULL_STRING; | |||||
} | |||||
return Expression.NO_ERROR; | |||||
}; | |||||
// 跳过空白符 | |||||
Expression.prototype.__SkipBlank = function() | |||||
{ | |||||
let i = 0; | |||||
for(; (this.pos + i) < this.str.length; i++) | |||||
{ | |||||
if(!/\s/.test(this.str.charAt(this.pos + i))) | |||||
break; | |||||
} | |||||
this.pos += i; | |||||
return i; | |||||
}; | |||||
// 对象转数字 | |||||
Expression.prototype.__ParseNumber = function(val) | |||||
{ | |||||
if(null === val) | |||||
return this.__NormalError(Expression.INVALID_DIGIT); | |||||
if(val instanceof Number) | |||||
return val; | |||||
else | |||||
{ | |||||
try | |||||
{ | |||||
return this.__StrTo(val.toString()); | |||||
} | |||||
catch(e) | |||||
{ | |||||
console.error(e); | |||||
return this.__NormalError(Expression.INVALID_DIGIT); | |||||
} | |||||
} | |||||
}; | |||||
@@ -1206,3 +1206,14 @@ export function manual_page(list, page_no = 1, page_size = 10) | |||||
let start = (page_no - 1) * page_size; | let start = (page_no - 1) * page_size; | ||||
return list.slice(start, start + page_size); | return list.slice(start, start + page_size); | ||||
} | } | ||||
export function array_toMap(arr, byFunc, overriding) | |||||
{ | |||||
let res = {}; | |||||
arr.forEach((x) => { | |||||
let a = byFunc(x); | |||||
if(!res.hasOwnProperty(a) || overriding) | |||||
res[a] = x; | |||||
}); | |||||
return res; | |||||
} |
@@ -158,3 +158,7 @@ export function isBankCard (str_cardNo) { | |||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
export function is_not_number(val) { | |||||
return (val === null || val === undefined || val === ''); | |||||
} |
@@ -0,0 +1,278 @@ | |||||
<template> | |||||
<div class="app-container"> | |||||
<div class="header_main-placeholder"> | |||||
<div class="header_main"> | |||||
综合填报 | |||||
<div class="return_btn" @click="$router.back()"></div> | |||||
<div class="add_btn" @click="add"></div> | |||||
</div> | |||||
</div> | |||||
<van-pull-refresh v-model="refreshing" @refresh="getList()"> | |||||
<van-list | |||||
class="list_main" | |||||
v-model="loading" | |||||
:finished="finished" | |||||
finished-text="没有更多了" | |||||
@load="getList('+1')" | |||||
> | |||||
<van-swipe-cell class="item" v-for="(item,index) in list" :key="index"> | |||||
<div class="item_box" @click="view(item)"> | |||||
<div class="head_block"> | |||||
<i class="icon"></i> | |||||
<div class="title">{{item.reportName}}</div> | |||||
</div> | |||||
<div class="order_block"> | |||||
<div class="flex_block"> | |||||
<i class="icon icon_1"></i> | |||||
<div class="text">{{item.operatorDate}}</div> | |||||
</div> | |||||
<div class="flex_block" v-if="item.operatorName"> | |||||
<i class="icon icon_2"></i> | |||||
<div class="text">{{item.operatorName}}</div> | |||||
</div> | |||||
<div class="flex_block" v-if="item.operatorDepartment"> | |||||
<i class="icon icon_2"></i> | |||||
<div class="text">{{item.operatorDepartment}}</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<template #right> | |||||
<van-row class="full-height toolbar"> | |||||
<van-col class="full-height"> | |||||
<van-button square text="修改" type="info" :to="{name:'entityReportView', query: {reportId:item.id, intent: 'edit'}}" class="full-height" /> | |||||
</van-col> | |||||
<van-col class="full-height"> | |||||
<van-button square text="删除" type="danger" @click="remove(item,index)" class="full-height" /> | |||||
</van-col> | |||||
</van-row> | |||||
</template> | |||||
</van-swipe-cell> | |||||
</van-list> | |||||
</van-pull-refresh> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import {delReport, listReport} from "@/api/sunVillage_info/entity/report.js"; | |||||
export default { | |||||
name: "ReportList", | |||||
data() { | |||||
return { | |||||
list:[], | |||||
loading: false, | |||||
finished: false, | |||||
refreshing: false, | |||||
total: 0, | |||||
queryParams:{ | |||||
pageNum:1, | |||||
pageSize:10, | |||||
orderByColumn:'createTime', | |||||
isAsc:'desc' | |||||
} | |||||
}; | |||||
}, | |||||
created() { | |||||
this.getList(); | |||||
}, | |||||
methods: { | |||||
add() { | |||||
this.$router.push({ | |||||
name: 'entityReportView', | |||||
query: { | |||||
intent: 'add', | |||||
} | |||||
}); | |||||
}, | |||||
view(row){ | |||||
this.$router.push({ | |||||
name: 'entityReportView', | |||||
query: { | |||||
intent: 'view', | |||||
reportId: row.id, | |||||
} | |||||
}); | |||||
}, | |||||
getList(target){ | |||||
let type = typeof (target); | |||||
//console.log(type, target); | |||||
if(target && this.finished) | |||||
return; | |||||
if (target === 0) { | |||||
this.refreshing = true; | |||||
this.finished = true; | |||||
this.total = 0; | |||||
this.queryParams.pageNum = 1; | |||||
this.list = []; | |||||
} | |||||
else if (type === 'number') | |||||
this.queryParams.pageNum = target; | |||||
else if (type === 'string') { | |||||
this.queryParams.pageNum = eval(this.queryParams.pageNum + target) | |||||
} | |||||
else | |||||
{ | |||||
this.refreshing = true; | |||||
this.finished = true; | |||||
this.total = 0; | |||||
this.queryParams.pageNum = 1; | |||||
this.list = [] | |||||
} | |||||
listReport(this.queryParams).then(response => { | |||||
if (response.rows.length === 0) { | |||||
this.finished = true; | |||||
return; | |||||
} | |||||
this.list = response.rows; | |||||
this.total += response.rows.length; | |||||
this.finished = this.total >= response.total; | |||||
}).finally(() => { | |||||
this.loading = false; | |||||
this.refreshing = false; | |||||
}); | |||||
}, | |||||
remove(row, index){ | |||||
this.$dialog.confirm({ | |||||
message: '您确认删除综合填报?', | |||||
}) | |||||
.then(() => { | |||||
delReport(row.id).then(res => { | |||||
this.$toast.success('删除成功'); | |||||
this.list.splice(index,1); | |||||
}); | |||||
}) | |||||
.catch(() => { | |||||
}); | |||||
}, | |||||
refresh() { | |||||
this.getList(); return; | |||||
this.list = []; | |||||
this.queryParams.pageNum = 1; | |||||
this.refreshing = true; | |||||
this.finished = false; | |||||
}, | |||||
}, | |||||
} | |||||
</script> | |||||
<style scoped lang="scss"> | |||||
.app-container { | |||||
//padding: 0.2rem 3%; | |||||
width: 100vw; | |||||
height: 100vh; | |||||
} | |||||
.full-height { | |||||
height: 100%; | |||||
} | |||||
.header_main-placeholder { | |||||
height: 116px; | |||||
} | |||||
.header_main { | |||||
height: 116px; | |||||
background: url('../../../assets/images/sunVillage_info/list_head.png') no-repeat; | |||||
background-size: 100% 100%; | |||||
position: fixed; | |||||
top: 0; | |||||
left: 0; | |||||
width: 100%; | |||||
font-size: 36px; | |||||
line-height: 116px; | |||||
text-align: center; | |||||
color: #fff; | |||||
z-index: 999; | |||||
.return_btn { | |||||
width: 24px; | |||||
height: 43.2px; | |||||
background: url('../../../assets/images/sunVillage_info/list_icon_5.png') center center no-repeat; | |||||
background-size: 20px 36px; | |||||
position: absolute; | |||||
left: 38px; | |||||
top: 36px; | |||||
} | |||||
.add_btn { | |||||
width: 56.4px; | |||||
height: 40.8px; | |||||
background: url('../../../assets/images/sunVillage_info/list_icon_9.png') center center no-repeat; | |||||
background-size: 47px 34px; | |||||
position: absolute; | |||||
right: 38px; | |||||
top: 36px; | |||||
} | |||||
} | |||||
.list_main{ | |||||
padding:26px 22px 0; | |||||
.item{ | |||||
height: 162px; | |||||
border-radius: 30px; | |||||
background: #fff; | |||||
box-shadow: 4px 6px 5px rgba(63, 68, 75, 0.1); | |||||
margin-bottom: 20px; | |||||
.item_box{ | |||||
padding:25px 32px; | |||||
} | |||||
.head_block{ | |||||
height: 62px; | |||||
display: flex; | |||||
align-items: center; | |||||
width: 100%; | |||||
.icon{ | |||||
width: 34px; | |||||
height: 30px; | |||||
background: url('../../../assets/images/sunVillage_info/fixedAssets_icon_4.png') no-repeat; | |||||
background-size: 100% 100%; | |||||
display: block; | |||||
margin-right: 12px; | |||||
} | |||||
.title{ | |||||
flex:1; | |||||
font-size: 32px; | |||||
color: #252525; | |||||
overflow: hidden; | |||||
text-overflow: ellipsis; | |||||
white-space: nowrap; | |||||
padding-right: 20px; | |||||
} | |||||
} | |||||
.order_block{ | |||||
display: flex; | |||||
height: 52px; | |||||
padding-top: 12px; | |||||
font-size: 24px; | |||||
color: #858585; | |||||
align-items: center; | |||||
padding-bottom: 10px; | |||||
.flex_block{ | |||||
display: flex; | |||||
align-items: center; | |||||
justify-content: center; | |||||
margin-right: 28px; | |||||
height: 42px; | |||||
.icon{ | |||||
width: 25px; | |||||
height: 25px; | |||||
margin-top: 3px; | |||||
margin-right: 8px; | |||||
&.icon_1{ | |||||
background: url('../../../assets/images/sunVillage_info/fixedAssets_icon_3.png') no-repeat; | |||||
background-size: 100% 100%; | |||||
} | |||||
&.icon_2{ | |||||
background: url('../../../assets/images/sunVillage_info/fixedAssets_icon_5.png') no-repeat; | |||||
background-size: 100% 100%; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
.toolbar { | |||||
margin-left: 2px; | |||||
} | |||||
</style> |
@@ -0,0 +1,595 @@ | |||||
<template> | |||||
<div class="app-container"> | |||||
<div class="header_main-placeholder"> | |||||
<div class="header_main"> | |||||
综合填报 | |||||
<div class="return_btn" @click="back"></div> | |||||
<div class="add_btn" @click="save" v-if="(isAdd || isEdit) && editorData.templateId"></div> | |||||
</div> | |||||
</div> | |||||
<van-form ref="form" :class="{'form_readonly': disableEdit}"> | |||||
<van-row> | |||||
<van-col :span="editorData.templateId ? 16 : 24"> | |||||
<field-select | |||||
class="template-selector" | |||||
v-model="editorData.templateId" | |||||
label=" 模板" | |||||
value-key="reportName" | |||||
data-key="id" | |||||
placeholder="报表模板" | |||||
:rules="[{ required: true }]" | |||||
:required="true" | |||||
:readonly="disableEdit" | |||||
:columns="templateList" | |||||
@input="getTemplate" | |||||
/> | |||||
</van-col> | |||||
<van-col span="8" v-if="!!editorData.templateId"> | |||||
<field-date-picker | |||||
class="field_no-label" | |||||
v-model="editorData.reportYear" | |||||
placeholder="报表年度" | |||||
formatter="yyyy" | |||||
:readonly="disableEdit" | |||||
input-align="center" | |||||
type="year" | |||||
/> | |||||
</van-col> | |||||
</van-row> | |||||
<van-row v-if="!!editorData.templateId"> | |||||
<van-col span="8"> | |||||
<van-field class="field_no-label" :readonly="disableEdit" v-model="editorData.titleLeft" label="" placeholder="左上" input-align="left"/> | |||||
</van-col> | |||||
<van-col span="8"> | |||||
<van-field class="field_no-label" :readonly="disableEdit" v-model="editorData.titleCenter" label="" placeholder="中上" input-align="center"/> | |||||
</van-col> | |||||
<van-col span="8"> | |||||
<van-field class="field_no-label" :readonly="disableEdit" v-model="editorData.titleRight" label="" placeholder="右上" input-align="right"/> | |||||
</van-col> | |||||
</van-row> | |||||
<div class="main-table" v-if="!!editorData.templateId"> | |||||
<table> | |||||
<thead> | |||||
<tr> | |||||
<td v-for="(header) in removePlaceholder(editorData.headers)" :colspan="header.colspan" :style="{ | |||||
'background-color': calcColor(header.type), | |||||
'color': calcTextColor(header.type), | |||||
}"> | |||||
{{header.headerName}} | |||||
</td> | |||||
</tr> | |||||
</thead> | |||||
<tbody> | |||||
<tr v-for="(row, rindex) in editorData.rows"> | |||||
<td v-for="(col) in removePlaceholder(row)" :colspan="col.colspan" :rowspan="col.rowspan" :style="{ | |||||
'text-align': calcAlign(editorData.headers[col.colIndex].type), | |||||
'background-color': calcColor(editorData.headers[col.colIndex].type), | |||||
}"> | |||||
<div class="full-height" v-if="editorData.headers[col.colIndex].type === '2'" :class="{'validate-error': col.error, 'validate-error-box': col.error,}"> | |||||
<input class="input-field align-right full-height" v-model="col.val" :readonly="disableEdit" type="number"></input> | |||||
</div> | |||||
<div class="full-height" v-else-if="editorData.headers[col.colIndex].type === '4'"> | |||||
<input class="input-field align-center full-height" v-model="col.name" :readonly="disableEdit"></input> | |||||
</div> | |||||
<div v-else :style="{'text-align': calcAlign(editorData.headers[col.colIndex].type)}">{{col.name}}</div> | |||||
</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</div> | |||||
<template v-if="!!editorData.templateId"> | |||||
<div> | |||||
<van-field :readonly="disableEdit" v-model="editorData.reportRemark" label="备注" placeholder="报表备注"/> | |||||
</div> | |||||
<div> | |||||
<van-field readonly :value="editorData.rule" label="规则" placeholder="报表效验公式"> | |||||
<template #extra> | |||||
<van-button :disabled="!editorData.rule" style="height: 100%;" type="primary" size="small" @click="validate(true)">效 验</van-button> | |||||
</template> | |||||
</van-field> | |||||
</div> | |||||
<van-row> | |||||
<van-col span="8"> | |||||
<van-field class="field_no-label" :readonly="disableEdit" v-model="editorData.operatorDepartment" label="" placeholder="填报单位" input-align="left"/> | |||||
</van-col> | |||||
<van-col span="8"> | |||||
<van-field class="field_no-label" :readonly="disableEdit" v-model="editorData.operatorName" label="" placeholder="填报人" input-align="center"/> | |||||
</van-col> | |||||
<van-col span="8"> | |||||
<field-date-picker | |||||
class="field_no-label" | |||||
v-model="editorData.operatorDate" | |||||
placeholder="填报日期" | |||||
formatter="yyyy-MM-dd" | |||||
:readonly="disableEdit" | |||||
input-align="right" | |||||
/> | |||||
</van-col> | |||||
</van-row> | |||||
</template> | |||||
</van-form> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import FieldSelect from "@/components/form/FieldSelect"; | |||||
import { | |||||
addReport, delReport, | |||||
getReport, | |||||
getReportTemplate, | |||||
listReporttitle, | |||||
updateReport | |||||
} from "@/api/sunVillage_info/entity/report"; | |||||
import {array_grouping, array_toMap, date_format} from "@/utils"; | |||||
import {Expression} from "@/utils/expression"; | |||||
import {is_not_number} from "@/utils/utils"; | |||||
import FieldDatePicker from "@/components/form/FieldDatePicker"; | |||||
import {Notify} from "vant"; | |||||
export default { | |||||
name: "ReportView", | |||||
components: {FieldDatePicker, FieldSelect}, | |||||
data() { | |||||
return { | |||||
editorData: { | |||||
id: null, | |||||
templateId: null, | |||||
reportRemark: null, | |||||
titleLeft: null, | |||||
titleCenter: null, | |||||
titleRight: null, | |||||
reportStatus: "0", | |||||
createBy: null, | |||||
createTime: null, | |||||
updateBy: null, | |||||
updateTime: null, | |||||
reportName: '', | |||||
operatorName: '', | |||||
operatorDate: '', | |||||
operatorDepartment: '', | |||||
rule: null, | |||||
reportYear: date_format('%Y'), | |||||
headers: [], | |||||
rows: [], | |||||
cells: [], | |||||
rules: [], | |||||
}, | |||||
templateList: [], | |||||
loading: false, | |||||
disableEdit: false, | |||||
intent: 'add', | |||||
reportId: null, | |||||
}; | |||||
}, | |||||
created() { | |||||
this.getTemplateList(); | |||||
this.parseQuery(); | |||||
}, | |||||
mounted(){ | |||||
this.init(); | |||||
}, | |||||
methods: { | |||||
getTemplateList() { | |||||
listReporttitle({reportStatus: '0'}).then((resp) => { | |||||
this.templateList = resp.rows; | |||||
}); | |||||
}, | |||||
getTemplate() { | |||||
if(!this.editorData.templateId && !this.editorData.id) | |||||
return; | |||||
this.loading = true; | |||||
if(this.editorData.id) // 修改 | |||||
{ | |||||
getReport(this.editorData.id).then((resp) => { | |||||
let reportData = resp.data; | |||||
getReportTemplate(reportData.templateId).then((resp) => { | |||||
let templateData = resp.data; | |||||
this.setTableData(templateData, reportData); | |||||
}).finally(() => { | |||||
this.loading = false; | |||||
}); | |||||
}).catch(() => { | |||||
this.loading = false; | |||||
}); | |||||
} | |||||
else | |||||
{ | |||||
getReportTemplate(this.editorData.templateId).then((resp) => { | |||||
let templateData = resp.data; | |||||
this.setTableData(templateData); | |||||
}).finally(() => { | |||||
this.loading = false; | |||||
}); | |||||
} | |||||
}, | |||||
setTableData(templateData, reportData) { | |||||
let data; | |||||
if(!reportData) | |||||
{ | |||||
data = templateData; | |||||
data.rows.forEach((x) => { | |||||
x.forEach((y) => { | |||||
y.error = false; | |||||
}); | |||||
}); | |||||
} | |||||
else | |||||
{ | |||||
let cells = reportData.cells; | |||||
data = reportData; | |||||
data.headers = templateData.headers; | |||||
data.rows = templateData.rows; | |||||
data.cells = templateData.cells; | |||||
data.rules = templateData.rules; | |||||
data.rule = templateData.rule; | |||||
let group = array_grouping(cells, (x) => x.rowIndex); | |||||
Object.keys(group).forEach((x) => group[x] = array_toMap(group[x], (x) => x.colIndex)); | |||||
data.rows.forEach((cols, rowIndex) => { | |||||
cols.forEach((x) => { | |||||
if(group[rowIndex] && group[rowIndex][x.colIndex]) | |||||
{ | |||||
if(templateData.headers[x.colIndex].type === '4') | |||||
x.name = group[rowIndex][x.colIndex].name; | |||||
x.val = group[rowIndex][x.colIndex].val; | |||||
} | |||||
}) | |||||
}); | |||||
} | |||||
this.editorData = data; | |||||
if(this.editorData.id) | |||||
this.validate(); | |||||
}, | |||||
cellIsPlaceholder(x) { | |||||
return x.colspan <= 0 || (x.hasOwnProperty('rowspan') && x.rowspan <= 0); | |||||
}, | |||||
removePlaceholder(cells) { | |||||
return cells.filter((x) => !this.cellIsPlaceholder(x)); | |||||
}, | |||||
calcAlign(type) { | |||||
switch(type) | |||||
{ | |||||
case '2': | |||||
return 'right'; | |||||
case '3': | |||||
case '4': | |||||
return 'center'; | |||||
case '1': | |||||
return 'left'; | |||||
} | |||||
}, | |||||
calcColor(type) { | |||||
switch(type) | |||||
{ | |||||
case '2': | |||||
return 'unset'; | |||||
case '4': | |||||
return 'unset'; | |||||
case '3': | |||||
return '#d7e8f3'; | |||||
case '1': | |||||
return '#aad8f6'; | |||||
} | |||||
}, | |||||
calcTextColor(type) { | |||||
switch(type) | |||||
{ | |||||
case '2': | |||||
case '4': | |||||
return '#2facfe'; | |||||
case '3': | |||||
case '1': | |||||
return '#858585'; | |||||
} | |||||
}, | |||||
save() { | |||||
let validateResult = this.validate(); | |||||
if(validateResult) | |||||
this.requestSave(); | |||||
else | |||||
{ | |||||
this.$dialog.confirm({ | |||||
message: '报表存在不通过的效验, 是否继续提交?', | |||||
}) | |||||
.then(() => { | |||||
return this.requestSave(); | |||||
}) | |||||
.catch(() => { | |||||
}); | |||||
} | |||||
}, | |||||
requestSave() { | |||||
this.$refs.form.validate().then(() => { | |||||
this.preHandle(); | |||||
this.loading = true; | |||||
let func = this.editorData.id ? updateReport : addReport; | |||||
func(this.editorData).then((resp) => { | |||||
this.notify("保存成功!", 'success'); | |||||
this.back(); | |||||
}).finally(() => { | |||||
this.loading = false; | |||||
}); | |||||
}).catch(() => { | |||||
this.notify("请填写完整表单", 'danger'); | |||||
this.$refs.form.scrollToField(); | |||||
}); | |||||
}, | |||||
preHandle() { | |||||
this.editorData.cells = []; | |||||
this.editorData.rows.forEach((x) => this.editorData.cells.push(...x)); | |||||
}, | |||||
reset() { | |||||
this.$refs.form.resetValidation(); | |||||
this.editorData = { | |||||
id: null, | |||||
deptId: null, | |||||
deptName: null, | |||||
templateId: null, | |||||
reportName: null, | |||||
reportYear: null, | |||||
reportRemark: null, | |||||
titleLeft: null, | |||||
titleCenter: null, | |||||
titleRight: null, | |||||
rule: null, | |||||
operatorName: null, | |||||
operatorDate: null, | |||||
createBy: null, | |||||
createTime: null, | |||||
updateBy: null, | |||||
updateTime: null, | |||||
headers: [], | |||||
rows: [], | |||||
cells: [], | |||||
rules: [], | |||||
}; | |||||
}, | |||||
validate(showMsg) { | |||||
if(!this.editorData.rules || !this.editorData.rules.length) | |||||
return true; | |||||
let errors = []; | |||||
for(let i in this.editorData.headers) | |||||
{ | |||||
let header = this.editorData.headers[i]; | |||||
if(header.type !== '2') | |||||
continue; | |||||
let map = {}; | |||||
for(let m in this.editorData.rows) | |||||
{ | |||||
let cell = this.editorData.rows[m][i]; | |||||
map['' + (Number(m) + 1)] = is_not_number(cell.val) ? 0 : Number(cell.val); | |||||
this.$set(this.editorData.rows[Number(m)][Number(i)], 'error', false); | |||||
} | |||||
for(let m in this.editorData.rules) | |||||
{ | |||||
let rule = this.editorData.rules[m]; | |||||
let exp = new Expression(rule, Expression.PARSE_FLAG_ALL_NUMBER_AS_PLACEHOLDER | Expression.PARSE_FLAG_ERROR_HANDLE_SCHEME_THROW_EXCEPTION, map); | |||||
try | |||||
{ | |||||
let res = exp.Predicate(); | |||||
//console.log(rule, res); | |||||
if(!res) | |||||
{ | |||||
errors.push(`第${Number(i) + 1}列效验错误: ${rule}`); | |||||
} | |||||
let placeholders = exp.ParsedPlaceholders(); | |||||
for(let n in placeholders) | |||||
{ | |||||
if(!res) | |||||
this.$set(this.editorData.rows[Number(placeholders[n]) - 1][Number(i)], 'error', true); | |||||
} | |||||
} | |||||
catch(e) | |||||
{ | |||||
console.log(e); | |||||
errors.push(e); | |||||
} | |||||
} | |||||
} | |||||
if(showMsg) | |||||
{ | |||||
this.$dialog.alert({ | |||||
title: errors.length ? '效验错误' : '效验成功', | |||||
message: errors.join('<br/>'), | |||||
allowHtml: true, | |||||
}); | |||||
} | |||||
return errors.length === 0; | |||||
}, | |||||
parseQuery() { | |||||
let query = this.$route.query; | |||||
this.reportId = query.reportId; | |||||
this.intent = query.intent; | |||||
if(!this.reportId) | |||||
{ | |||||
this.intent = 'add'; | |||||
return; | |||||
} | |||||
if(this.intent === 'add') | |||||
{ | |||||
this.reportId = null; | |||||
} | |||||
}, | |||||
init() { | |||||
this.editorData.id = this.reportId; | |||||
this.getTemplate(); | |||||
this.disableEdit = this.intent === 'view'; | |||||
}, | |||||
back() { | |||||
this.$router.back(); | |||||
}, | |||||
notify(message, type) { | |||||
Notify.clear(); | |||||
Notify({ type: type || 'primary', message: message }); | |||||
}, | |||||
}, | |||||
computed: { | |||||
isAdd() { | |||||
return this.intent === 'add'; | |||||
}, | |||||
isEdit() { | |||||
return this.intent === 'edit'; | |||||
}, | |||||
isView() { | |||||
return this.intent === 'view'; | |||||
}, | |||||
} | |||||
} | |||||
</script> | |||||
<style scoped lang="scss"> | |||||
.app-container{ | |||||
background: #e9e9e9; | |||||
min-height: 100vh; | |||||
width: 100vw; | |||||
.header_main-placeholder { | |||||
height: 116px; | |||||
} | |||||
.header_main { | |||||
height: 116px; | |||||
background: url('../../../assets/images/sunVillage_info/list_head.png') no-repeat; | |||||
background-size: 100% 100%; | |||||
position: fixed; | |||||
top: 0; | |||||
left: 0; | |||||
width: 100%; | |||||
font-size: 36px; | |||||
line-height: 116px; | |||||
text-align: center; | |||||
color: #fff; | |||||
z-index: 999; | |||||
.return_btn { | |||||
width: 24px; | |||||
height: 43.2px; | |||||
background: url('../../../assets/images/sunVillage_info/list_icon_5.png') center center no-repeat; | |||||
background-size: 20px 36px; | |||||
position: absolute; | |||||
left: 38px; | |||||
top: 36px; | |||||
} | |||||
.add_btn { | |||||
width: 56.4px; | |||||
height: 40.8px; | |||||
background: url('../../../assets/images/sunVillage_info/list_icon_9.png') center center no-repeat; | |||||
background-size: 47px 34px; | |||||
position: absolute; | |||||
right: 38px; | |||||
top: 36px; | |||||
} | |||||
} | |||||
.main-table { | |||||
overflow-x: auto; | |||||
overflow-y: auto; | |||||
position: relative; | |||||
background-color: #ffffff; | |||||
padding: 0.15rem 0.15rem; | |||||
border-radius: 0.15rem; | |||||
margin: 0.1rem 0.1rem; | |||||
table { | |||||
width: max-content; | |||||
border-collapse: collapse; | |||||
border: 0.01rem solid #1989fa; | |||||
table-layout: fixed; | |||||
} | |||||
thead td { | |||||
text-align: center; | |||||
border: 0.01rem solid #1989fa; | |||||
height: 1rem; | |||||
font-size: 0.32rem; | |||||
padding: 0 0.4rem; | |||||
margin: 0; | |||||
font-weight: bold; | |||||
max-width: 1.2rem; | |||||
} | |||||
tbody td { | |||||
font-size: 0.3rem; | |||||
border: 0.01rem solid #1989fa; | |||||
height: 1rem; | |||||
white-space: break-spaces; | |||||
word-wrap: break-word; | |||||
overflow-wrap: break-word; | |||||
padding: 0; | |||||
margin: 0; | |||||
max-width: 1.5rem; | |||||
position: relative; | |||||
} | |||||
.input-field { | |||||
width: 100%; | |||||
background-color: unset; | |||||
border: 0; | |||||
} | |||||
.validate-error { | |||||
color: #F56C6C; | |||||
} | |||||
.validate-error-box { | |||||
color: #F56C6C; | |||||
border: 0.02rem solid #F56C6C; | |||||
} | |||||
} | |||||
.align-right { | |||||
text-align: right; | |||||
} | |||||
.align-center { | |||||
text-align: center; | |||||
} | |||||
.full-height { | |||||
height: 100%; | |||||
} | |||||
/deep/ .van-field__label { | |||||
background-color: #2facfe; | |||||
margin: 0; | |||||
color: #fff; | |||||
border-top-left-radius: 0.15rem; | |||||
border-bottom-left-radius: 0.15rem; | |||||
padding: 0 0.2rem; | |||||
display: flex; | |||||
align-items: center; | |||||
} | |||||
/deep/ .van-field__body { | |||||
background-color: #ffffff; | |||||
border-top-right-radius: 0.15rem; | |||||
border-bottom-right-radius: 0.15rem; | |||||
padding: 0 0.1rem; | |||||
} | |||||
/deep/ .van-field__body { | |||||
height: 100%; | |||||
} | |||||
/deep/ .van-field { | |||||
background-color: unset; | |||||
padding: 0.1rem 0.15rem; | |||||
height: 1rem; | |||||
} | |||||
.field_no-label /deep/ .van-field__body { | |||||
border-top-left-radius: 0.15rem; | |||||
border-bottom-left-radius: 0.15rem; | |||||
} | |||||
.template-selector /deep/ span { | |||||
padding-left: 0.8rem; | |||||
background: #2facfe url('../../../assets/images/sunVillage_info/list_icon_11.png') left center no-repeat; | |||||
background-size: 0.45rem; | |||||
} | |||||
.form_readonly /deep/ .van-icon-arrow-down { | |||||
display: none; | |||||
} | |||||
} | |||||
</style> |