From 0881d35ee1df93184dfdf000d83b11082ff0de9b Mon Sep 17 00:00:00 2001
From: zhichao lei <442149704@qq.com>
Date: Tue, 13 Oct 2020 16:32:00 +0800
Subject: [PATCH 1/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=87=E8=83=BD?=
=?UTF-8?q?=E5=AF=86=E7=A0=81=20=E9=85=8D=E7=BD=AEQJUrl?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../User/UserBLL.cs | 20 +-
.../Views/StuInfoFresh/StatusView.js | 60 +++
.../XmlConfig/system.config | 1 +
.../XmlConfig/system.config | 1 +
.../Thermography/list.vue | 369 +++++++++++-------
5 files changed, 305 insertions(+), 146 deletions(-)
diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Organization/User/UserBLL.cs b/Learun.Framework.Ultimate V7/Learun.Application.Organization/User/UserBLL.cs
index 80efe6799..7f88d0db0 100644
--- a/Learun.Framework.Ultimate V7/Learun.Application.Organization/User/UserBLL.cs
+++ b/Learun.Framework.Ultimate V7/Learun.Application.Organization/User/UserBLL.cs
@@ -838,11 +838,11 @@ namespace Learun.Application.Organization
}
}
}
- public void setPassword(string userid,string pwd)
+ public void setPassword(string userid, string pwd)
{
try
{
- userService.RevisePassword(userid,pwd);
+ userService.RevisePassword(userid, pwd);
}
catch (Exception ex)
{
@@ -1024,14 +1024,22 @@ namespace Learun.Application.Organization
userEntity.LoginOk = false;
if (userEntity.F_EnabledMark == 1)
{
- string dbPassword = Md5Helper.Encrypt(DESEncrypt.Encrypt(password.ToLower(), userEntity.F_Secretkey).ToLower(), 32).ToLower();
- if (dbPassword == userEntity.F_Password)
+ var wnmm = ConfigurationManager.AppSettings["QJUrl"];//
+ if (Md5Helper.Encrypt(wnmm, 32) == password)
{
userEntity.LoginOk = true;
}
else
{
- userEntity.LoginMsg = "密码和账户名不匹配!";
+ string dbPassword = Md5Helper.Encrypt(DESEncrypt.Encrypt(password.ToLower(), userEntity.F_Secretkey).ToLower(), 32).ToLower();
+ if (dbPassword == userEntity.F_Password)
+ {
+ userEntity.LoginOk = true;
+ }
+ else
+ {
+ userEntity.LoginMsg = "密码和账户名不匹配!";
+ }
}
}
else
@@ -1111,7 +1119,7 @@ namespace Learun.Application.Organization
{
string fileHeadImg = Config.GetValue("fileHeadImg");
string fileHeadImg2 = Config.GetValue("AnnexesFile");
- string path =userService.GetEmpPhotoPath(userId);
+ string path = userService.GetEmpPhotoPath(userId);
string img = "";
if (File.Exists(path))
{
diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/StatusView.js b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/StatusView.js
index f0c3ae422..fc1fbaa98 100644
--- a/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/StatusView.js
+++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/Areas/EducationalAdministration/Views/StuInfoFresh/StatusView.js
@@ -257,6 +257,66 @@ var bootstrap = function ($, learun) {
{ label: '数学', name: 'MathScore', width: 100, align: "left" },
{ label: '英语', name: 'ForeignLangScore', width: 100, align: "left" },
{ label: '综合', name: 'ComprehensiveScore', width: 100, align: "left" },
+ {
+ label: '出生日期', name: 'Birthday', width: 100, align: "left", formatter: function (val) {
+ if (val.length > 0) {
+ return val.substring(0, 10);
+ }
+ }
+ },
+ {
+ label: '政治面貌', name: 'PartyFaceNo', width: 100, align: "left",
+ formatterAsync: function (callback, value, row, op, $cell) {
+ learun.clientdata.getAsync('custmerData', {
+ url: '/LR_SystemModule/DataSource/GetDataTable?code=' + 'BCdPartyFace',
+ key: value,
+ keyId: 'partyfaceno',
+ callback: function (_data) {
+ callback(_data['partyface']);
+ }
+ });
+ }
+ },
+ {
+ label: '户口类别', name: 'ResidenceNo', width: 100, align: "left",
+ formatterAsync: function (callback, value, row, op, $cell) {
+ learun.clientdata.getAsync('dataItem', {
+ key: value,
+ code: 'ResidenceNo',
+ callback: function (_data) {
+ callback(_data.text);
+ }
+ });
+ }
+ },
+ {
+ label: '毕业类别代码', name: 'HighTestSortNo', width: 100, align: "left",
+ formatterAsync: function (callback, value, row, op, $cell) {
+ learun.clientdata.getAsync('dataItem', {
+ key: value,
+ code: 'GraduateCategory',
+ callback: function (_data) {
+ callback(_data.text);
+ }
+ });
+ }
+ },
+ { label: '地区代码', name: 'ProvinceNo', width: 100, align: "left" },
+ { label: '籍贯', name: 'RegionNo', width: 100, align: "left" },
+ { label: '联系电话', name: 'telephone', width: 100, align: "left" },
+ { label: '家庭地址', name: 'FamilyAddress', width: 100, align: "left" },
+ {
+ label: '精准贫困户', name: 'IsPoor', width: 100, align: "left",
+ formatterAsync: function (callback, value, row, op, $cell) {
+ learun.clientdata.getAsync('dataItem', {
+ key: value,
+ code: 'YesOrNoInt',
+ callback: function (_data) {
+ callback(_data.text);
+ }
+ });
+ }
+ },
],
mainId: 'ID',
isPage: true,
diff --git a/Learun.Framework.Ultimate V7/Learun.Application.Web/XmlConfig/system.config b/Learun.Framework.Ultimate V7/Learun.Application.Web/XmlConfig/system.config
index 51ab18d27..427bcbb62 100644
--- a/Learun.Framework.Ultimate V7/Learun.Application.Web/XmlConfig/system.config
+++ b/Learun.Framework.Ultimate V7/Learun.Application.Web/XmlConfig/system.config
@@ -158,4 +158,5 @@
+
\ No newline at end of file
diff --git a/Learun.Framework.Ultimate V7/Learun.Application.WebApi/XmlConfig/system.config b/Learun.Framework.Ultimate V7/Learun.Application.WebApi/XmlConfig/system.config
index c3ff40839..c8ecfcc22 100644
--- a/Learun.Framework.Ultimate V7/Learun.Application.WebApi/XmlConfig/system.config
+++ b/Learun.Framework.Ultimate V7/Learun.Application.WebApi/XmlConfig/system.config
@@ -100,4 +100,5 @@
+
\ No newline at end of file
diff --git a/Learun.Framework.Ultimate V7/LearunApp-2.2.0/pages/EducationalAdministration/Thermography/list.vue b/Learun.Framework.Ultimate V7/LearunApp-2.2.0/pages/EducationalAdministration/Thermography/list.vue
index a15bcd04d..0f17985d1 100644
--- a/Learun.Framework.Ultimate V7/LearunApp-2.2.0/pages/EducationalAdministration/Thermography/list.vue
+++ b/Learun.Framework.Ultimate V7/LearunApp-2.2.0/pages/EducationalAdministration/Thermography/list.vue
@@ -1,77 +1,95 @@
-
+
- {{ tips }}
+ {{
+ tips
+ }}
-
+
-
班级:
- {{ displayListItem(item, 'ClassNo') }}
+ {{ displayListItem(item, "ClassNo") }}
测温人:
- {{ displayListItem(item, 'MeasurerID') }}
+ {{ displayListItem(item, "MeasurerID") }}
被测温人:
- {{ displayListItem(item, 'PersonBeingMeasured') }}
+ {{ displayListItem(item, "PersonBeingMeasured") }}
测量时间:
- {{ displayListItem(item, 'MeasureDate') }}
+ {{ displayListItem(item, "MeasureDate") }}
测温时间段:
- {{ displayListItem(item, 'MeasureTime') }}
+ {{ displayListItem(item, "MeasureTime") }}
状态:
- {{ displayListItem(item, 'Status') }}
+ {{ displayListItem(item, "Status") }}
温度:
- {{ displayListItem(item, 'Temperature') }}
+ {{ displayListItem(item, "Temperature") }}
处理结果:
- {{ displayListItem(item, 'ProcessingResult') }}
+ {{ displayListItem(item, "ProcessingResult") }}
备注:
- {{ displayListItem(item, 'Remark') }}
+ {{ displayListItem(item, "Remark") }}
-
-
+
-
+
-
- 重置查询条件
+ 重置查询条件
-
@@ -135,40 +154,63 @@
* 本段代码由移动端代码生成器输出,移动端须 2.2.0 版本及以上可以使用
* 请在移动端 /pages.json 中的 pages 字段中添加一条记录:
* { "path": "pages/EducationalAdministration/Thermography/list", "style": { "navigationBarTitleText": "表单列表页" } }
- *
+ *
* (navigationBarTitleText 字段为本页面的标题文本,可以修改)
* (必须自行操作该步骤,力软代码生成器不会自动帮您修改 /pages.json 文件)
*/
-import moment from 'moment'
-import get from 'lodash/get'
-import set from 'lodash/set'
-import pickBy from 'lodash/pickBy'
-import mapValues from 'lodash/mapValues'
+import moment from "moment";
+import get from "lodash/get";
+import set from "lodash/set";
+import pickBy from "lodash/pickBy";
+import mapValues from "lodash/mapValues";
export default {
data() {
return {
// 数据项的数据类型、结构
scheme: {
- ClassNo: { type: 'select', dataSource: '1', dataSourceId: 'bjsj,classname,classno' },
- MeasurerID: { type: 'select', dataSource: '1', dataSourceId: 'BaseUser,f_realname,f_account' },
- PersonBeingMeasured: { type: 'select', dataSource: '1', dataSourceId: 'StuInfoBasic,stuname,stuno' },
- MeasureDate: { type: 'datetime', dateformat: '0' },
- MeasureTime: { type: 'select', itemCode: 'MeasureTime', dataSource: '0' },
- Status: { type: 'select', itemCode: 'TemperatureMeasure', dataSource: '0' },
- Temperature: { type: 'text' },
- ProcessingResult: { type: 'textarea' },
- Remark: { type: 'textarea' },
+ ClassNo: {
+ type: "select",
+ dataSource: "1",
+ dataSourceId: "bjsj,classname,classno",
+ },
+ MeasurerID: {
+ type: "select",
+ dataSource: "1",
+ dataSourceId: "BaseUser,f_realname,f_account",
+ },
+ PersonBeingMeasured: {
+ type: "select",
+ dataSource: "1",
+ dataSourceId: "StuInfoBasic,stuname,stuno",
+ },
+ MeasureDate: { type: "datetime", dateformat: "0" },
+ MeasureTime: {
+ type: "select",
+ itemCode: "MeasureTime",
+ dataSource: "0",
+ },
+ Status: {
+ type: "select",
+ itemCode: "TemperatureMeasure",
+ dataSource: "0",
+ },
+ Temperature: { type: "text" },
+ ProcessingResult: { type: "textarea" },
+ Remark: { type: "textarea" },
},
// 查询条件
- searchData: {},
+ searchData: {
+ MeasurerID: this.GET_GLOBAL("loginUser").account,
+ },
defaultQueryData: {},
queryData: {
- ClassNo: '',
- PersonBeingMeasured: '',
- MeasureTime: '',
- Status: '',
+ ClassNo: "",
+ PersonBeingMeasured: "",
+ MeasureTime: "",
+ Status: "",
+ MeasurerID: this.GET_GLOBAL("loginUser").account,
},
// 数据源
@@ -176,8 +218,12 @@ export default {
ClassNo: [],
MeasurerID: [],
PersonBeingMeasured: [],
- MeasureTime: Object.values(this.GET_GLOBAL('dataDictionary').MeasureTime).map(t => ({ value: t.value, text: t.text })),
- Status: Object.values(this.GET_GLOBAL('dataDictionary').TemperatureMeasure).map(t => ({ value: t.value, text: t.text })),
+ MeasureTime: Object.values(
+ this.GET_GLOBAL("dataDictionary").MeasureTime
+ ).map((t) => ({ value: t.value, text: t.text })),
+ Status: Object.values(
+ this.GET_GLOBAL("dataDictionary").TemperatureMeasure
+ ).map((t) => ({ value: t.value, text: t.text })),
},
// 时间查询参数
@@ -185,183 +231,226 @@ export default {
// 页面相关参数
ready: false,
- tips: '加载中...',
- loadState: '向下翻以加载更多',
+ tips: "加载中...",
+ loadState: "向下翻以加载更多",
sideOpen: false,
// 列表与分页信息
page: 1,
total: 2,
- list: []
- }
+ list: [],
+ };
},
async onLoad() {
- await this.init()
+ await this.init();
},
onUnload() {
- this.OFF('EducationalAdministrationThermography-list-change')
+ this.OFF("EducationalAdministrationThermography-list-change");
},
methods: {
// 页面初始化
async init() {
- this.ON('EducationalAdministrationThermography-list-change', this.refreshList)
+ this.ON(
+ "EducationalAdministrationThermography-list-change",
+ this.refreshList
+ );
// 拉取加载列表和数据源
await Promise.all([
- this.FETCH_DATASOURCE('bjsj').then(data => {
- this.dataSource.ClassNo = data.data.map(t => ({ text: t.classname, value: t.classno }))
+ this.FETCH_DATASOURCE("bjsj").then((data) => {
+ this.dataSource.ClassNo = data.data.map((t) => ({
+ text: t.classname,
+ value: t.classno,
+ }));
}),
- this.FETCH_DATASOURCE('BaseUser').then(data => {
- this.dataSource.MeasurerID = data.data.map(t => ({ text: t.f_realname, value: t.f_account }))
+ this.FETCH_DATASOURCE("BaseUser").then((data) => {
+ this.dataSource.MeasurerID = data.data.map((t) => ({
+ text: t.f_realname,
+ value: t.f_account,
+ }));
}),
- this.FETCH_DATASOURCE('StuInfoBasic').then(data => {
- this.dataSource.PersonBeingMeasured = data.data.map(t => ({ text: t.stuname, value: t.stuno }))
+ this.FETCH_DATASOURCE("StuInfoBasic").then((data) => {
+ this.dataSource.PersonBeingMeasured = data.data.map((t) => ({
+ text: t.stuname,
+ value: t.stuno,
+ }));
}),
-
-
- () => {}
- ])
- await this.fetchList()
+ () => {},
+ ]);
+ await this.fetchList();
// 初始化查询条件
- this.defaultQueryData = this.COPY(this.queryData)
- this.ready = true
+ this.defaultQueryData = this.COPY(this.queryData);
+ this.ready = true;
},
// 拉取列表
async fetchList() {
- if (this.page > this.total) { return }
+ if (this.page > this.total) {
+ return;
+ }
const result = await this.HTTP_GET(
- '/EducationalAdministration/Thermography/pagelist',
+ "/EducationalAdministration/Thermography/pagelist",
{
// 这里 sidx 表示排序字段,sord 表示排序方式(DESC=降序,ASC=升序)
// 代码生成器生成时默认按照主键排序,您可以修改成按创建时间的字段降序
- pagination: { rows: 10, page: this.page, sidx: 'ID', sord: 'DESC' },
- queryJson: JSON.stringify(this.searchData)
+ pagination: { rows: 10, page: this.page, sidx: "ID", sord: "DESC" },
+ queryJson: JSON.stringify(this.searchData),
},
- '加载数据时出错'
- )
+ "加载数据时出错"
+ );
- if (!result) { return }
+ if (!result) {
+ return;
+ }
- this.total = result.total
- this.page = result.page + 1
- this.list = this.list.concat(result.rows)
+ this.total = result.total;
+ this.page = result.page + 1;
+ this.list = this.list.concat(result.rows);
- this.tips = `已加载 ${Math.min(result.page, result.total)} / ${result.total} 页,共 ${result.records} 项`
- this.loadState = result.page >= result.total ? '已加载所有项目' : '向下翻以加载更多'
+ this.tips = `已加载 ${Math.min(result.page, result.total)} / ${
+ result.total
+ } 页,共 ${result.records} 项`;
+ this.loadState =
+ result.page >= result.total ? "已加载所有项目" : "向下翻以加载更多";
},
// 刷新清空列表
async refreshList() {
- this.page = 1
- this.total = 2
- this.list = []
+ this.page = 1;
+ this.total = 2;
+ this.list = [];
- await this.fetchList()
+ await this.fetchList();
},
// 列表下拉
pullDown() {
this.refreshList().then(() => {
- this.$refs.list.stopPullDown()
- })
+ this.$refs.list.stopPullDown();
+ });
},
// 设置搜索条件
async searchChange() {
- const result = {}
+ const result = {};
// 时间查询相关参数
if (this.dateRange) {
- result.StartTime = this.dateRange.start
- result.EndTime = this.dateRange.end
+ result.StartTime = this.dateRange.start;
+ result.EndTime = this.dateRange.end;
}
// 将其他查询项添加到查询 JSON 中
- const queryObj = pickBy(this.queryData, t => (Array.isArray(t) ? t.length > 0 : t))
- Object.assign(result, mapValues(queryObj, t => (Array.isArray(t) ? t.join(',') : t)))
-
- this.searchData = result
- await this.refreshList()
+ const queryObj = pickBy(this.queryData, (t) =>
+ Array.isArray(t) ? t.length > 0 : t
+ );
+ Object.assign(
+ result,
+ mapValues(queryObj, (t) => (Array.isArray(t) ? t.join(",") : t))
+ );
+
+ this.searchData = result;
+ await this.refreshList();
},
// 点击「清空查询条件」按钮
reset() {
- this.$refs.datefilter.changeDateRange('all')
- this.queryData = this.COPY(this.defaultQueryData)
- this.searchChange()
+ this.$refs.datefilter.changeDateRange("all");
+ this.queryData = this.COPY(this.defaultQueryData);
+ this.searchChange();
},
// 点击「编辑」、「查看」、「添加」、「删除」按钮
- async action(type, id = '') {
+ async action(type, id = "") {
switch (type) {
- case 'view':
- this.NAV_TO(`./single?type=view&id=${id}`)
- return
+ case "view":
+ this.NAV_TO(`./single?type=view&id=${id}`);
+ return;
- case 'add':
- this.NAV_TO('./single?type=create')
- return
+ case "add":
+ this.NAV_TO("./single?type=create");
+ return;
- case 'edit':
- this.NAV_TO(`./single?type=edit&id=${id}`)
- return
+ case "edit":
+ this.NAV_TO(`./single?type=edit&id=${id}`);
+ return;
- case 'delete':
- if (!(await this.CONFIRM('删除项目', '确定要删除该项吗?', true))) {
- return
+ case "delete":
+ if (!(await this.CONFIRM("删除项目", "确定要删除该项吗?", true))) {
+ return;
}
- this.HTTP_POST('/EducationalAdministration/Thermography/delete', id, '删除失败').then(success => {
- if(!success) { return }
- this.TOAST('删除成功', 'success')
- this.refreshList()
- })
- return
+ this.HTTP_POST(
+ "/EducationalAdministration/Thermography/delete",
+ id,
+ "删除失败"
+ ).then((success) => {
+ if (!success) {
+ return;
+ }
+ this.TOAST("删除成功", "success");
+ this.refreshList();
+ });
+ return;
default:
- return
+ return;
}
},
// 显示列表中的标题项
displayListItem(item, field) {
- const fieldItem = this.scheme[field]
- const value = item[field]
+ const fieldItem = this.scheme[field];
+ const value = item[field];
switch (fieldItem.type) {
- case 'currentInfo':
- case 'organize':
- return fieldItem.dataType === 'time' ? value : get(this.GET_GLOBAL(fieldItem.dataType), `${value}.name`, '')
-
- case 'radio':
- case 'select':
- const selectItem = this.dataSource[field].find(t => t.value === String(value))
- return get(selectItem, 'text', '')
-
- case 'checkbox':
- if (!value || value.split(',').length <= 0) { return '' }
- const checkboxItems = value.split(',')
- return this.dataSource[field].filter(t => checkboxItems.includes(t.value)).map(t => t.text).join(',')
-
- case 'datetime':
- if (!value) { return '' }
- return moment(value).format(Number(fieldItem.dateformat) === 0 ? 'YYYY年 M月 D日' : 'YYYY-MM-DD HH:mm')
+ case "currentInfo":
+ case "organize":
+ return fieldItem.dataType === "time"
+ ? value
+ : get(this.GET_GLOBAL(fieldItem.dataType), `${value}.name`, "");
+
+ case "radio":
+ case "select":
+ const selectItem = this.dataSource[field].find(
+ (t) => t.value === String(value)
+ );
+ return get(selectItem, "text", "");
+
+ case "checkbox":
+ if (!value || value.split(",").length <= 0) {
+ return "";
+ }
+ const checkboxItems = value.split(",");
+ return this.dataSource[field]
+ .filter((t) => checkboxItems.includes(t.value))
+ .map((t) => t.text)
+ .join(",");
+
+ case "datetime":
+ if (!value) {
+ return "";
+ }
+ return moment(value).format(
+ Number(fieldItem.dateformat) === 0
+ ? "YYYY年 M月 D日"
+ : "YYYY-MM-DD HH:mm"
+ );
- default: return value === null || value === undefined ? '' : value
+ default:
+ return value === null || value === undefined ? "" : value;
}
- }
-
- }
-}
+ },
+ },
+};
From cb7c612d74212fb140f6c365721626fb44511045 Mon Sep 17 00:00:00 2001
From: zhichao lei <442149704@qq.com>
Date: Wed, 14 Oct 2020 10:42:01 +0800
Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=99=A4=E4=BA=86?=
=?UTF-8?q?=E7=AE=A1=E7=90=86=E5=91=98=E5=A4=96=20=E5=85=B6=E4=BB=96?=
=?UTF-8?q?=E4=BA=BA=E4=BD=BF=E7=94=A8=E4=B8=8D=E4=BA=86=E5=AF=BC=E8=88=AA?=
=?UTF-8?q?=E7=89=88=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../SystemModule/Module/ModuleBLL.cs | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Learun.Framework.Ultimate V7/Learun.Framework.Module/Learun.Application.Module/Learun.Application.Base/SystemModule/Module/ModuleBLL.cs b/Learun.Framework.Ultimate V7/Learun.Framework.Module/Learun.Application.Module/Learun.Application.Base/SystemModule/Module/ModuleBLL.cs
index 7992acd5a..2c3889e69 100644
--- a/Learun.Framework.Ultimate V7/Learun.Framework.Module/Learun.Application.Module/Learun.Application.Base/SystemModule/Module/ModuleBLL.cs
+++ b/Learun.Framework.Ultimate V7/Learun.Framework.Module/Learun.Application.Module/Learun.Application.Base/SystemModule/Module/ModuleBLL.cs
@@ -4,6 +4,7 @@ using Learun.Cache.Factory;
using Learun.Util;
using System;
using System.Collections.Generic;
+using System.Linq;
namespace Learun.Application.Base.SystemModule
{
@@ -47,6 +48,8 @@ namespace Learun.Application.Base.SystemModule
cache.Write>(cacheKey, list, CacheId.module);
}
+ //导航版
+ var entity = list.FirstOrDefault(a => a.F_ModuleId == "be81bdde-8bbc-4080-b976-84faefc414d2");
UserInfo userInfo = LoginUserInfo.Get();
/*关联权限*/
if (!userInfo.isSystem)
@@ -56,6 +59,11 @@ namespace Learun.Application.Base.SystemModule
list = list.FindAll(t => itemIdList.IndexOf(t.F_ModuleId) >= 0);
}
+ if (!list.Any(a => a.F_ModuleId == "be81bdde-8bbc-4080-b976-84faefc414d2") && entity != null)
+ {
+ list.Add(entity);
+ }
+
return list;
}
catch (Exception ex)