@@ -1,4 +1,4 @@ | |||
function GetQueryString(name) { | |||
function GetQueryString(name) { | |||
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); | |||
var r = window.location.search.substr(1).match(reg);//search,查询?后面的参数,并匹配正则 | |||
if (r != null) return unescape(r[2]); return null; | |||
@@ -665,7 +665,7 @@ namespace Learun.Application.Web.Areas.EducationalAdministration.Controllers | |||
FinaChargesStandardList = FinaChargesStandardList, | |||
StuInfoFreshFamilyList = stuInfoFreshFamily, | |||
PayFeeTotal = PayFeeTotal, | |||
YJAmount = FeeOrderList.Sum(x => x.SJAmount) | |||
YJAmount = FinaChargesStandardList.Sum(x => x.PayedMoney) | |||
}; | |||
return Success(jsonData); | |||
} | |||
@@ -1321,9 +1321,6 @@ namespace Learun.Application.Web.Areas.EducationalAdministration.Controllers | |||
if (!string.IsNullOrEmpty(imgUrl)) | |||
{ | |||
// model.PayFeeDetail = entity.PayFeeDetail; | |||
// model.PayMoney = entity.PayMoney; | |||
model.LoanMoney = entity.LoanMoney; | |||
model.orderid = orderid; | |||
stuInfoFreshIBLL.SaveFeeData(keyValue, model, list); | |||
} | |||
@@ -115,6 +115,7 @@ var bootstrap = function ($, learun) { | |||
var detail = ""; | |||
var ifisnull = false; | |||
$('.paydetail').each(function (i, item) { | |||
$(this).attr('disabled', 'disabled'); | |||
var value = 0; | |||
if (!!$(this).val()) { | |||
value = parseFloat($(this).val()); | |||
@@ -142,8 +143,6 @@ var bootstrap = function ($, learun) { | |||
param.PayMoney = $('#PayMoney').html(); | |||
learun.loading(true, '正在生成付款信息请稍等...'); | |||
$("#confirmPayFee").hide(); | |||
console.log(JSON.stringify(param)); | |||
console.log(JSON.stringify(list)); | |||
learun.httpAsyncPost(top.$.rootUrl + '/EducationalAdministration/StuInfoBasic_PayFee/PayFeeQRCode?keyValue=' + keyValue, { strEntity: JSON.stringify(param), detailList: JSON.stringify(list) }, function (res) { | |||
learun.loading(false); | |||
$('#qrcodeImg').attr('src', res.info); | |||
@@ -52,7 +52,7 @@ var bootstrap = function ($, learun) { | |||
title: '二维码缴费', | |||
url: top.$.rootUrl + '/EducationalAdministration/StuInfoBasic_PayFee/PayFeeForm?keyValue=' + keyValue, | |||
width: 800, | |||
height: 650, | |||
height: 690, | |||
btn: null | |||
}); | |||
} | |||
@@ -108,7 +108,7 @@ var bootstrap = function ($, learun) { | |||
{ | |||
label: "性别", name: "GenderNo", width: 80, align: "left", | |||
formatter: function (cellvalue) { | |||
return cellvalue == true ? "男" : "女"; | |||
return cellvalue === true ? "男" : "女"; | |||
} | |||
}, | |||
{ label: "身份证号", name: "IdentityCardNo", width: 150, align: "left" }, | |||
@@ -102,7 +102,7 @@ var bootstrap = function ($, learun) { | |||
$.each(data['FinaChargesStandardList'], function (i, item) { | |||
html += '<tr><td class=\"tableLeft\">' + item.ChargeItemName + '</td><td>' + item.Standard + '元</td><td><input id="' + item.ChargeItemCode + '" data-amount="' + item.Standard + '" data-name="' + item.ChargeItemName + '" type="number" class="form-control paydetail" value="' + item.SJAmount + '" /></td></tr>'; | |||
}); | |||
html += '<tr><td class=\"tableLeft\">应缴合计</td><td>' + data['PayFeeTotal'] + '元</td><td><span id="PayMoney"></span></td></tr>'; | |||
html += '<tr><td class=\"tableLeft\">应缴合计</td><td>' + data['PayFeeTotal'] + '元</td><td><span id="PayMoney">' + PayFeeTotal+'</span></td></tr>'; | |||
html += '<tr><td class=\"tableLeft\"> </td><td colspan="2"> </td></tr>'; | |||
html += '<tr><td class=\"tableLeft\">已缴金额</td><td colspan="2">' + YJAmount + '</td></tr>'; | |||
$('#PayFeeDetail').html(html); | |||
@@ -114,6 +114,7 @@ var bootstrap = function ($, learun) { | |||
var detail = ""; | |||
var ifisnull = false; | |||
$('.paydetail').each(function (i, item) { | |||
$(this).attr('disabled', 'disabled'); | |||
var value = 0; | |||
if (!!$(this).val()) { | |||
value = parseFloat($(this).val()); | |||
@@ -53,7 +53,7 @@ var bootstrap = function ($, learun) { | |||
title: '二维码缴费', | |||
url: top.$.rootUrl + '/EducationalAdministration/StuInfoFresh/PayFeeForm?keyValue=' + keyValue, | |||
width: 800, | |||
height: 650, | |||
height: 690, | |||
btn: null | |||
}); | |||
} | |||
@@ -302,8 +302,14 @@ var bootstrap = function ($, learun) { | |||
{ label: '学号', name: 'StuNo', width: 100, align: "left" }, | |||
{ label: '姓名', name: 'StuName', width: 100, align: "left" }, | |||
{ | |||
label: '线上缴费状态', name: 'PayFeeStatus', width: 100, align: "left", formatter: function (value) { | |||
return value == 1 ? "<span class=\"label label-success\">已缴费</span>" : "<span class=\"label label-warning\">未缴费</span>"; | |||
label: '线上缴费状态', name: 'PayFeeStatus', width: 100, align: "left", formatterAsync: function (callback, value, row, op, $cell) { | |||
learun.clientdata.getAsync('dataItem', { | |||
key: value, | |||
code: 'PayStatus', | |||
callback: function (_data) { | |||
callback(_data.text); | |||
} | |||
}); | |||
} | |||
}, | |||
{ label: '线上缴费时间', name: 'PayFeeDate', width: 130, align: "left" }, | |||
@@ -15,14 +15,14 @@ | |||
<div class="lr-layout-wrap lr-layout-wrap-notitle" style="padding-top:10px;"> | |||
<div class="lr-layout-body"> | |||
<ul class="lr-left-list" id="lr_left_list"> | |||
<li data-value="1">基本信息</li> | |||
<li data-value="1" class="active">基本信息</li> | |||
@*<li data-value="2">联系方式</li>*@ | |||
<li data-value="3">我的头像</li> | |||
<li data-value="4">修改密码</li> | |||
<li data-value="5">我的日志</li> | |||
@if (ViewBag.UserType == "学生") | |||
{ | |||
<li data-value="6">选修流程</li> | |||
@*<li data-value="6">选修流程</li>*@ | |||
} | |||
<li data-value="7">语言设置</li> | |||
</ul> | |||
@@ -190,6 +190,7 @@ | |||
}, | |||
filters: { | |||
sex: function (value) { | |||
console.log(value); | |||
return value ? "男生" : "女生"; | |||
}, | |||
@@ -686,7 +687,7 @@ | |||
</div> | |||
@if (ViewBag.UserType == "学生") | |||
{ | |||
<div class="lr-layout-wrap-item " id="lr_layout_item6" style="padding: 10;"> | |||
@*<div class="lr-layout-wrap-item " id="lr_layout_item6" style="padding: 10;"> | |||
<center><h3> 西昌民族幼儿师范高等专科学校</h3></center> | |||
<center> | |||
<h3> | |||
@@ -710,7 +711,7 @@ | |||
3、选择课只开放三天,三天后自动关闭选课功能,每门选修课记2个选修学分,如果修不够选修学分将会无法毕业。<br /> | |||
</p> | |||
</div> | |||
</div> | |||
</div>*@ | |||
} | |||
@if (ViewBag.UserType == "学生" || ViewBag.UserType == "教师") | |||
@@ -742,8 +743,8 @@ | |||
$("#headUrl").attr("src", "/LR_OrganizationModule/User/GetImg?userId=" + loginInfo.userId); | |||
if ('@ViewBag.UserType' == '学生') { | |||
$("#lr_left_list").children('li').eq(4).addClass("active"); | |||
$('.lr-layout-wrap-item').eq(5).addClass("active"); | |||
$("#lr_left_list").children('li').eq(0).addClass("active"); | |||
$('.lr-layout-wrap-item').eq(0).addClass("active"); | |||
} else { | |||
$("#lr_left_list").children('li').eq(0).addClass("active"); | |||
@@ -154,7 +154,7 @@ | |||
<add key="ACIp" value="192.168.90.2"/> | |||
<add key="ACIp2" value="192.168.200.252"/> | |||
<!-- 是否强制验证强密码 --> | |||
<add key="verifypwd" value="true"/> | |||
<add key="verifypwd" value="false"/> | |||
<!--疫情防控组角色Id--> | |||
<add key="EpidemicControlTeamRoleId" value="87f38e4e-b0a6-472c-b01a-2620b8f1ec46" /> | |||
<!--注册教师生成编号 金隅:jy;西昌:xc;大厂:dc--> | |||
@@ -156,6 +156,9 @@ | |||
<Reference Include="System.Web.Services" /> | |||
<Reference Include="System.EnterpriseServices" /> | |||
<Reference Include="System.Xml.Linq" /> | |||
<Reference Include="ThoughtWorks.QRCode, Version=1.0.4778.30637, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\ThoughtWorks.QRCode.1.1.0\lib\ThoughtWorks.QRCode.dll</HintPath> | |||
</Reference> | |||
<Reference Include="WebGrease, Version=1.5.2.14234, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> | |||
<HintPath>..\packages\WebGrease.1.5.2\lib\WebGrease.dll</HintPath> | |||
</Reference> | |||
@@ -192,6 +195,8 @@ | |||
<ItemGroup> | |||
<Compile Include="Bootstraper.cs" /> | |||
<Compile Include="Modules\AnnexesApiWx.cs" /> | |||
<Compile Include="Modules\StuFreshPayFeeApi.cs" /> | |||
<Compile Include="Modules\StuPayFeeApi.cs" /> | |||
<Compile Include="Modules\BaseNoLoginApi.cs" /> | |||
<Compile Include="Modules\ArrangeLessonTermAttemperApi.cs" /> | |||
<Compile Include="Modules\DataSourceNoLoginApi.cs" /> | |||
@@ -7,136 +7,135 @@ using System.IO; | |||
namespace Learun.Application.WebApi.Modules | |||
{ | |||
public class AnnexesApiWx : BaseApi | |||
{ | |||
public AnnexesApiWx() | |||
: base("/learun/adms/annexes") | |||
public class AnnexesApiWx : BaseApi | |||
{ | |||
Get["/wxlist"] = WxGetList; | |||
Get["/wxdown"] = WxDownload; | |||
Get["/wxfileinfo"] = WxFileInfo; | |||
Post["/wxupload"] = WxUpload; | |||
Post["/wxdelete"] = WxDeleteFile; | |||
public AnnexesApiWx() | |||
: base("/learun/adms/annexes") | |||
{ | |||
Get["/wxlist"] = WxGetList; | |||
Get["/wxdown"] = WxDownload; | |||
Get["/wxfileinfo"] = WxFileInfo; | |||
Post["/wxupload"] = WxUpload; | |||
Post["/wxdelete"] = WxDeleteFile; | |||
} | |||
private AnnexesFileIBLL annexesFileIBLL = new AnnexesFileBLL(); | |||
/// <summary> | |||
/// 获取附件列表 | |||
/// </summary> | |||
/// <param name="_"></param> | |||
/// <returns></returns> | |||
public Response WxGetList(dynamic _) | |||
{ | |||
var keyValue = this.GetReqData(); | |||
var list = annexesFileIBLL.GetList(keyValue); | |||
return Success(list); | |||
} | |||
/// <summary> | |||
/// 上传附件图片文件 | |||
/// <summary> | |||
/// <returns></returns> | |||
public Response WxUpload(dynamic _) | |||
{ | |||
var files = (List<HttpFile>)this.Context.Request.Files; | |||
string folderId = Request.Form["folderId"]; | |||
string filePath = Config.GetValue("AnnexesFile"); | |||
string uploadDate = DateTime.Now.ToString("yyyyMMdd"); | |||
string fileEextension = Path.GetExtension(files[0].Name); | |||
string fileType = fileEextension.Replace(".", ""); | |||
string fileGuid = Guid.NewGuid().ToString(); | |||
string virtualPath = string.Format("{0}/{1}/{2}/{3}{4}", filePath, userInfo.userId, uploadDate, fileGuid, fileEextension); | |||
//创建文件夹 | |||
string path = Path.GetDirectoryName(virtualPath); | |||
Directory.CreateDirectory(path); | |||
AnnexesFileEntity fileAnnexesEntity = new AnnexesFileEntity(); | |||
if (!System.IO.File.Exists(virtualPath)) | |||
{ | |||
byte[] bytes = new byte[files[0].Value.Length]; | |||
files[0].Value.Read(bytes, 0, bytes.Length); | |||
FileInfo file = new FileInfo(virtualPath); | |||
FileStream fs = file.Create(); | |||
fs.Write(bytes, 0, bytes.Length); | |||
fs.Close(); | |||
//文件信息写入数据库 | |||
fileAnnexesEntity.F_Id = fileGuid; | |||
fileAnnexesEntity.F_FileName = files[0].Name; | |||
fileAnnexesEntity.F_FilePath = virtualPath; | |||
fileAnnexesEntity.F_FileSize = files[0].Value.Length.ToString(); | |||
fileAnnexesEntity.F_FileExtensions = fileEextension; | |||
fileAnnexesEntity.F_FileType = fileType; | |||
fileAnnexesEntity.F_CreateUserId = userInfo.userId; | |||
fileAnnexesEntity.F_CreateUserName = userInfo.realName; | |||
annexesFileIBLL.SaveEntity(folderId, fileAnnexesEntity); | |||
} | |||
return SuccessString(folderId); | |||
} | |||
/// <summary> | |||
/// 获取文件信息 | |||
/// </summary> | |||
/// <param name="_"></param> | |||
/// <returns></returns> | |||
public Response WxFileInfo(dynamic _) | |||
{ | |||
var fileId = this.GetReqData(); | |||
var fileEntity = annexesFileIBLL.GetEntity(fileId); | |||
return Success(fileEntity); | |||
} | |||
/// <summary> | |||
/// 删除文件 | |||
/// </summary> | |||
/// <param name="_"></param> | |||
/// <returns></returns> | |||
public Response WxDeleteFile(dynamic _) | |||
{ | |||
var fileId = this.GetReqData(); | |||
AnnexesFileEntity fileInfoEntity = annexesFileIBLL.GetEntity(fileId); | |||
annexesFileIBLL.DeleteEntity(fileId); | |||
//删除文件 | |||
if (System.IO.File.Exists(fileInfoEntity.F_FilePath)) | |||
{ | |||
System.IO.File.Delete(fileInfoEntity.F_FilePath); | |||
} | |||
return Success("删除成功"); | |||
} | |||
/// <summary> | |||
/// 下载文件,微信小程序用 | |||
/// | |||
/// 微信小程序可以预览图片、文档 | |||
/// 支持的图片格式:.jpg .png .webp .gif | |||
/// 支持的文档格式:.doc(x) .xls(x) .ppt(x) .pdf | |||
/// | |||
/// 对于其他格式的文件,微信小程序官方未提供打开或预览的 API,文件对用户来说不可访问 | |||
/// </summary> | |||
/// <param name="_"></param> | |||
/// <returns></returns> | |||
public Response WxDownload(dynamic _) | |||
{ | |||
string name = this.GetReqData(); | |||
string fileId = name.Split('.')[0]; | |||
var fileEntity = annexesFileIBLL.GetEntity(fileId); | |||
string filepath = fileEntity.F_FilePath; | |||
if (!FileDownHelper.FileExists(filepath)) | |||
{ | |||
return 404; | |||
} | |||
FileDownHelper.DownLoadWx(filepath, fileEntity.F_FileType); | |||
return Success(""); | |||
} | |||
} | |||
private AnnexesFileIBLL annexesFileIBLL = new AnnexesFileBLL(); | |||
/// <summary> | |||
/// 获取附件列表 | |||
/// </summary> | |||
/// <param name="_"></param> | |||
/// <returns></returns> | |||
public Response WxGetList(dynamic _) | |||
{ | |||
var keyValue = this.GetReqData(); | |||
var list = annexesFileIBLL.GetList(keyValue); | |||
return Success(list); | |||
} | |||
/// <summary> | |||
/// 上传附件图片文件 | |||
/// <summary> | |||
/// <returns></returns> | |||
public Response WxUpload(dynamic _) | |||
{ | |||
var files = (List<HttpFile>)this.Context.Request.Files; | |||
var folderId = this.GetReqData(); | |||
string filePath = Config.GetValue("AnnexesFile"); | |||
string uploadDate = DateTime.Now.ToString("yyyyMMdd"); | |||
string fileEextension = Path.GetExtension(files[0].Name); | |||
string fileType = fileEextension.Replace(".", ""); | |||
string fileGuid = Guid.NewGuid().ToString(); | |||
string virtualPath = string.Format("{0}/{1}/{2}/{3}{4}", filePath, userInfo.userId, uploadDate, fileGuid, fileEextension); | |||
//创建文件夹 | |||
string path = Path.GetDirectoryName(virtualPath); | |||
Directory.CreateDirectory(path); | |||
AnnexesFileEntity fileAnnexesEntity = new AnnexesFileEntity(); | |||
if (!System.IO.File.Exists(virtualPath)) | |||
{ | |||
byte[] bytes = new byte[files[0].Value.Length]; | |||
files[0].Value.Read(bytes, 0, bytes.Length); | |||
FileInfo file = new FileInfo(virtualPath); | |||
FileStream fs = file.Create(); | |||
fs.Write(bytes, 0, bytes.Length); | |||
fs.Close(); | |||
//文件信息写入数据库 | |||
fileAnnexesEntity.F_Id = fileGuid; | |||
fileAnnexesEntity.F_FileName = files[0].Name; | |||
fileAnnexesEntity.F_FilePath = virtualPath; | |||
fileAnnexesEntity.F_FileSize = files[0].Value.Length.ToString(); | |||
fileAnnexesEntity.F_FileExtensions = fileEextension; | |||
fileAnnexesEntity.F_FileType = fileType; | |||
fileAnnexesEntity.F_CreateUserId = userInfo.userId; | |||
fileAnnexesEntity.F_CreateUserName = userInfo.realName; | |||
annexesFileIBLL.SaveEntity(folderId, fileAnnexesEntity); | |||
} | |||
return SuccessString(fileGuid); | |||
} | |||
/// <summary> | |||
/// 获取文件信息 | |||
/// </summary> | |||
/// <param name="_"></param> | |||
/// <returns></returns> | |||
public Response WxFileInfo(dynamic _) | |||
{ | |||
var fileId = this.GetReqData(); | |||
var fileEntity = annexesFileIBLL.GetEntity(fileId); | |||
return Success(fileEntity); | |||
} | |||
/// <summary> | |||
/// 删除文件 | |||
/// </summary> | |||
/// <param name="_"></param> | |||
/// <returns></returns> | |||
public Response WxDeleteFile(dynamic _) | |||
{ | |||
var fileId = this.GetReqData(); | |||
AnnexesFileEntity fileInfoEntity = annexesFileIBLL.GetEntity(fileId); | |||
annexesFileIBLL.DeleteEntity(fileId); | |||
//删除文件 | |||
if (System.IO.File.Exists(fileInfoEntity.F_FilePath)) | |||
{ | |||
System.IO.File.Delete(fileInfoEntity.F_FilePath); | |||
} | |||
return Success("删除成功"); | |||
} | |||
/// <summary> | |||
/// 下载文件,微信小程序用 | |||
/// | |||
/// 微信小程序可以预览图片、文档 | |||
/// 支持的图片格式:.jpg .png .webp .gif | |||
/// 支持的文档格式:.doc(x) .xls(x) .ppt(x) .pdf | |||
/// | |||
/// 对于其他格式的文件,微信小程序官方未提供打开或预览的 API,文件对用户来说不可访问 | |||
/// </summary> | |||
/// <param name="_"></param> | |||
/// <returns></returns> | |||
public Response WxDownload(dynamic _) | |||
{ | |||
string name = this.GetReqData(); | |||
string fileId = name.Split('.')[0]; | |||
var fileEntity = annexesFileIBLL.GetEntity(fileId); | |||
string filepath = fileEntity.F_FilePath; | |||
if (!FileDownHelper.FileExists(filepath)) | |||
{ | |||
return 404; | |||
} | |||
FileDownHelper.DownLoadWx(filepath, fileEntity.F_FileType); | |||
return Success(""); | |||
} | |||
} | |||
} |
@@ -21,12 +21,28 @@ namespace Learun.Application.WebApi.Modules | |||
{ | |||
Get["/scheme"] = GetScheme; | |||
Get["/data"] = GetData; | |||
Get["/folderkey"] = GetFolderkey; | |||
Post["/save"] = Save; | |||
Post["/delete"] = DeleteForm; | |||
} | |||
private FormSchemeIBLL formSchemeIBLL = new FormSchemeBLL(); | |||
private Response GetFolderkey(dynamic _) | |||
{ | |||
List<FolderKeyReq> req = this.GetReqData<List<FolderKeyReq>>();// 获取模板请求数据 | |||
Dictionary<string, string> dic = new Dictionary<string, string>(); | |||
foreach (var item in req) | |||
{ | |||
if (!string.IsNullOrEmpty(item.processIdName)) | |||
{ | |||
var data = formSchemeIBLL.GetFolderKey(item.schemeInfoId, item.processIdName, item.keyValue);// | |||
dic = data; | |||
} | |||
} | |||
return Success(dic); | |||
} | |||
/// <summary> | |||
/// 获取表单模板数据 | |||
/// </summary> | |||
@@ -104,6 +120,35 @@ namespace Learun.Application.WebApi.Modules | |||
} | |||
#region 请求参数 | |||
private class FolderKeyReq | |||
{ | |||
/// <summary> | |||
/// 表单请求Id | |||
/// </summary> | |||
public string id { get; set; } | |||
/// <summary> | |||
/// 当前自定义表单版本号 | |||
/// </summary> | |||
public string ver { get; set; } | |||
/// <summary> | |||
/// 流程模板id | |||
/// </summary> | |||
public string schemeInfoId { get; set; } | |||
/// <summary> | |||
/// 关联字段名称 | |||
/// </summary> | |||
public string processIdName { get; set; } | |||
/// <summary> | |||
/// 数据主键值 | |||
/// </summary> | |||
public string keyValue { get; set; } | |||
/// <summary> | |||
/// 表单数据 | |||
/// </summary> | |||
public string formData { get; set; } | |||
} | |||
private class SchemeReq { | |||
/// <summary> | |||
/// 表单请求Id | |||
@@ -0,0 +1,219 @@ | |||
using System; | |||
using Learun.Application.Organization; | |||
using Learun.Application.TwoDevelopment.EducationalAdministration; | |||
using Learun.Application.TwoDevelopment.EvaluationTeach; | |||
using Learun.Util; | |||
using Nancy; | |||
using System.Collections.Generic; | |||
using System.Drawing; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Security.Cryptography; | |||
using System.Text; | |||
using System.Web; | |||
using System.Web.Mvc; | |||
using Learun.Application.Base.SystemModule; | |||
using Learun.Application.TwoDevelopment.Ask; | |||
using Learun.Application.TwoDevelopment.ReceiveSendFeeManagement; | |||
using Newtonsoft.Json; | |||
using ThoughtWorks.QRCode.Codec; | |||
namespace Learun.Application.WebApi.Modules | |||
{ | |||
/// <summary> | |||
/// 版 本 Learun-ADMS V7.0.0 数字化智慧校园 | |||
/// Copyright (c) 2013-2018 北京泉江科技有限公司 | |||
/// 创建人:数字化智慧校园-框架开发组 | |||
/// 日 期:2018.01.04 | |||
/// 描 述:部门管理 | |||
/// </summary> | |||
public class StuFreshPayFeeApi : BaseApi | |||
{ | |||
public StuFreshPayFeeApi() | |||
: base("/learun/freshpayfee") | |||
{ | |||
Get["/getpayfeelist"] = GetPayfeeList;// 获取缴费列表 | |||
Get["/getpayfeeinfo"] = GetPayfeeInfo;//获取缴费明细 | |||
Post["/generateqrcode"] = PayFeeQRCode;//生成缴费二维码 | |||
Get["/getinvoice"] = GetInvoice;//获取发票 | |||
} | |||
private StuInfoFreshIBLL stuInfoFreshIBLL = new StuInfoFreshBLL(); | |||
private FinaChargesStandardIBLL finaChargesStandardIBLL = new FinaChargesStandardBLL(); | |||
public Response GetInvoice(dynamic _) | |||
{ | |||
string keyValue = Request.Query["keyValue"]; | |||
var list = stuInfoFreshIBLL.GetStuEnrollFeeOrder(keyValue, true); | |||
return Success(list); | |||
} | |||
public Response GetPayfeeList(dynamic _) | |||
{ | |||
ReqPageParam parameter = this.GetReqData<ReqPageParam>(); | |||
var data = stuInfoFreshIBLL.GetPageList(parameter.pagination, parameter.queryJson); | |||
var jsonData = new | |||
{ | |||
rows = data, | |||
total = parameter.pagination.total, | |||
page = parameter.pagination.page, | |||
records = parameter.pagination.records | |||
}; | |||
return Success(jsonData); | |||
} | |||
public Response GetPayfeeInfo(dynamic _) | |||
{ | |||
string keyValue = Request.Query["keyValue"]; | |||
int jiaoFeiYear = DateTime.Now.Year; | |||
var StuInfoFreshData = stuInfoFreshIBLL.GetStuInfoFreshEntity(keyValue); | |||
var stuInfoFreshFamily = stuInfoFreshIBLL.GetStuInfoFreshFamilyList(keyValue); | |||
//当前年度缴费记录 | |||
var FeeOrderList = stuInfoFreshIBLL.GetFeeOrderList(StuInfoFreshData.StuNo, jiaoFeiYear); | |||
var FinaChargesStandardList = new List<FinaChargesStandardEntity>(); | |||
FinaChargesStandardList = finaChargesStandardIBLL.GetFinaChargesStandardListByYongYou(StuInfoFreshData.StuNo, jiaoFeiYear).ToList(); | |||
var PayFeeTotal = FinaChargesStandardList.Select(x => x.Standard).Sum(); | |||
var jsonData = new | |||
{ | |||
StuInfoFreshData = StuInfoFreshData, | |||
FinaChargesStandardList = FinaChargesStandardList, | |||
StuInfoFreshFamilyList = stuInfoFreshFamily, | |||
PayFeeTotal = PayFeeTotal, | |||
YJAmount = FeeOrderList.Sum(x => x.SJAmount) | |||
}; | |||
return Success(jsonData); | |||
} | |||
public class PayfeeRequest | |||
{ | |||
public string strEntity { get; set; } | |||
public string detailList { get; set; } | |||
} | |||
/// <summary> | |||
/// 生成缴费二维码 | |||
/// </summary> | |||
/// <returns></returns> | |||
public Response PayFeeQRCode(dynamic _) | |||
{ | |||
string keyValue = Request.Query["keyValue"]; | |||
PayfeeRequest parameter = this.GetReqData<PayfeeRequest>(); | |||
StuInfoFreshEntity entity = parameter.strEntity.ToObject<StuInfoFreshEntity>(); | |||
List<StuEnrollFeeOrderDetailEntity> list = parameter.detailList.ToObject<List<StuEnrollFeeOrderDetailEntity>>(); | |||
var model = stuInfoFreshIBLL.GetStuInfoFreshEntity(keyValue); | |||
var imgUrl = ""; | |||
Random ran = new Random(); | |||
string merchantid = "105000082201406";//商户号 | |||
string posid = "043724806";//商户柜台代码 | |||
string branchid = "510000000";//分行代码 | |||
string orderid = DateTime.Now.ToString("yyyyMMddhhmmss") + ran.Next(0, 100000); | |||
string payment = entity.PayMoney.ToString(); | |||
string curcode = "01"; | |||
string txcode = "530550"; | |||
string remark1 = model.StuNo; | |||
string remark2 = "20" + model.Grade; | |||
string returntype = "3"; | |||
string timeout = DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"); | |||
string pub32tr2 = "40d987faa793a0a27e7a86ef020111"; | |||
string bankURL = "https://ibsbjstar.ccb.com.cn/CCBIS/ccbMain?CCB_IBSVersion=V6"; | |||
string tmp = "MERCHANTID=" + merchantid + "&POSID=" + posid + "&BRANCHID=" + branchid + "&ORDERID=" + orderid; | |||
tmp += "&PAYMENT=" + payment + "&CURCODE=" + curcode + "&TXCODE=" + txcode + "&REMARK1=" + remark1; | |||
tmp += "&REMARK2=" + remark2 + "&RETURNTYPE=" + returntype + "&TIMEOUT=" + timeout; | |||
MD5 md5 = MD5.Create(); | |||
string tmp1 = tmp; | |||
tmp += "&PUB=" + pub32tr2; | |||
byte[] buffer = Encoding.Default.GetBytes(tmp); | |||
byte[] md5Buffer = md5.ComputeHash(buffer); | |||
string strMd5 = ""; | |||
//hdnOrderId.Value = orderid; | |||
foreach (byte item in md5Buffer) | |||
{ | |||
strMd5 += item.ToString("x2"); | |||
} | |||
string url = bankURL + "&" + tmp1 + "&MAC=" + strMd5; | |||
string reJson = HttpMethods.Post(url); | |||
LogEntity logEntity = new LogEntity(); | |||
logEntity.F_CategoryId = 121; | |||
logEntity.F_ExecuteResultJson = reJson; | |||
logEntity.WriteLog(); | |||
//HttpConnect conn = new HttpConnect(); | |||
//string reJson = conn.Post(url, ""); | |||
JsonBean MemberInfoList = JsonConvert.DeserializeObject<JsonBean>(reJson); | |||
if (MemberInfoList.SUCCESS.Equals("true")) | |||
{ | |||
string imgCode = HttpMethods.Post(MemberInfoList.PAYURL); | |||
logEntity.F_CategoryId = 121; | |||
logEntity.F_ExecuteResultJson = imgCode; | |||
logEntity.WriteLog(); | |||
MemberInfoList = JsonConvert.DeserializeObject<JsonBean>(imgCode); | |||
if (MemberInfoList.SUCCESS.Equals("true")) | |||
{ | |||
imgUrl = CreateQRImg(MemberInfoList.QRURL, orderid); | |||
} | |||
} | |||
if (!string.IsNullOrEmpty(imgUrl)) | |||
{ | |||
// model.PayFeeDetail = entity.PayFeeDetail; | |||
// model.PayMoney = entity.PayMoney; | |||
model.LoanMoney = entity.LoanMoney; | |||
model.orderid = orderid; | |||
stuInfoFreshIBLL.SaveFeeData(keyValue, model, list); | |||
} | |||
return Success(imgUrl); | |||
} | |||
public class JsonBean | |||
{ | |||
/// <summary> | |||
/// | |||
/// </summary> | |||
public string SUCCESS { get; set; } | |||
public string PAYURL { get; set; } | |||
public string QRURL { get; set; } | |||
} | |||
/// <summary> | |||
/// 生成并保存二维码图片的方法 | |||
/// </summary> | |||
/// <param name="str">输入的内容</param> | |||
public string CreateQRImg(string str, string orderId) | |||
{ | |||
string QRCodeFile = Config.GetValue("QRCodeFile"); | |||
Random ran = new Random(); | |||
Bitmap bt; | |||
str = HttpUtility.UrlDecode(str); | |||
string enCodeString = str; | |||
//生成设置编码实例 | |||
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(); | |||
//设置二维码的规模,默认4 | |||
qrCodeEncoder.QRCodeScale = 3; | |||
//设置二维码的版本,默认7 | |||
qrCodeEncoder.QRCodeVersion = 7; | |||
//设置错误校验级别,默认中等 | |||
qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M; | |||
//生成二维码图片 | |||
bt = qrCodeEncoder.Encode(enCodeString, Encoding.UTF8); | |||
//二维码图片的名称 | |||
string filename = orderId; | |||
if (!DirFileHelper.IsExistFile(QRCodeFile + "/Content/images/QRCode/")) | |||
{ | |||
Directory.CreateDirectory(QRCodeFile + "/Content/images/QRCode/"); | |||
} | |||
var path = QRCodeFile + "/Content/images/QRCode/" + filename + ".jpg"; | |||
//保存二维码图片在photos路径下 | |||
try | |||
{ | |||
bt.Save(path); | |||
} | |||
catch (Exception ex) | |||
{ | |||
return ""; | |||
} | |||
//图片控件要显示的二维码图片路径 | |||
return QRCodeFile + "/Content/images/QRCode/" + filename + ".jpg"; | |||
} | |||
} | |||
} |
@@ -0,0 +1,215 @@ | |||
using System; | |||
using Learun.Application.Organization; | |||
using Learun.Application.TwoDevelopment.EducationalAdministration; | |||
using Learun.Application.TwoDevelopment.EvaluationTeach; | |||
using Learun.Util; | |||
using Nancy; | |||
using System.Collections.Generic; | |||
using System.Drawing; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Security.Cryptography; | |||
using System.Text; | |||
using System.Web; | |||
using System.Web.Mvc; | |||
using Learun.Application.Base.SystemModule; | |||
using Learun.Application.TwoDevelopment.Ask; | |||
using Learun.Application.TwoDevelopment.ReceiveSendFeeManagement; | |||
using Newtonsoft.Json; | |||
using ThoughtWorks.QRCode.Codec; | |||
namespace Learun.Application.WebApi.Modules | |||
{ | |||
/// <summary> | |||
/// 版 本 Learun-ADMS V7.0.0 数字化智慧校园 | |||
/// Copyright (c) 2013-2018 北京泉江科技有限公司 | |||
/// 创建人:数字化智慧校园-框架开发组 | |||
/// 日 期:2018.01.04 | |||
/// 描 述:部门管理 | |||
/// </summary> | |||
public class StuPayFeeApi : BaseApi | |||
{ | |||
public StuPayFeeApi() | |||
: base("/learun/payfee") | |||
{ | |||
Get["/getpayfeelist"] = GetPayfeeList;// 获取缴费列表 | |||
Get["/getpayfeeinfo"] = GetPayfeeInfo;//获取缴费明细 | |||
Post["/generateqrcode"] = PayFeeQRCode;//生成缴费二维码 | |||
Get["/getinvoice"] = GetInvoice;//获取发票 | |||
} | |||
private StuInfoBasic_PayFeeIBLL stuInfoBasic_PayFeeIBLL = new StuInfoBasic_PayFeeBLL(); | |||
private StuInfoBasicIBLL stuInfoBasicIbll = new StuInfoBasicBLL(); | |||
private StuInfoFreshIBLL stuInfoFreshIBLL = new StuInfoFreshBLL(); | |||
private FinaChargesStandardIBLL finaChargesStandardIBLL = new FinaChargesStandardBLL(); | |||
public Response GetInvoice(dynamic _) | |||
{ | |||
string keyValue = Request.Query["keyValue"]; | |||
var list = stuInfoFreshIBLL.GetStuEnrollFeeOrder(keyValue, false); | |||
return Success(list); | |||
} | |||
public Response GetPayfeeList(dynamic _) | |||
{ | |||
ReqPageParam parameter = this.GetReqData<ReqPageParam>(); | |||
var data = stuInfoBasic_PayFeeIBLL.GetPageList(parameter.pagination, parameter.queryJson); | |||
var jsonData = new | |||
{ | |||
rows = data, | |||
total = parameter.pagination.total, | |||
page = parameter.pagination.page, | |||
records = parameter.pagination.records | |||
}; | |||
return Success(jsonData); | |||
} | |||
public Response GetPayfeeInfo(dynamic _) | |||
{ | |||
string keyValue = Request.Query["keyValue"]; | |||
var stuInfoBasic_PayFeeEntity = stuInfoBasic_PayFeeIBLL.GetStuInfoBasic_PayFeeEntity(keyValue); | |||
var StuInfoFreshData = stuInfoBasicIbll.GetStuInfoBasicEntityByStuNo(stuInfoBasic_PayFeeEntity.StuNo); | |||
//当前年度缴费记录 | |||
var FinaChargesStandardList = new List<FinaChargesStandardEntity>(); | |||
FinaChargesStandardList = finaChargesStandardIBLL.GetFinaChargesStandardListByYongYou(StuInfoFreshData.StuNo, stuInfoBasic_PayFeeEntity.PayYear.Value).ToList(); | |||
var PayFeeTotal = FinaChargesStandardList.Select(x => x.SJAmount).Sum(); | |||
var jsonData = new | |||
{ | |||
StuInfoFreshData = StuInfoFreshData, | |||
FinaChargesStandardList = FinaChargesStandardList, | |||
PayFeeTotal = PayFeeTotal, | |||
YJAmount = FinaChargesStandardList.Sum(x => x.PayedMoney) | |||
}; | |||
return Success(jsonData); | |||
} | |||
public class PayfeeRequest | |||
{ | |||
public string strEntity { get; set; } | |||
public string detailList { get; set; } | |||
} | |||
/// <summary> | |||
/// 生成缴费二维码 | |||
/// </summary> | |||
/// <returns></returns> | |||
public Response PayFeeQRCode(dynamic _) | |||
{ | |||
string keyValue = Request.Query["keyValue"]; | |||
PayfeeRequest parameter = this.GetReqData<PayfeeRequest>(); | |||
StuInfoFreshEntity entity = parameter.strEntity.ToObject<StuInfoFreshEntity>(); | |||
List<StuEnrollFeeOrderDetailEntity> list = parameter.detailList.ToObject<List<StuEnrollFeeOrderDetailEntity>>(); | |||
var model = stuInfoBasic_PayFeeIBLL.GetStuInfoBasic_PayFeeEntity(keyValue); | |||
var imgUrl = ""; | |||
Random ran = new Random(); | |||
string merchantid = "105000082201406";//商户号 | |||
string posid = "043724806";//商户柜台代码 | |||
string branchid = "510000000";//分行代码 | |||
string orderid = DateTime.Now.ToString("yyyyMMddhhmmss") + ran.Next(0, 100000); | |||
string payment = entity.PayMoney.ToString(); | |||
string curcode = "01"; | |||
string txcode = "530550"; | |||
string remark1 = model.StuNo; | |||
string remark2 = model.PayYear.ToString(); | |||
string returntype = "3"; | |||
string timeout = DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"); | |||
string pub32tr2 = "40d987faa793a0a27e7a86ef020111"; | |||
string bankURL = "https://ibsbjstar.ccb.com.cn/CCBIS/ccbMain?CCB_IBSVersion=V6"; | |||
string tmp = "MERCHANTID=" + merchantid + "&POSID=" + posid + "&BRANCHID=" + branchid + "&ORDERID=" + orderid; | |||
tmp += "&PAYMENT=" + payment + "&CURCODE=" + curcode + "&TXCODE=" + txcode + "&REMARK1=" + remark1; | |||
tmp += "&REMARK2=" + remark2 + "&RETURNTYPE=" + returntype + "&TIMEOUT=" + timeout; | |||
MD5 md5 = MD5.Create(); | |||
string tmp1 = tmp; | |||
tmp += "&PUB=" + pub32tr2; | |||
byte[] buffer = Encoding.Default.GetBytes(tmp); | |||
byte[] md5Buffer = md5.ComputeHash(buffer); | |||
string strMd5 = ""; | |||
//hdnOrderId.Value = orderid; | |||
foreach (byte item in md5Buffer) | |||
{ | |||
strMd5 += item.ToString("x2"); | |||
} | |||
string url = bankURL + "&" + tmp1 + "&MAC=" + strMd5; | |||
string reJson = HttpMethods.Post(url); | |||
LogEntity logEntity = new LogEntity(); | |||
logEntity.F_CategoryId = 121; | |||
logEntity.F_ExecuteResultJson = reJson; | |||
logEntity.WriteLog(); | |||
//HttpConnect conn = new HttpConnect(); | |||
//string reJson = conn.Post(url, ""); | |||
JsonBean MemberInfoList = JsonConvert.DeserializeObject<JsonBean>(reJson); | |||
if (MemberInfoList.SUCCESS.Equals("true")) | |||
{ | |||
string imgCode = HttpMethods.Post(MemberInfoList.PAYURL); | |||
logEntity.F_CategoryId = 121; | |||
logEntity.F_ExecuteResultJson = imgCode; | |||
logEntity.WriteLog(); | |||
MemberInfoList = JsonConvert.DeserializeObject<JsonBean>(imgCode); | |||
if (MemberInfoList.SUCCESS.Equals("true")) | |||
{ | |||
imgUrl = CreateQRImg(MemberInfoList.QRURL, orderid); | |||
} | |||
} | |||
if (!string.IsNullOrEmpty(imgUrl)) | |||
{ | |||
model.orderid = orderid; | |||
stuInfoFreshIBLL.SaveFeeData(keyValue, model, list); | |||
} | |||
return Success(imgUrl); | |||
} | |||
public class JsonBean | |||
{ | |||
/// <summary> | |||
/// | |||
/// </summary> | |||
public string SUCCESS { get; set; } | |||
public string PAYURL { get; set; } | |||
public string QRURL { get; set; } | |||
} | |||
/// <summary> | |||
/// 生成并保存二维码图片的方法 | |||
/// </summary> | |||
/// <param name="str">输入的内容</param> | |||
public string CreateQRImg(string str, string orderId) | |||
{ | |||
string QRCodeFile = Config.GetValue("QRCodeFile"); | |||
Random ran = new Random(); | |||
Bitmap bt; | |||
str = HttpUtility.UrlDecode(str); | |||
string enCodeString = str; | |||
//生成设置编码实例 | |||
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(); | |||
//设置二维码的规模,默认4 | |||
qrCodeEncoder.QRCodeScale = 3; | |||
//设置二维码的版本,默认7 | |||
qrCodeEncoder.QRCodeVersion = 7; | |||
//设置错误校验级别,默认中等 | |||
qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M; | |||
//生成二维码图片 | |||
bt = qrCodeEncoder.Encode(enCodeString, Encoding.UTF8); | |||
//二维码图片的名称 | |||
string filename = orderId; | |||
if (!DirFileHelper.IsExistFile(QRCodeFile+"/Content/images/QRCode/")) | |||
{ | |||
Directory.CreateDirectory(QRCodeFile + "/Content/images/QRCode/"); | |||
} | |||
var path = QRCodeFile + "/Content/images/QRCode/" + filename + ".jpg"; | |||
//保存二维码图片在photos路径下 | |||
try | |||
{ | |||
bt.Save(path); | |||
} | |||
catch (Exception ex) | |||
{ | |||
return ""; | |||
} | |||
//图片控件要显示的二维码图片路径 | |||
return QRCodeFile + "/Content/images/QRCode/" + filename + ".jpg"; | |||
} | |||
} | |||
} |
@@ -36,6 +36,8 @@ namespace Learun.Application.WebApi.Modules | |||
Get["/weixinconfig"] = GetWeixinConfig; | |||
Post["/getweixinaccess_token"] = GetWeixinAccess_token; | |||
Post["/login"] = Login; | |||
//新生首次登陆 | |||
Post["/loginbyidcard"] = LoginByIdCard; | |||
Get["/getweixinwebaccess_token"] = GetWeixinWebaccess_token; | |||
//获取ACIp | |||
Get["/GetACIp"] = GetACIp; | |||
@@ -100,6 +102,13 @@ namespace Learun.Application.WebApi.Modules | |||
return Success(new { appid, secret }); | |||
} | |||
public class wxinfo | |||
{ | |||
public string errcode { get; set; } | |||
public string errmsg { get; set; } | |||
public string openid { get; set; } | |||
} | |||
public Response GetWeixinAccess_token(dynamic _) | |||
{ | |||
var entity = weChatConfigIbll.GetEnableEntity(); | |||
@@ -110,7 +119,7 @@ namespace Learun.Application.WebApi.Modules | |||
var responsejson = HttpGet("https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appid + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code"); | |||
if (!string.IsNullOrEmpty(responsejson)) | |||
{ | |||
var weixintokenobj = JsonConvert.DeserializeObject<dynamic>(responsejson); | |||
var weixintokenobj = JsonConvert.DeserializeObject<wxinfo>(responsejson); | |||
if (string.IsNullOrEmpty(weixintokenobj.errcode)) | |||
{ | |||
string openid = weixintokenobj.openid; | |||
@@ -241,6 +250,77 @@ namespace Learun.Application.WebApi.Modules | |||
#endregion | |||
} | |||
private Response LoginByIdCard(dynamic _) | |||
{ | |||
LoginModel loginModel = this.GetReqData<LoginModel>(); | |||
#region 内部账户验证 | |||
UserEntity userEntity = userIbll.CheckLoginByIdCard(loginModel.username, loginModel.password); | |||
#region 写入日志 | |||
LogEntity logEntity = new LogEntity(); | |||
logEntity.F_CategoryId = 1; | |||
logEntity.F_OperateTypeId = ((int)OperationType.Login).ToString(); | |||
logEntity.F_OperateType = EnumAttribute.GetDescription(OperationType.Login); | |||
logEntity.F_OperateAccount = loginModel.username + "(" + userEntity.F_RealName + ")"; | |||
logEntity.F_OperateUserId = !string.IsNullOrEmpty(userEntity.F_UserId) ? userEntity.F_UserId : loginModel.username; | |||
logEntity.F_Module = Config.GetValue("SoftName"); | |||
logEntity.F_Description = "移动端"; | |||
#endregion | |||
if (!userEntity.LoginOk)//登录失败 | |||
{ | |||
//写入日志 | |||
logEntity.F_ExecuteResult = 0; | |||
logEntity.F_ExecuteResultJson = "登录失败:" + userEntity.LoginMsg; | |||
logEntity.WriteLog(); | |||
return Fail(userEntity.LoginMsg); | |||
} | |||
else | |||
{ | |||
ReqParameter req = this.Bind<ReqParameter>(); | |||
string token = OperatorHelper.Instance.AddLoginUser(userEntity.F_Account, "Learun_ADMS_6.1_App", req.loginMark, false);//写入缓存信息 | |||
//写入日志 | |||
logEntity.F_ExecuteResult = 1; | |||
logEntity.F_ExecuteResultJson = "登录成功"; | |||
logEntity.WriteLog(); | |||
OperatorResult res = OperatorHelper.Instance.IsOnLine(token, req.loginMark); | |||
res.userInfo.password = null; | |||
res.userInfo.secretkey = null; | |||
var studententity = stuInfoBasicIBLL.GetStuInfoBasicEntityByStuNo(userEntity.F_Account); | |||
if (studententity != null) | |||
{ | |||
res.userInfo.grade = studententity.Grade; | |||
var majorinfo = majorIbll.GetCdMajorEntityByMajorNo(studententity.MajorNo); | |||
if (majorinfo != null) | |||
{ | |||
res.userInfo.majorno = majorinfo.ID ?? ""; | |||
} | |||
} | |||
//是否强密码验证 | |||
bool pwd = false; | |||
if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["verifypwd"]) && ConfigurationManager.AppSettings["verifypwd"] == "true" && loginModel.up == false) | |||
{ | |||
pwd = true; | |||
} | |||
else | |||
{ | |||
//保存用户设备号 | |||
userIbll.UpdateWeixinOpenId(userEntity.F_UserId, loginModel.openid); | |||
} | |||
var jsonData = new | |||
{ | |||
baseinfo = res.userInfo, | |||
post = postIBLL.GetListByPostIds(res.userInfo.postIds), | |||
role = roleIBLL.GetListByRoleIds(res.userInfo.roleIds), | |||
pwd = pwd | |||
}; | |||
return Success(jsonData); | |||
} | |||
#endregion | |||
} | |||
public Response GetWeixinWebaccess_token(dynamic _) | |||
{ | |||
var entity = weChatConfigIbll.GetEnableEntity(); | |||
@@ -66,6 +66,7 @@ | |||
<add key="userKey" value="14B417B0-463D-4F2B-8075-0A20EEDB773A" /> | |||
<!-- ==================注意附件上传地址 修改到主网站部署目录下的Resource要不然飞星会报错================== --> | |||
<add key="AnnexesFile" value="D:\leiprojects\西昌单校区\Learun.Application.Web\Resource" /> | |||
<add key="QRCodeFile" value="D:\leiprojects\西昌单校区\Learun.Application.Web\Content" /> | |||
<add key="ReportFile" value="~/Reports" /> | |||
<!-- ================== 工作流服务地址 ================== --> | |||
<add key="workflowapi" value="http://localhost:8013" /> | |||
@@ -30,6 +30,7 @@ | |||
<package id="Oracle.ManagedDataAccess" version="12.1.24160719" targetFramework="net45" /> | |||
<package id="Oracle.ManagedDataAccess.EntityFramework" version="12.1.2400" targetFramework="net45" /> | |||
<package id="System.ValueTuple" version="4.5.0" targetFramework="net45" requireReinstallation="true" /> | |||
<package id="ThoughtWorks.QRCode" version="1.1.0" targetFramework="net461" /> | |||
<package id="Unity" version="4.0.1" targetFramework="net45" /> | |||
<package id="WebGrease" version="1.5.2" targetFramework="net45" /> | |||
</packages> |
@@ -551,7 +551,91 @@ namespace Learun.Application.Form | |||
} | |||
} | |||
} | |||
public Dictionary<string, string> GetFolderKey(string schemeInfoId, string processIdName, string keyValue) | |||
{ | |||
Dictionary<string, DataTable> res = new Dictionary<string, DataTable>(); | |||
try | |||
{ | |||
FormSchemeInfoEntity formSchemeInfoEntity = GetSchemeInfoEntity(schemeInfoId); | |||
FormSchemeEntity formSchemeEntity = GetSchemeEntity(formSchemeInfoEntity.F_SchemeId); | |||
FormSchemeModel formSchemeModel = formSchemeEntity.F_Scheme.ToObject<FormSchemeModel>(); | |||
// 确定主从表之间的关系 | |||
List<TreeModelEx<FormTableModel>> TableTree = new List<TreeModelEx<FormTableModel>>();// 从表 | |||
foreach (var table in formSchemeModel.dbTable) | |||
{ | |||
TreeModelEx<FormTableModel> treeone = new TreeModelEx<FormTableModel>(); | |||
treeone.data = table; | |||
treeone.id = table.name; | |||
treeone.parentId = table.relationName; | |||
if (string.IsNullOrEmpty(table.relationName)) | |||
{ | |||
treeone.parentId = "0"; | |||
} | |||
TableTree.Add(treeone); | |||
} | |||
TableTree = TableTree.ToTree(); | |||
// 确定表与组件之间的关系 | |||
Dictionary<string, List<FormCompontModel>> tableComponts = new Dictionary<string, List<FormCompontModel>>(); | |||
foreach (var tab in formSchemeModel.data) | |||
{ | |||
foreach (var compont in tab.componts) | |||
{ | |||
if (!string.IsNullOrEmpty(compont.table)) | |||
{ | |||
if (!tableComponts.ContainsKey(compont.table)) | |||
{ | |||
tableComponts[compont.table] = new List<FormCompontModel>(); | |||
} | |||
if (compont.type == "upload") | |||
{ | |||
tableComponts[compont.table].Add(compont); | |||
} | |||
if (compont.type == "guid") | |||
{ | |||
tableComponts[compont.table].Add(compont); | |||
} | |||
} | |||
} | |||
} | |||
GetInstanceTableData(TableTree, tableComponts, formSchemeModel.dbId, keyValue, processIdName, null, res); | |||
Dictionary < string,string> uploadfieldkeyvalue=new Dictionary<string, string>(); | |||
foreach (var itemCompont in tableComponts) | |||
{ | |||
foreach (FormCompontModel formitem in itemCompont.Value) | |||
{ | |||
if (formitem.type=="upload") | |||
{ | |||
foreach (var resitem in res) | |||
{ | |||
if (resitem.Value.Rows.Count>0) | |||
{ | |||
if (resitem.Value.Rows[0][formitem.field] != null) | |||
uploadfieldkeyvalue.Add(formitem.id, resitem.Value.Rows[0][formitem.field].ToString()); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
return uploadfieldkeyvalue; | |||
} | |||
catch (Exception ex) | |||
{ | |||
if (ex is ExceptionEx) | |||
{ | |||
throw; | |||
} | |||
else | |||
{ | |||
throw ExceptionEx.ThrowBusinessException(ex); | |||
} | |||
} | |||
} | |||
/// <summary> | |||
/// 保存自定义表单数据 | |||
/// </summary> | |||
@@ -137,5 +137,7 @@ namespace Learun.Application.Form | |||
/// <param name="keyValue">数据主键值</param> | |||
void DeleteInstanceForm(string schemeInfoId, string keyValue); | |||
#endregion | |||
Dictionary<string, string> GetFolderKey(string itemSchemeInfoId, string itemProcessIdName, string itemKeyValue); | |||
} | |||
} |
@@ -62,7 +62,7 @@ namespace Learun.Application.TwoDevelopment.EducationalAdministration | |||
[NotMapped] public string StuCode { get; set; } | |||
[NotMapped] public string StuName { get; set; } | |||
[NotMapped] public string GenderNo { get; set; } | |||
[NotMapped] public bool? GenderNo { get; set; } | |||
[NotMapped] public string IdentityCardNo { get; set; } | |||
[NotMapped] public string DeptNo { get; set; } | |||
[NotMapped] public string MajorNo { get; set; } | |||
@@ -10,6 +10,10 @@ | |||
{ | |||
"launchtype" : "remote" | |||
}, | |||
"mp-weixin" : | |||
{ | |||
"launchtype" : "remote" | |||
}, | |||
"type" : "uniCloud" | |||
} | |||
] | |||
@@ -10,7 +10,7 @@ | |||
// H5 刷新时获取当前页面路径 | |||
const pagePath = "/" + param.path; | |||
// 如果 H5 刷新后访问的不是首页/登录页/注册页,直接跳转回首页 | |||
if (!["/pages/login", "/pages/home", "/pages/signup"].includes(pagePath)) { | |||
if (!["/pages/login", "/pages/weixinLogin","/pages/home", "/pages/signup","/pages/my/newpassword"].includes(pagePath)) { | |||
this.$nextTick(() => { | |||
this.TAB_TO("/pages/home"); | |||
return; | |||
@@ -24,274 +24,310 @@ import moment from 'moment' | |||
*/ | |||
export default { | |||
methods: { | |||
/** | |||
* 获取一个 scheme 表单项的源数据 (加载表单时使用) | |||
* 参数: 单个 schemeItem | |||
* | |||
* radio、select、checkbox、layer 这四种表单项,需要加载额外的选单数据 | |||
* 选单数据有两种获取方式: | |||
* 1、来自数据字典: | |||
* 数据字典在 this.GET_GLOBAL('dataDictionary') | |||
* 表单使用的字段在 schemeItem.itemCode | |||
* 选单数据中的 text 字段作为显示, value 字段作为值 | |||
* | |||
* 2、来自数据源: | |||
* 将 schemeItem.dataSourceId 按符号「,」逗号分割为数组,分割为: [code, displayField, valueField] | |||
* 数据源需要请求 API 来获取,请求需要带上数据源的编号 code | |||
* displayField、valueField 分别为展示字段和值绑定字段 | |||
* | |||
* 选单数据有两种格式: | |||
* 1、对于 radio、select、checkbox 来说: | |||
* 只需要一个数组,数组形如: [{ text: '选项文字', value: '选项值' }, ...] | |||
* 将获取的数据绑定到组件的 range 属性上即可 | |||
* 全局数据中默认是对象形式,使用 Object.values() 转化即可 | |||
* | |||
* 2、对于 layer 来说: | |||
* 返回一个对象,形如 { source, layerData, selfField } | |||
* source: 为弹层中列出的数据,是一个数组 | |||
* layerData: 需要在弹层窗口中展示的字段及标题文字,形如: [{ name:'要展示的字段名', label:'标题文字' }] | |||
* selfField: 该表单值绑定哪个字段,默认为绑定到自身的字段 | |||
*/ | |||
async getSourceData(schemeItem) { | |||
if (['radio', 'select', 'checkbox'].includes(schemeItem.type)) { | |||
// radio select checkbox 三种情况 | |||
if (!schemeItem.dataSource || Number(schemeItem.dataSource) === 0) { | |||
// dataSource 为 0,使用 clientData | |||
return Object | |||
.values(this.GET_GLOBAL('dataDictionary')[schemeItem.itemCode]) | |||
.map(t => ({ value: t.value, text: t.text })) | |||
} else { | |||
// dataSource 不为 0,使用数据源,需要请求接口,并且提取出显示字段和实际字段 | |||
const [code, displayField = schemeItem.showField, valueField = schemeItem.saveField] = schemeItem.dataSourceId | |||
.split(',') | |||
const sourceData = await this.FETCH_DATASOURCE(code) | |||
if (!sourceData) { return [] } | |||
return sourceData.data.map(t => ({ text: t[displayField], value: t[valueField] })) | |||
} | |||
} else if (['layer'].includes(schemeItem.type)) { | |||
// layer 需要更多属性 | |||
if (!schemeItem.dataSource || Number(schemeItem.dataSource) === 0) { | |||
// dataSource 为 0,使用 clientData | |||
// clientData 对象转数组后,隐含 key:item.text 和 value:item.value 的关系 | |||
const [keyItem, valueItem] = schemeItem.layerData | |||
const source = Object | |||
.values(this.GET_GLOBAL('dataDictionary')[schemeItem.itemCode]) | |||
.map(t => ({ value: t.value, text: t.text })) | |||
return { | |||
source, | |||
layerData: [ | |||
{ name: 'text', label: keyItem.label || '', value: keyItem.value || '' }, | |||
{ name: 'value', label: valueItem.label || '', value: valueItem.value || '' } | |||
] | |||
} | |||
} else { | |||
// dataSource 不为 0,使用数据源,需要请求接口,并且提取出显示字段和实际字段 | |||
const [code] = schemeItem.dataSourceId.split(',') | |||
const sourceData = await this.FETCH_DATASOURCE(code) | |||
if (!sourceData) { return [] } | |||
const source = sourceData.data | |||
return { source, layerData: schemeItem.layerData.filter(t => (!t.hide) && (t.value || t.label)) } | |||
} | |||
} | |||
return [] | |||
}, | |||
/** | |||
* 获取一个 scheme 表单项的默认值 (用户新建表单时使用,或是编辑草稿) | |||
* 参数: 单个 schemeItem , { processId } | |||
* | |||
* 每种类别的表单项分别获取的默认值: | |||
* | |||
* currentInfo: 根据类别取当前用户/部门/公司/时间日期 | |||
* datetime: 根据 dfValue 字段表示昨天/今天/明天,格式化为字符串 | |||
* radio、select: 有 dfValue 则使用,否则取第一条 | |||
* checkbox: 有 dfValue 则使用,否则为空数组 | |||
* encode: 根据 rulecode 请求表单编码 | |||
* upload: 空数组 | |||
* guid: 赋值第二个参数中的 processId,但是如果在子表格中,赋空字符串 | |||
* girdtable: 递归所有表格项 scheme 依次为它们生成默认值 | |||
* datetimerange: 字符串 0 | |||
*/ | |||
async getDefaultData(item, prop) { | |||
const { processId } = prop | |||
switch (item.type) { | |||
case 'currentInfo': | |||
switch (item.dataType) { | |||
case 'user': | |||
return this.GET_GLOBAL('loginUser').userId | |||
case 'department': | |||
return this.GET_GLOBAL('loginUser').departmentId | |||
case 'company': | |||
return this.GET_GLOBAL('loginUser').companyId | |||
case 'time': | |||
return moment().format('YYYY-MM-DD HH:mm:ss') | |||
default: | |||
return '' | |||
} | |||
case 'datetime': | |||
const datetimeFormat = item.table ? | |||
(Number(item.dateformat) === 0 ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss') : | |||
(item.datetime === 'datetime' ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD') | |||
const today = moment() | |||
const dfDatetime = [ | |||
today.subtract(1, 'day'), | |||
today, | |||
today.add(1, 'day') | |||
][Number(item.dfvalue)] || today | |||
return dfDatetime.format(datetimeFormat) || '' | |||
case 'radio': | |||
case 'select': | |||
const radioItem = item.__sourceData__.find(t => t.value === item.dfvalue) || item.__sourceData__[0] | |||
return item.type === 'radio' ? radioItem.value : '' | |||
case 'checkbox': | |||
if (!item.dfvalue) { | |||
return [] | |||
} | |||
return item.dfvalue.split(',').filter(t => item.__sourceData__.find(s => s.value === t)) | |||
case 'encode': | |||
const result = await this.FETCH_ENCODE(item.rulecode) | |||
return result | |||
case 'upload': | |||
return [] | |||
case 'guid': | |||
return item.table ? processId : '' | |||
case 'girdtable': | |||
const tableItemObj = {} | |||
for (const fieldItem of item.fieldsData) { | |||
tableItemObj[fieldItem.field] = await this.getDefaultData(fieldItem, prop) | |||
} | |||
return this.COPY(tableItemObj) | |||
case 'datetimerange': | |||
return '0' | |||
default: | |||
return item.dfvalue || '' | |||
} | |||
}, | |||
/** | |||
* 将单条 formData 值转化为 formValue 值 (拉取表单数据时使用) | |||
* 参数: 单个 schemeItem , 数据值 | |||
* | |||
* 具体执行逻辑: | |||
* radio、select: 剔除无效值 | |||
* checkbox: 分割成数组并剔除无效值 | |||
* upload: 分割成数组,拉取其中所有文件的信息 | |||
* datetime: 按照时间日期格式进行格式化字符串 | |||
* 其他类型: 保留原值 | |||
*/ | |||
async convertToFormValue(item, val) { | |||
switch (item.type) { | |||
case 'upload': | |||
if (!val) { return [] } | |||
const uidList = val.split(',') | |||
const fileList = [] | |||
for (const uid of uidList || []) { | |||
const fileInfo = await this.FETCH_FILEINFO(uid) | |||
if (!fileInfo) { continue } | |||
const fileType = fileInfo.F_FileType | |||
const fileSize = fileInfo.F_FileSize | |||
const path = this.API + '/learun/adms/annexes/wxdown?' + this.URL_QUERY(uid, true) | |||
fileList.push({ path, type: fileType, uid, size: fileSize }) | |||
} | |||
return fileList | |||
case 'select': | |||
case 'radio': | |||
if (!val || !item.__sourceData__.map(t => t.value).includes(val)) { | |||
return '' | |||
} | |||
return val | |||
case 'checkbox': | |||
const validValue = item.__sourceData__.map(t => t.value) | |||
const checkboxVal = val.split(',') || [] | |||
return checkboxVal.filter(t => validValue.includes(t)) | |||
case 'datetime': | |||
if (!val) { | |||
return '' | |||
} | |||
return moment(val).format( | |||
Number(item.dateformat) === 0 || item.datetime === 'date' ? | |||
'YYYY-MM-DD' : | |||
'YYYY-MM-DD HH:mm:ss' | |||
) | |||
default: | |||
return val || '' | |||
} | |||
}, | |||
/** | |||
* 将一个 formValue 值转化为 post 提交值(提交表单数据时使用) | |||
* 参数: 单个 schemeItem , 表单项值 , 所有 formValue , scheme | |||
* | |||
* 具体执行逻辑: | |||
* checkbox: 将数组使用符号「,」逗号拼接成字符串 | |||
* datetimerange: 获取开始日期、结束日期,计算差值天数并保留整数 | |||
* datetime: 格式化为完整时间日期字符串 | |||
* upload: 依次上传文件,将返回的文件 ID 使用符号「,」逗号拼接成字符串 | |||
* 其他类型: 保留原值 | |||
*/ | |||
async convertToPostData(item, val, formValue, scheme) { | |||
switch (item.type) { | |||
case 'checkbox': | |||
return val ? val.join(',') : '' | |||
case 'datetimerange': | |||
const startTime = get(formValue, scheme.find(t => t.id === item.startTime).__valuePath__, null) | |||
const endTime = get(formValue, scheme.find(t => t.id === item.endTime).__valuePath__, null) | |||
if (!startTime || !endTime || moment(endTime).isBefore(startTime)) { | |||
return '' | |||
} else { | |||
return moment.duration(moment(endTime).diff(moment(startTime))).asDays().toFixed(0) | |||
} | |||
case 'datetime': | |||
return val ? moment(val).format('YYYY-MM-DD HH:mm:ss') : '' | |||
case 'upload': | |||
const uploadUid = [] | |||
// { path, uid } | |||
for (const item of val) { | |||
if (item.uid) { | |||
uploadUid.push(item.uid) | |||
continue | |||
} | |||
const fileId = await this.HTTP_UPLOAD(item.path||item) | |||
if (fileId) { | |||
uploadUid.push(fileId) | |||
} | |||
} | |||
return uploadUid.join(',') | |||
default: | |||
return val || '' | |||
} | |||
} | |||
} | |||
methods: { | |||
/** | |||
* 获取一个 scheme 表单项的源数据 (加载表单时使用) | |||
* 参数: 单个 schemeItem | |||
* | |||
* radio、select、checkbox、layer 这四种表单项,需要加载额外的选单数据 | |||
* 选单数据有两种获取方式: | |||
* 1、来自数据字典: | |||
* 数据字典在 this.GET_GLOBAL('dataDictionary') | |||
* 表单使用的字段在 schemeItem.itemCode | |||
* 选单数据中的 text 字段作为显示, value 字段作为值 | |||
* | |||
* 2、来自数据源: | |||
* 将 schemeItem.dataSourceId 按符号「,」逗号分割为数组,分割为: [code, displayField, valueField] | |||
* 数据源需要请求 API 来获取,请求需要带上数据源的编号 code | |||
* displayField、valueField 分别为展示字段和值绑定字段 | |||
* | |||
* 选单数据有两种格式: | |||
* 1、对于 radio、select、checkbox 来说: | |||
* 只需要一个数组,数组形如: [{ text: '选项文字', value: '选项值' }, ...] | |||
* 将获取的数据绑定到组件的 range 属性上即可 | |||
* 全局数据中默认是对象形式,使用 Object.values() 转化即可 | |||
* | |||
* 2、对于 layer 来说: | |||
* 返回一个对象,形如 { source, layerData, selfField } | |||
* source: 为弹层中列出的数据,是一个数组 | |||
* layerData: 需要在弹层窗口中展示的字段及标题文字,形如: [{ name:'要展示的字段名', label:'标题文字' }] | |||
* selfField: 该表单值绑定哪个字段,默认为绑定到自身的字段 | |||
*/ | |||
async getSourceData(schemeItem) { | |||
if (['radio', 'select', 'checkbox'].includes(schemeItem.type)) { | |||
// radio select checkbox 三种情况 | |||
if (!schemeItem.dataSource || Number(schemeItem.dataSource) === 0) { | |||
// dataSource 为 0,使用 clientData | |||
return Object | |||
.values(this.GET_GLOBAL('dataDictionary')[schemeItem.itemCode]) | |||
.map(t => ({ | |||
value: t.value, | |||
text: t.text | |||
})) | |||
} else { | |||
// dataSource 不为 0,使用数据源,需要请求接口,并且提取出显示字段和实际字段 | |||
const [code, displayField = schemeItem.showField, valueField = schemeItem.saveField] = | |||
schemeItem.dataSourceId | |||
.split(',') | |||
const sourceData = await this.FETCH_DATASOURCE(code) | |||
if (!sourceData) { | |||
return [] | |||
} | |||
return sourceData.data.map(t => ({ | |||
text: t[displayField], | |||
value: t[valueField] | |||
})) | |||
} | |||
} else if (['layer'].includes(schemeItem.type)) { | |||
// layer 需要更多属性 | |||
if (!schemeItem.dataSource || Number(schemeItem.dataSource) === 0) { | |||
// dataSource 为 0,使用 clientData | |||
// clientData 对象转数组后,隐含 key:item.text 和 value:item.value 的关系 | |||
const [keyItem, valueItem] = schemeItem.layerData | |||
const source = Object | |||
.values(this.GET_GLOBAL('dataDictionary')[schemeItem.itemCode]) | |||
.map(t => ({ | |||
value: t.value, | |||
text: t.text | |||
})) | |||
return { | |||
source, | |||
layerData: [{ | |||
name: 'text', | |||
label: keyItem.label || '', | |||
value: keyItem.value || '' | |||
}, | |||
{ | |||
name: 'value', | |||
label: valueItem.label || '', | |||
value: valueItem.value || '' | |||
} | |||
] | |||
} | |||
} else { | |||
// dataSource 不为 0,使用数据源,需要请求接口,并且提取出显示字段和实际字段 | |||
const [code] = schemeItem.dataSourceId.split(',') | |||
const sourceData = await this.FETCH_DATASOURCE(code) | |||
if (!sourceData) { | |||
return [] | |||
} | |||
const source = sourceData.data | |||
return { | |||
source, | |||
layerData: schemeItem.layerData.filter(t => (!t.hide) && (t.value || t.label)) | |||
} | |||
} | |||
} | |||
return [] | |||
}, | |||
/** | |||
* 获取一个 scheme 表单项的默认值 (用户新建表单时使用,或是编辑草稿) | |||
* 参数: 单个 schemeItem , { processId } | |||
* | |||
* 每种类别的表单项分别获取的默认值: | |||
* | |||
* currentInfo: 根据类别取当前用户/部门/公司/时间日期 | |||
* datetime: 根据 dfValue 字段表示昨天/今天/明天,格式化为字符串 | |||
* radio、select: 有 dfValue 则使用,否则取第一条 | |||
* checkbox: 有 dfValue 则使用,否则为空数组 | |||
* encode: 根据 rulecode 请求表单编码 | |||
* upload: 空数组 | |||
* guid: 赋值第二个参数中的 processId,但是如果在子表格中,赋空字符串 | |||
* girdtable: 递归所有表格项 scheme 依次为它们生成默认值 | |||
* datetimerange: 字符串 0 | |||
*/ | |||
async getDefaultData(item, prop) { | |||
const { | |||
processId | |||
} = prop | |||
switch (item.type) { | |||
case 'currentInfo': | |||
switch (item.dataType) { | |||
case 'user': | |||
return this.GET_GLOBAL('loginUser').userId | |||
case 'department': | |||
return this.GET_GLOBAL('loginUser').departmentId | |||
case 'company': | |||
return this.GET_GLOBAL('loginUser').companyId | |||
case 'time': | |||
return moment().format('YYYY-MM-DD HH:mm:ss') | |||
default: | |||
return '' | |||
} | |||
case 'datetime': | |||
const datetimeFormat = item.table ? | |||
(Number(item.dateformat) === 0 ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss') : | |||
(item.datetime === 'datetime' ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD') | |||
const today = moment() | |||
const dfDatetime = [ | |||
today.subtract(1, 'day'), | |||
today, | |||
today.add(1, 'day') | |||
][Number(item.dfvalue)] || today | |||
return dfDatetime.format(datetimeFormat) || '' | |||
case 'radio': | |||
case 'select': | |||
const radioItem = item.__sourceData__.find(t => t.value === item.dfvalue) || item | |||
.__sourceData__[0] | |||
return item.type === 'radio' ? radioItem.value : '' | |||
case 'checkbox': | |||
if (!item.dfvalue) { | |||
return [] | |||
} | |||
return item.dfvalue.split(',').filter(t => item.__sourceData__.find(s => s.value === t)) | |||
case 'encode': | |||
const result = await this.FETCH_ENCODE(item.rulecode) | |||
return result | |||
case 'upload': | |||
return [] | |||
case 'guid': | |||
return item.table ? processId : '' | |||
case 'girdtable': | |||
const tableItemObj = {} | |||
for (const fieldItem of item.fieldsData) { | |||
tableItemObj[fieldItem.field] = await this.getDefaultData(fieldItem, prop) | |||
} | |||
return this.COPY(tableItemObj) | |||
case 'datetimerange': | |||
return '0' | |||
default: | |||
return item.dfvalue || '' | |||
} | |||
}, | |||
/** | |||
* 将单条 formData 值转化为 formValue 值 (拉取表单数据时使用) | |||
* 参数: 单个 schemeItem , 数据值 | |||
* | |||
* 具体执行逻辑: | |||
* radio、select: 剔除无效值 | |||
* checkbox: 分割成数组并剔除无效值 | |||
* upload: 分割成数组,拉取其中所有文件的信息 | |||
* datetime: 按照时间日期格式进行格式化字符串 | |||
* 其他类型: 保留原值 | |||
*/ | |||
async convertToFormValue(item, val) { | |||
switch (item.type) { | |||
case 'upload': | |||
if (!val) { | |||
return [] | |||
} | |||
const uidList = val; | |||
const fileList = [] | |||
const wxlist = await this.FETCH_FILEList(uidList); | |||
for (const wxfile of wxlist) { | |||
const fileInfo = await this.FETCH_FILEINFO(wxfile.F_Id) | |||
if (!fileInfo) { | |||
continue | |||
} | |||
const fileType = fileInfo.F_FileType | |||
const fileSize = fileInfo.F_FileSize | |||
const path = this.API + '/learun/adms/annexes/wxdown?' + this.URL_QUERY(wxfile.F_Id, true) | |||
fileList.push({ | |||
path, | |||
type: fileType, | |||
uid:wxfile.F_Id, | |||
folderId:wxfile.F_FolderId, | |||
size: fileSize | |||
}) | |||
} | |||
return fileList | |||
case 'select': | |||
case 'radio': | |||
if (!val || !item.__sourceData__.map(t => t.value).includes(val)) { | |||
return '' | |||
} | |||
return val | |||
case 'checkbox': | |||
const validValue = item.__sourceData__.map(t => t.value) | |||
const checkboxVal = val.split(',') || [] | |||
return checkboxVal.filter(t => validValue.includes(t)) | |||
case 'datetime': | |||
if (!val) { | |||
return '' | |||
} | |||
return moment(val).format( | |||
Number(item.dateformat) === 0 || item.datetime === 'date' ? | |||
'YYYY-MM-DD' : | |||
'YYYY-MM-DD HH:mm:ss' | |||
) | |||
default: | |||
return val || '' | |||
} | |||
}, | |||
/** | |||
* 将一个 formValue 值转化为 post 提交值(提交表单数据时使用) | |||
* 参数: 单个 schemeItem , 表单项值 , 所有 formValue , scheme | |||
* | |||
* 具体执行逻辑: | |||
* checkbox: 将数组使用符号「,」逗号拼接成字符串 | |||
* datetimerange: 获取开始日期、结束日期,计算差值天数并保留整数 | |||
* datetime: 格式化为完整时间日期字符串 | |||
* upload: 依次上传文件,将返回的文件 ID 使用符号「,」逗号拼接成字符串 | |||
* 其他类型: 保留原值 | |||
*/ | |||
async convertToPostData(item, val, formValue, scheme, guid) { | |||
switch (item.type) { | |||
case 'checkbox': | |||
return val ? val.join(',') : '' | |||
case 'datetimerange': | |||
const startTime = get(formValue, scheme.find(t => t.id === item.startTime).__valuePath__, null) | |||
const endTime = get(formValue, scheme.find(t => t.id === item.endTime).__valuePath__, null) | |||
if (!startTime || !endTime || moment(endTime).isBefore(startTime)) { | |||
return '' | |||
} else { | |||
return moment.duration(moment(endTime).diff(moment(startTime))).asDays().toFixed(0) | |||
} | |||
case 'datetime': | |||
return val ? moment(val).format('YYYY-MM-DD HH:mm:ss') : '' | |||
case 'upload': | |||
var uploadUid = ''; | |||
for (const item of val) { | |||
if (item.uid) { | |||
uploadUid = item.uid | |||
continue | |||
} | |||
const fileId = await this.HTTP_UPLOAD(item.path || item, undefined, guid || '') | |||
if (fileId) { | |||
uploadUid = fileId; | |||
} | |||
} | |||
return uploadUid; | |||
default: | |||
return val || '' | |||
} | |||
} | |||
} | |||
} |
@@ -1,3 +1,4 @@ | |||
import { conforms } from 'lodash' | |||
import get from 'lodash/get' | |||
import omit from 'lodash/omit' | |||
import moment from 'moment' | |||
@@ -233,7 +234,11 @@ export default { | |||
} else { | |||
for (const [fieldName, scheme] of Object.entries(schemeItem)) { | |||
const dataSource = get(this.dataSource, `${tableName}.${fieldName}`) | |||
data[tableName][fieldName] = await this.convertToFormValue(scheme, data[tableName][fieldName], dataSource) | |||
if(data[tableName]){ | |||
data[tableName][fieldName] = await this.convertToFormValue(scheme, data[tableName][fieldName], dataSource) | |||
}else{ | |||
this.scheme[tableName][fieldName] = await this.convertToFormValue(scheme, this.scheme[tableName][fieldName], dataSource) | |||
} | |||
} | |||
} | |||
} | |||
@@ -257,7 +262,6 @@ export default { | |||
const fileSize = fileInfo.F_FileSize | |||
const path = this.API + '/learun/adms/annexes/wxdown?' + this.URL_QUERY(uid, true) | |||
fileList.push({ path, type: fileType, uid, size: fileSize }) | |||
} | |||
return fileList | |||
@@ -229,6 +229,14 @@ export default { | |||
return await this.HTTP_GET('learun/adms/annexes/wxfileinfo', fileId) | |||
}, | |||
//获取文件夹下文件列表 | |||
async FETCH_FILEList(folderId) { | |||
if (!folderId) { | |||
return null | |||
} | |||
return await this.HTTP_GET('learun/adms/annexes/wxlist', folderId) | |||
}, | |||
// 封装的 GET 请求,集成了验证信息 | |||
// 返回请求结果或 null | |||
@@ -258,8 +266,8 @@ export default { | |||
// url 为请求地址 | |||
// filePath 为临时文件的路径 | |||
// formData 为请求附带的提交数据 | |||
async HTTP_UPLOAD(filePath, formData) { | |||
const [err, res] = await this.UPLOAD('/learun/adms/annexes/wxupload', filePath, formData) | |||
async HTTP_UPLOAD(filePath, formData,guid) { | |||
const [err, res] = await this.UPLOAD('/learun/adms/annexes/wxupload', filePath, formData,guid) | |||
return this.handleResult(err, res) | |||
}, | |||
@@ -308,11 +316,12 @@ export default { | |||
// 返回结果是一个数组: [error, result] | |||
// error 表示错误,一般是网络错误,请求很可能根本没有发出 | |||
// result 包含 { statusCode, data } 分别表示状态码、接口返回的数据 | |||
async UPLOAD(url, filePath, formData) { | |||
async UPLOAD(url, filePath, formData,guid) { | |||
const uploadUrl = this.handleUrl(url) | |||
const query = { | |||
loginMark: this.getLoginMark(), | |||
token: this.GET_GLOBAL('token') | |||
token: this.GET_GLOBAL('token'), | |||
folderId:guid | |||
} | |||
if (formData && typeof formData === 'object') { | |||
@@ -683,13 +692,13 @@ export default { | |||
if(result.data.code != 200){ | |||
uni.hideLoading() | |||
uni.showToast({ | |||
title: tips||result.data.info||"未知错误", | |||
title: result.data.info, | |||
icon: 'none' | |||
}) | |||
return null | |||
} | |||
return result.data.data||true | |||
return result.data.data | |||
}, | |||
// 【即将废弃】请使用 this.CONFIG() 来替代 | |||
@@ -194,12 +194,14 @@ export default { | |||
// 依次验证表单项,返回一个所有错误提示的数组,如果为空数组则表示无错误 | |||
verifyValue() { | |||
const errorList = [] | |||
console.log(this.scheme) | |||
this.scheme | |||
.filter(t => t.verify) | |||
.forEach(schemeItem => { | |||
if (schemeItem.table && schemeItem.field) { | |||
console.log(schemeItem.verify,'hemeItem.verify') | |||
const verifyFunc = this.verify[schemeItem.verify] | |||
console.log(schemeItem.verify) | |||
const verifyResult = verifyFunc(this.getValue(schemeItem.__valuePath__)) | |||
if (verifyResult !== true) { | |||
errorList.push(`[${schemeItem.title}]: ${verifyResult}`) | |||
@@ -304,7 +306,8 @@ export default { | |||
MobileOrPhoneOrNull: t => | |||
t.length <= 0 || /^1[0-9]{10}$/.test(t) || /^[+0-9- ]*$/.test(t) || '须留空或符合手机/电话号码格式', | |||
Uri: t => /^[a-zA-z]+:\/\/[^\s]*$/.test(t) || '须符合网址Url格式', | |||
UriOrNull: t => t.length <= 0 || /^[a-zA-z]+:\/\/[^\s]*$/.test(t) || '须留空或符合网址Url格式' | |||
UriOrNull: t => t.length <= 0 || /^[a-zA-z]+:\/\/[^\s]*$/.test(t) || '须留空或符合网址Url格式', | |||
PositiveFloatint:t=> /^([1-9]\d*|(0|[1-9]\d*)\.\d*[1-9])$/.test(t) || '请输入正确的整数或小数(不能为零和负数)' | |||
} | |||
} | |||
} | |||
@@ -89,7 +89,7 @@ export default { | |||
// #endif | |||
// #ifndef MP-DINGTALK | |||
uni.chooseImage({ | |||
uni.chooseFile({ | |||
count: Number(this.number), | |||
sizeType: ['original', 'compressed'], | |||
sourceType: ['album', 'camera'], | |||
@@ -1,296 +1,293 @@ | |||
<template> | |||
<view class="cu-form-group"> | |||
<view class="grid col-4 grid-square flex-sub"> | |||
<view | |||
v-for="(item, index) in imgList" | |||
@tap="viewImg(item)" | |||
:key="index" | |||
class="bg-img" | |||
> | |||
<!-- {{API + '/user/img?data=' + (path.path ? path.path : path)}} --> | |||
<image | |||
v-if="showfile()&&isImage(item.type)" | |||
:src="CONFIG('webHost') + item.url" | |||
mode="aspectFill" | |||
></image> | |||
<l-icon v-if="showfile()&&!isImage(item.type)" type="text" /> | |||
<text class="file-name">{{item.name}}</text> | |||
<view v-if="!readonly" @tap.stop="delImg(index)" class="cu-tag bg-red" style="width: 18px; height: 18px; font-size: 24px"> | |||
<l-icon | |||
type="close" | |||
style="width: 18px; height: 18px; font-size: 12px" | |||
/> | |||
</view> | |||
</view> | |||
<view class="cu-form-group"> | |||
<view class="grid col-4 grid-square flex-sub"> | |||
<view v-for="(item, index) in imgList" @tap="viewImg(item)" :key="index" class="bg-img"> | |||
<image v-if="showfile()&&isImage(item.type)" :src="CONFIG('webHost') + item.url" mode="aspectFill"> | |||
</image> | |||
<l-icon v-if="showfile()&&!isImage(item.type)" type="text" /> | |||
<text class="file-name">{{item.name}}</text> | |||
<view v-if="!readonly" @tap.stop="delImg(index)" class="cu-tag bg-red" | |||
style="width: 18px; height: 18px; font-size: 24px"> | |||
<l-icon type="close" style="width: 18px; height: 18px; font-size: 12px" /> | |||
</view> | |||
</view> | |||
<view v-show="!readonly && imgList.length < Number(number)&&isShow" class="solids"> | |||
<!-- @tap="chooseImg" --> | |||
<l-icon type="file" /> | |||
<lsj-upload ref="lsjUpload" height="80px" width="100%" :size="20" :option="{}" :count="1" | |||
@change="chooseChange" style="opacity: 0;"></lsj-upload> | |||
</view> | |||
</view> | |||
</view> | |||
<view | |||
v-show="!readonly && imgList.length < Number(number)&&isShow" | |||
class="solids" | |||
> | |||
<!-- @tap="chooseImg" --> | |||
<l-icon type="file" /> | |||
<lsj-upload | |||
ref="lsjUpload" | |||
height="80px" | |||
width="100%" | |||
:size="20" | |||
:option="{}" | |||
:count="1" | |||
@change="chooseChange" | |||
style="opacity: 0;" | |||
></lsj-upload> | |||
</view> | |||
</view> | |||
</view> | |||
</template> | |||
<script> | |||
export default { | |||
export default { | |||
props: { | |||
number: { default: 1 }, | |||
readonly: {}, | |||
value: { default: () => [] }, | |||
folderId:{}, | |||
}, | |||
data(){ | |||
return{ | |||
isShow:false, | |||
imgList:[], | |||
} | |||
}, | |||
props: { | |||
number: { | |||
default: 1 | |||
}, | |||
readonly: {}, | |||
value: { | |||
default: () => [] | |||
}, | |||
folderId: {}, | |||
}, | |||
methods: { | |||
chooseChange(files){ | |||
let array = Array.from(files); | |||
if(array.length){ | |||
this.$refs.lsjUpload.clear() | |||
} | |||
let tempFilePaths = [],tempFiles=[]; | |||
array.forEach(item=>{ | |||
tempFilePaths.push(item[1].path) | |||
tempFiles.push(item[1].file) | |||
}) | |||
this.chooseChangeback(tempFilePaths,tempFiles) | |||
}, | |||
delImg(index) { | |||
this.LOADING('正在删除…'); | |||
const newList = JSON.parse(JSON.stringify(this.imgList)); | |||
this.HTTP_POST('StuInfoFresh/deleteFiles', {id:this.imgList[index].id},"文件删除失败").then((data) => { | |||
this.HIDE_LOADING(); | |||
if (data) { | |||
newList.splice(index, 1); | |||
this.imgList = newList | |||
this.$emit("update:value", newList); | |||
this.$emit("input", newList); | |||
this.$emit("change"); | |||
this.$emit("del"); | |||
data() { | |||
return { | |||
isShow: false, | |||
imgList: [], | |||
} | |||
}) | |||
}, | |||
showfile() { | |||
return true; | |||
}, | |||
async chooseChangeback(tempFilePaths,tempFiles) { | |||
// let {tempFilePaths,tempFiles} = res | |||
// if(!this.validate(tempFiles))return | |||
let uploadImageRes = await this.uploadImage(tempFilePaths[0],tempFiles[0]?tempFiles[0].name:"") | |||
let newList = this.imgList || [] | |||
if(uploadImageRes){ | |||
newList = JSON.parse(JSON.stringify(newList)).concat(uploadImageRes); | |||
} | |||
this.imgList = newList | |||
this.$emit("update:value", newList); | |||
this.$emit("input", newList); | |||
this.$emit("change",newList); | |||
this.$emit("add"); | |||
}, | |||
uploadImage(url,name){ | |||
if(!url)return | |||
// 文件上传 | |||
return new Promise(async (reslove,reject)=>{ | |||
this.LOADING('正在上传…'); | |||
let params = name?{folderId:this.folderId,name}:{folderId:this.folderId} | |||
this.HTTP_UPLOAD2('StuInfoFresh/upload', url,params).then((data) => { | |||
this.HIDE_LOADING(); | |||
this.$refs.lsjUpload.show() | |||
if (data) { | |||
// this.HTTP_GET('StuInfoFresh/upload', {fileId:data}) | |||
reslove([{ | |||
id:data.F_Id, | |||
name:data.F_FileName, | |||
url:data.F_FilePath, | |||
type:data.F_FileType, | |||
}]) | |||
}else{ | |||
reject('上传失败!') | |||
}, | |||
methods: { | |||
chooseChange(files) { | |||
let array = Array.from(files); | |||
if (array.length) { | |||
this.$refs.lsjUpload.clear() | |||
} | |||
}) | |||
}) | |||
}, | |||
ceshi(){ | |||
function apiFn(params){ | |||
return new Promise((resolve,reject)=>{ | |||
this.LOADING('正在上传…'); | |||
this.HTTP_UPLOAD2('StuInfoFresh/upload', params.url,{folderId:this.folderId}).then((data) => { | |||
this.HIDE_LOADING(); | |||
if (data) { | |||
// this.HTTP_GET('StuInfoFresh/upload', {fileId:data}) | |||
this.imgList[params.index] = [{ | |||
id:data.F_Id, | |||
name:data.F_FileName, | |||
url:data.F_FilePath, | |||
type:data.F_FileType | |||
}] | |||
reslove(this.imgList[params.index]) | |||
}else{ | |||
reject('上传失败!') | |||
let tempFilePaths = [], | |||
tempFiles = []; | |||
array.forEach(item => { | |||
tempFilePaths.push(item[1].path) | |||
tempFiles.push(item[1].file) | |||
}) | |||
this.chooseChangeback(tempFilePaths, tempFiles) | |||
}, | |||
delImg(index) { | |||
this.CONFIRM("", "是否确认删除?", true).then(res => { | |||
if(!res)return | |||
this.LOADING('正在删除…'); | |||
const newList = JSON.parse(JSON.stringify(this.imgList)); | |||
this.HTTP_POST('StuInfoFresh/deleteFiles', { | |||
id: this.imgList[index].id | |||
}, "文件删除失败").then((data) => { | |||
this.HIDE_LOADING(); | |||
if (data) { | |||
newList.splice(index, 1); | |||
this.imgList = newList | |||
this.$emit("update:value", newList); | |||
this.$emit("input", newList); | |||
this.$emit("change"); | |||
this.$emit("del"); | |||
} | |||
}) | |||
}) | |||
}, | |||
showfile() { | |||
return true; | |||
}, | |||
async chooseChangeback(tempFilePaths, tempFiles) { | |||
// let {tempFilePaths,tempFiles} = res | |||
// if(!this.validate(tempFiles))return | |||
let uploadImageRes = await this.uploadImage(tempFilePaths[0], tempFiles[0] ? tempFiles[0].name : "") | |||
let newList = this.imgList || [] | |||
if (uploadImageRes) { | |||
newList = JSON.parse(JSON.stringify(newList)).concat(uploadImageRes); | |||
} | |||
this.imgList = newList | |||
this.$emit("update:value", newList); | |||
this.$emit("input", newList); | |||
this.$emit("change", newList); | |||
// this.$emit("add"); | |||
}, | |||
uploadImage(url, name) { | |||
if (!url) return | |||
// 文件上传 | |||
return new Promise(async (reslove, reject) => { | |||
this.LOADING('正在上传…'); | |||
let params = name ? { | |||
folderId: this.folderId, | |||
name | |||
} : { | |||
folderId: this.folderId | |||
} | |||
this.HTTP_UPLOAD2('StuInfoFresh/upload', url, params).then((data) => { | |||
this.HIDE_LOADING(); | |||
this.$refs.lsjUpload.show() | |||
if (data) { | |||
// this.HTTP_GET('StuInfoFresh/upload', {fileId:data}) | |||
reslove([{ | |||
id: data.F_Id, | |||
name: data.F_FileName, | |||
url: data.F_FilePath, | |||
type: data.F_FileType, | |||
}]) | |||
} else { | |||
reject('上传失败!') | |||
} | |||
}) | |||
}) | |||
}) | |||
} | |||
let array = this.imgList.map(item=>{ | |||
if(item.id){ | |||
return "" | |||
}else{ | |||
return { | |||
url:"learun/adms/annexes/upload" | |||
}, | |||
ceshi() { | |||
function apiFn(params) { | |||
return new Promise((resolve, reject) => { | |||
this.LOADING('正在上传…'); | |||
this.HTTP_UPLOAD2('StuInfoFresh/upload', params.url, { | |||
folderId: this.folderId | |||
}).then((data) => { | |||
this.HIDE_LOADING(); | |||
if (data) { | |||
// this.HTTP_GET('StuInfoFresh/upload', {fileId:data}) | |||
this.imgList[params.index] = [{ | |||
id: data.F_Id, | |||
name: data.F_FileName, | |||
url: data.F_FilePath, | |||
type: data.F_FileType | |||
}] | |||
reslove(this.imgList[params.index]) | |||
} else { | |||
reject('上传失败!') | |||
} | |||
}) | |||
}) | |||
} | |||
} | |||
}) | |||
this.promiseAllLimit(2,[1,2,3,4,5,6,7,8,9],a).then(res=>{ | |||
console.log(res) | |||
}) | |||
}, | |||
/** | |||
* @description 控制promise.all并发数量 | |||
* @param limit 并发数 | |||
* @param array 参数列表 | |||
* @param apiFn 执行函数 | |||
* @returns {Promise<Awaited<unknown>[]>} | |||
*/ | |||
async promiseAllLimit(limit, array, apiFn) { | |||
const ret = [] // 用于存放所有的promise实例 | |||
const executing = [] // 用于存放目前正在执行的promise | |||
for (const item of array) { | |||
const p = apiFn(item) | |||
ret.push(p) | |||
if (limit <= array.length) { | |||
// then回调中,当这个promise状态变为fulfilled后,将其从正在执行的promise列表executing中删除 | |||
const e = p.then(() => executing.splice(executing.indexOf(e), 1)) | |||
executing.push(e) | |||
if (executing.length >= limit) { | |||
// 一旦正在执行的promise列表数量等于限制数,就使用Promise.race等待某一个promise状态发生变更, | |||
// 状态变更后,就会执行上面then的回调,将该promise从executing中删除, | |||
// 然后再进入到下一次for循环,生成新的promise进行补充 | |||
await Promise.race(executing) | |||
let array = this.imgList.map(item => { | |||
if (item.id) { | |||
return "" | |||
} else { | |||
return { | |||
url: "learun/adms/annexes/upload" | |||
} | |||
} | |||
}) | |||
this.promiseAllLimit(2, [1, 2, 3, 4, 5, 6, 7, 8, 9], a).then(res => { | |||
console.log(res) | |||
}) | |||
}, | |||
/** | |||
* @description 控制promise.all并发数量 | |||
* @param limit 并发数 | |||
* @param array 参数列表 | |||
* @param apiFn 执行函数 | |||
* @returns {Promise<Awaited<unknown>[]>} | |||
*/ | |||
async promiseAllLimit(limit, array, apiFn) { | |||
const ret = [] // 用于存放所有的promise实例 | |||
const executing = [] // 用于存放目前正在执行的promise | |||
for (const item of array) { | |||
const p = apiFn(item) | |||
ret.push(p) | |||
if (limit <= array.length) { | |||
// then回调中,当这个promise状态变为fulfilled后,将其从正在执行的promise列表executing中删除 | |||
const e = p.then(() => executing.splice(executing.indexOf(e), 1)) | |||
executing.push(e) | |||
if (executing.length >= limit) { | |||
// 一旦正在执行的promise列表数量等于限制数,就使用Promise.race等待某一个promise状态发生变更, | |||
// 状态变更后,就会执行上面then的回调,将该promise从executing中删除, | |||
// 然后再进入到下一次for循环,生成新的promise进行补充 | |||
await Promise.race(executing) | |||
} | |||
} | |||
} | |||
} | |||
} | |||
return Promise.all(ret) | |||
}, | |||
validate(array){ | |||
// let type = array.every(item=>{ | |||
// return item.type && item.type.substring(0,6) == "image/" | |||
// }) | |||
// if(!type){ | |||
// this.TOAST('文件类型错误'); | |||
// return false | |||
// } | |||
let size = array.every(item=>{ | |||
return item.size && item.size <= 200 * 1024 * 1024 | |||
}) | |||
if(!size){ | |||
this.TOAST('文件大小不得超过200M'); | |||
return false | |||
} | |||
return true | |||
}, | |||
isImage(type){ | |||
if(type&&type.length){ | |||
return ["png","jpg"].includes(type.substring(type.length-3,type.length)) | |||
}else{ | |||
return false | |||
} | |||
}, | |||
return Promise.all(ret) | |||
}, | |||
viewImg(item) { | |||
if(!this.isImage(item.type)){ | |||
window.location.href = this.CONFIG("webHost")+item.url | |||
}else{ | |||
uni.previewImage({ | |||
urls: [this.CONFIG('webHost')+item.url], | |||
current: this.CONFIG('webHost')+item.url | |||
}); | |||
} | |||
}, | |||
// previewFile() { | |||
// var file = document.querySelector('input[type=file]').files[0]; | |||
// var reader = new FileReader(); | |||
// // fileReader.readAsDataURL(blob); | |||
// // fileReader.onerror = () => { | |||
// // reject(new Error('blobToBase64 error')); | |||
// // }; | |||
// // var encodedData = window.btoa("Hello, world"); | |||
// reader.onloadend = function () { | |||
// //$('#PhotoImg').attr('src', reader.result); | |||
// var postData = { | |||
// Base64Url: reader.result | |||
// } | |||
// this.HTTP_POST(config.webapi + "StuInfoFresh/savePhoto", postData, (data) => { | |||
// if (data) { | |||
// $('#Photo').val(data.AnnexesFileId); | |||
// $('#PhotoImg').attr('src', config.web + data.Url); | |||
// } else { | |||
// learun.layer.toast('采集照片信息失败!'); | |||
// } | |||
// }); | |||
// } | |||
// if (file) { | |||
// reader.readAsDataURL(file); | |||
// } | |||
// }, | |||
}, | |||
created() { | |||
this.imgList = JSON.parse(JSON.stringify(this.value.map(item=>{ | |||
return { | |||
id:item.F_Id, | |||
name:item.F_FileName, | |||
url:item.F_FilePath, | |||
type:item.F_FileType | |||
validate(array) { | |||
// let type = array.every(item=>{ | |||
// return item.type && item.type.substring(0,6) == "image/" | |||
// }) | |||
// if(!type){ | |||
// this.TOAST('文件类型错误'); | |||
// return false | |||
// } | |||
let size = array.every(item => { | |||
return item.size && item.size <= 200 * 1024 * 1024 | |||
}) | |||
if (!size) { | |||
this.TOAST('文件大小不得超过200M'); | |||
return false | |||
} | |||
return true | |||
}, | |||
isImage(type) { | |||
if (type && type.length) { | |||
return ["png", "jpg"].includes(type.substring(type.length - 3, type.length)) | |||
} else { | |||
return false | |||
} | |||
}, | |||
viewImg(item) { | |||
if (!this.isImage(item.type)) { | |||
window.location.href = this.CONFIG("webHost") + item.url | |||
} else { | |||
uni.previewImage({ | |||
urls: [this.CONFIG('webHost') + item.url], | |||
current: this.CONFIG('webHost') + item.url | |||
}); | |||
} | |||
}, | |||
// previewFile() { | |||
// var file = document.querySelector('input[type=file]').files[0]; | |||
// var reader = new FileReader(); | |||
// // fileReader.readAsDataURL(blob); | |||
// // fileReader.onerror = () => { | |||
// // reject(new Error('blobToBase64 error')); | |||
// // }; | |||
// // var encodedData = window.btoa("Hello, world"); | |||
// reader.onloadend = function () { | |||
// //$('#PhotoImg').attr('src', reader.result); | |||
// var postData = { | |||
// Base64Url: reader.result | |||
// } | |||
// this.HTTP_POST(config.webapi + "StuInfoFresh/savePhoto", postData, (data) => { | |||
// if (data) { | |||
// $('#Photo').val(data.AnnexesFileId); | |||
// $('#PhotoImg').attr('src', config.web + data.Url); | |||
// } else { | |||
// learun.layer.toast('采集照片信息失败!'); | |||
// } | |||
// }); | |||
// } | |||
// if (file) { | |||
// reader.readAsDataURL(file); | |||
// } | |||
// }, | |||
}, | |||
created() { | |||
console.log(this.value) | |||
this.imgList = JSON.parse(JSON.stringify(this.value.map(item => { | |||
return { | |||
id: item.F_Id, | |||
name: item.F_FileName, | |||
url: item.F_FilePath, | |||
type: item.F_FileType | |||
} | |||
}))) | |||
this.$nextTick(() => { | |||
this.isShow = true | |||
}) | |||
} | |||
}))) | |||
this.$nextTick(()=>{ | |||
this.isShow = true | |||
}) | |||
} | |||
}; | |||
}; | |||
</script> | |||
<style scoped> | |||
.file-name{ | |||
.file-name { | |||
position: absolute; | |||
bottom: 0; | |||
width: 100%; | |||
color: #606266; | |||
font-size: 13px; | |||
text-align: center; | |||
background-color: rgba(255,255,255,0.6); | |||
background-color: rgba(255, 255, 255, 0.6); | |||
text-overflow: ellipsis; | |||
overflow: hidden; | |||
white-space: nowrap; | |||
@@ -21,10 +21,10 @@ export default { | |||
// "http://192.168.2.98:8088/" | |||
// ], | |||
"apiHost": [ | |||
"http://192.168.10.68:8002/" | |||
// "http://192.168.10.85:8088/" | |||
"http://192.168.10.58:8012/" | |||
// "http://123.57.209.16:31173/" | |||
], | |||
"webHost":"http://localhost:20472/", | |||
"webHost":"http://demo.bjquanjiang.com:8081/", | |||
// 开发环境下自动填充登录账号密码,与接口地址一一对应,只在开发环境下显示 | |||
"devAccount": [ | |||
// 20201130230 21364200000400266 老师 420528196310072253 学生 420528200606205026 420528200507261428 | |||
@@ -119,7 +119,7 @@ | |||
"quickapp" : {}, | |||
/* 小程序特有相关 */ | |||
"mp-weixin" : { | |||
"appid" : "wxbc18c9bf92c86d28", | |||
"appid" : "wx36f8c96ee26af75b", | |||
"setting" : { | |||
"urlCheck" : false, | |||
"es6" : true, | |||
@@ -1028,6 +1028,15 @@ | |||
} | |||
} | |||
,{ | |||
"path" : "pages/onlienpay/payInvioce", | |||
"style" : | |||
{ | |||
"navigationBarTitleText": "", | |||
"enablePullDownRefresh": false | |||
} | |||
} | |||
], | |||
// 全局样式 | |||
@@ -3,7 +3,8 @@ | |||
<!-- 主列表页 --> | |||
<view :class="sideOpen ? 'show' : ''" class="mainpage" style="padding-top: 80rpx;"> | |||
<!-- 顶部条目/分页信息栏 --> | |||
<l-customlist-banner @buttonClick="sideOpen = true">{{ tips }}</l-customlist-banner> | |||
<!-- @buttonClick="sideOpen = true" --> | |||
<l-customlist-banner @buttonClick="">{{ tips }}</l-customlist-banner> | |||
<!-- 滚动列表,跨端支持上拉/下拉 --> | |||
<l-scroll-list v-if="ready" @pullDown="pullDown" @toBottom="fetchList()" ref="list"> | |||
@@ -26,14 +27,14 @@ | |||
{{ displayListItem(item, 'EmpName') }} | |||
</view> | |||
<view class="customlist-item-field"> | |||
<view class="customlist-item-field"> | |||
<text class="customlist-item-field-title">课程名称:</text> | |||
{{ displayListItem(item, 'LessonName') }} | |||
{{ displayListItem(item, 'LessonName') }} | |||
</view> | |||
<view class="customlist-item-field"> | |||
<text class="customlist-item-field-title">评教状态:</text> | |||
{{ displayListItem(item, 'UID') }} | |||
</view> | |||
</view> | |||
<l-customlist-action @view="action('view', item)" /> | |||
@@ -1,69 +1,63 @@ | |||
<template> | |||
<view class="page"> | |||
<view v-if="ready"> | |||
<l-input | |||
@input="setValue('JournalSend.JTitle', $event)" | |||
:value="getValue('JournalSend.JTitle')" | |||
:disabled="!edit" | |||
title="上课是否迟到" | |||
/> | |||
<l-select | |||
@input="setValue('JournalSend.JTypeId', $event)" | |||
:value="getValue('JournalSend.JTypeId')" | |||
:disabled="!edit" | |||
:range="dataSource.JournalSend.JTypeId" | |||
title="是否拖堂" | |||
/> | |||
<l-organize-picker | |||
@input="setValue('JournalSend.JReceiveId', $event)" | |||
:value="getValue('JournalSend.JReceiveId')" | |||
:readonly="!edit" | |||
type="user" | |||
title="作业量是否合理" | |||
/> | |||
<l-textarea | |||
@input="setValue('JournalSend.JContent', $event)" | |||
:value="getValue('JournalSend.JContent')" | |||
:readonly="!edit" | |||
title="对老师还有什么建议" | |||
/> | |||
</view> | |||
<view v-if="ready"> | |||
<!-- <l-input v-model="text" disabled title="你说呢你说呢?"></l-input> | |||
<radio-group> | |||
<l-radio v-model="radioValue" title="单选框1" radioValue="1" /> | |||
<l-radio v-model="radioValue" title="单选框2" radioValue="2" /> | |||
</radio-group> --> | |||
<view v-for="(item,index) in formData.Eval_Questions" :key="item.QID"> | |||
<view class="questionTitle"> | |||
<text style="color: red;">{{item.QMust?"* ":""}}</text> | |||
{{item.QTitle}} | |||
</view> | |||
<!-- 单选 --> | |||
<l-select | |||
v-if="item.QType == 1" | |||
v-model="aa" | |||
:range="item.Eval_QuestionItems" | |||
title="" | |||
placeholder="请选择" | |||
:disabled="false" | |||
textField="ITitle" | |||
valueField="IID" | |||
/> | |||
<!-- 多选 --> | |||
<!-- <l-checkbox | |||
v-if="item.QTypeString == 1" | |||
v-model="aa" | |||
@change="searchChange" | |||
:range="item.Eval_QuestionItems" | |||
title="" | |||
placeholder="请选择" | |||
:disabled="false" | |||
textField="ITitle" | |||
valueField="IID" | |||
/> --> | |||
<checkbox-group v-if="item.QType == 1"> | |||
<l-checkbox v-for="item1 in item.Eval_QuestionItems" :key="item1.IID" v-model="bbb" :title="item1.ITitle" :checkboxValue="item1.IID.toString()" /> | |||
</checkbox-group> | |||
<!-- 填空 --> | |||
<l-textarea v-if="item.QType == 1" v-model="aa" placeholder="请输入" /> | |||
</view> | |||
<!-- <l-input v-model="text" disabled title="你说呢你说呢?"></l-input> | |||
<radio-group> | |||
<l-radio v-model="radioValue" title="单选框1" radioValue="1" /> | |||
<l-radio v-model="radioValue" title="单选框2" radioValue="2" /> | |||
</radio-group> --> | |||
</view> | |||
<view v-if="ready" class="bg-white margin-tb padding" style="padding-top: 0; overflow: hidden;"> | |||
<l-button v-if="edit" @click="action('save')" size="lg" color="green" class="block margin-top" block> | |||
<l-button v-if="edit" @click="action('save')" size="lg" style="background-color: #0C86D8;color: #fff;" class="block margin-top" block> | |||
提交保存 | |||
</l-button> | |||
<l-button v-if="!edit && mode !== 'create'" @click="action('edit')" size="lg" line="orange" class="block margin-top" block> | |||
编辑本页 | |||
</l-button> | |||
<l-button v-if="edit && mode !== 'create'" @click="action('reset')" size="lg" line="red" class="block margin-top" block> | |||
取消编辑 | |||
</l-button> | |||
<l-button v-if="!edit && mode !== 'create'" @click="action('delete')" size="lg" line="red" class="block margin-top" block> | |||
删除 | |||
</l-button> | |||
</view> | |||
</view> | |||
</template> | |||
<script> | |||
/* | |||
* 版 本 Learun-ADMS V7.0.3 力软敏捷开发框架(http://www.learun.cn) | |||
* Copyright (c) 2013-2020 上海力软信息技术有限公司 | |||
* 创建人:超级管理员 | |||
* 日 期:2020-10-16 15:39 | |||
* 描 述:工作日志 | |||
*/ | |||
/** | |||
* 本段代码由移动端代码生成器输出,移动端须 2.2.0 版本及以上可以使用 | |||
* 请在移动端 /pages.json 中的 pages 字段中添加一条记录: | |||
* { "path": "pages/EducationalAdministration/JournalSend/single", "style": { "navigationBarTitleText": "表单详情页" } } | |||
* | |||
* (navigationBarTitleText 字段为本页面的标题文本,可以修改) | |||
* (必须自行操作该步骤,力软代码生成器不会自动帮您修改 /pages.json 文件) | |||
*/ | |||
import get from 'lodash/get' | |||
import set from 'lodash/set' | |||
@@ -74,73 +68,50 @@ export default { | |||
mixins: [customPageMixins], | |||
data() { | |||
return { | |||
return { | |||
aa:"", | |||
bbb:[], | |||
// 页面相关参数 | |||
id: null, | |||
mode: null, | |||
edit: null, | |||
ready: false, | |||
// 表单数据 | |||
current: {}, | |||
origin: {}, | |||
// 表单项数据结构 | |||
scheme: { | |||
JournalSend: { | |||
JTitle: { type: 'text', title: '日志主题' }, | |||
JTypeId: { type: 'select', title: '日志类型', dataSource: '0' }, | |||
JReceiveId: { type: 'organize', title: '接收人', dataType: 'user' }, | |||
JContent: { type: 'textarea', title: '日志内容' }, | |||
}, | |||
}, | |||
// 数据源 | |||
dataSource: { | |||
JournalSend: { | |||
JTypeId: [], | |||
}, | |||
} | |||
} | |||
}, | |||
async onLoad({ type, id }) { | |||
await this.init(type, id) | |||
ready: false, | |||
formData:{}, | |||
submitParams:null | |||
} | |||
}, | |||
async onLoad({ id,EmpNo,LessonNo }) { | |||
this.submitParams = {EmpNo,LessonNo} | |||
await this.init(id) | |||
}, | |||
methods: { | |||
aaa(){ | |||
console.log(this.bbb,this) | |||
}, | |||
// 页面初始化 | |||
async init(type, id) { | |||
this.LOADING('加载数据中...') | |||
this.id = id | |||
this.mode = type | |||
this.edit = ['create', 'edit'].includes(this.mode) | |||
// 拉取表单数据,同时拉取所有来自数据源的选单数据 | |||
await Promise.all([ | |||
() => {} | |||
]) | |||
async init( id ) { | |||
this.LOADING('加载数据中...') | |||
this.id = id | |||
await this.fetchForm() | |||
this.ready = true | |||
this.HIDE_LOADING() | |||
}, | |||
// 加载表单数据 | |||
async fetchForm() { | |||
if (this.mode === 'create') { | |||
this.origin = await this.getDefaultForm() | |||
} else { | |||
const result = await this.HTTP_GET('learun/adms/eval/paper', {VID:this.id}) | |||
console.log(result); | |||
this.origin = await this.formatFormData(result) | |||
} | |||
this.current = this.COPY(this.origin) | |||
async fetchForm() { | |||
return this.HTTP_GET('learun/adms/eval/paper', {VID:this.id}, '加载数据时出错').then(success => { | |||
this.HIDE_LOADING() | |||
if (!success) { | |||
return | |||
} | |||
if(success){ | |||
this.edit = true | |||
} | |||
console.log(success) | |||
this.formData = success | |||
}) | |||
}, | |||
// 点击 「编辑」、「重置」、「保存」、「删除」 按钮 | |||
@@ -156,29 +127,37 @@ console.log(result); | |||
break | |||
case 'save': | |||
const verifyResult = this.verifyForm() | |||
if (verifyResult.length > 0) { | |||
this.CONFIRM('表单验证失败', verifyResult.join('\n')) | |||
return | |||
} | |||
// const verifyResult = this.verifyForm() | |||
// if (verifyResult.length > 0) { | |||
// this.CONFIRM('表单验证失败', verifyResult.join('\n')) | |||
// return | |||
// } | |||
if (!(await this.CONFIRM('提交确认', '确定要提交本页表单内容吗?', true))) { | |||
return | |||
} | |||
this.LOADING('正在提交...') | |||
const postData = await this.getPostData(this.id) | |||
this.LOADING('正在提交...') | |||
let postarray = this.formData.Eval_Questions.map(item=>{ | |||
return { | |||
QID:item.QID, | |||
IID:item.IID.toString(), | |||
UText:item.UText, | |||
} | |||
}) | |||
const postData = { | |||
VID:this.formData.VID, | |||
...this.submitParams, | |||
postarray | |||
} | |||
this.HTTP_POST('learun/adms/EducationalAdministration/Journal/save', postData, '表单提交保存失败').then(success => { | |||
this.HIDE_LOADING() | |||
if (!success) { | |||
return | |||
} | |||
this.EMIT('EducationalAdministrationJournalSend-list-change') | |||
this.NAV_BACK() | |||
this.TOAST('提交保存成功') | |||
}) | |||
this.NAV_BACK() | |||
this.TOAST('提交保存成功') | |||
}) | |||
break | |||
case 'delete': | |||
@@ -214,4 +193,17 @@ console.log(result); | |||
} | |||
} | |||
} | |||
</script> | |||
</script> | |||
<style scoped lang="scss"> | |||
.questionTitle{ | |||
line-height: 18px; | |||
background-color: #fff; | |||
color: #000; | |||
margin-top: 8px; | |||
margin-bottom: 1px; | |||
padding: 16px 12px; | |||
} | |||
:deep(.cu-form-group){ | |||
display: none; | |||
} | |||
</style> |
@@ -508,6 +508,7 @@ export default{ | |||
text-align: center; | |||
font-size: 14px; | |||
color: #1a1a1a; | |||
background-color: #ffffff; | |||
} | |||
.timeTableAlertLi.active { | |||
@@ -518,10 +519,6 @@ export default{ | |||
background-color: #fbfdff; | |||
} | |||
.timeTableAlertLi:nth-child(2n - 1) { | |||
background-color: #ffffff; | |||
} | |||
#MeasureTime { | |||
text-align: center; | |||
} | |||
@@ -273,7 +273,7 @@ page { | |||
.otherLogin{ | |||
display: flex; | |||
justify-content: right; | |||
justify-content: flex-end; | |||
.textBtn{ | |||
width: 100px; | |||
color: #606266; | |||
@@ -132,7 +132,7 @@ export default { | |||
return null | |||
} | |||
return this.API + `/user/img?data=${item.F_OtherUserId}` | |||
return this.API + `/learun/adms/user/img?data=${item.F_OtherUserId}` | |||
} | |||
}, | |||
@@ -186,7 +186,7 @@ export default { | |||
// 获取用户头像图片 url | |||
avatar(id) { | |||
return id === this.chatUserId && this.isSystem ? null : this.API + `/user/img?data=${id}` | |||
return id === this.chatUserId && this.isSystem ? null : this.API + `/learun/adms/user/img?data=${id}` | |||
} | |||
}, | |||
@@ -156,7 +156,7 @@ export default { | |||
return '' | |||
} | |||
return this.API + `/user/img?data=${this.currentUser.userId}` | |||
return this.API + `/learun/adms/user/img?data=${this.currentUser.userId}` | |||
} | |||
}, | |||
@@ -34,7 +34,7 @@ export default { | |||
// 头像图片 url | |||
avatarSrc() { | |||
return this.API + `/user/img?data=${this.currentUser.userId}` | |||
return this.API + `/learun/adms/user/img?data=${this.currentUser.userId}` | |||
} | |||
} | |||
} | |||
@@ -30,7 +30,7 @@ export default { | |||
// 头像图片 url | |||
avatar() { | |||
return this.API + `/user/img?data=${this.currentUser.userId}` | |||
return this.API + `/learun/adms/user/img?data=${this.currentUser.userId}` | |||
}, | |||
// 用户公司部门 tag | |||
@@ -38,7 +38,7 @@ | |||
<view class="tSec2Con2"> | |||
<view class="studCheckList"> | |||
<view class="studCheckLi" v-for="(k, i) in data.result" :key="k.StuName"> | |||
<view style="float:right; margin-top: 7px;" class="studCheckStatue" :class="type(k.Sort)"> | |||
<view style="float:right; margin-top: 7px;" class="studCheckStatue" :class="[type(k.Sort)]"> | |||
<text></text> | |||
{{ k.Sort }} | |||
</view> | |||
@@ -95,14 +95,15 @@ export default { | |||
// t.formId 使用表单,根据这个 formId 来获取 scheme 等信息 | |||
// t.appurl 使用移动页面,直接跳转到本地的页面;表单结构等均写死在页面里 | |||
const { wfForms } = this.currentNode | |||
console.log(wfForms); | |||
// 处理没有有效表单的情况,停止加载 | |||
if (!wfForms || wfForms.every(t => !t.formId && !t.appurl)) { | |||
this.HIDE_LOADING() | |||
this.TOAST('移动表单数据(wfForms)中无有效表单') | |||
return | |||
} | |||
const fetchFolderkeyData=await this.fetchFolderkeyData(this.currentNode , this.processId); | |||
uni.setStorageSync('guids',JSON.stringify(fetchFolderkeyData)); | |||
// 处理移动端本地表单(也就是系统表单)的情况,直接跳转过去 | |||
const appSysPage = wfForms.find(t => t.appurl) | |||
@@ -151,8 +152,6 @@ export default { | |||
// 不是子流程,可以直接渲染 | |||
const schemeData = await this.fetchSchemeData(this.currentNode) | |||
const formData = await this.fetchFormData(this.currentNode, this.processId) | |||
console.log(schemeData) | |||
console.log(formData) | |||
const { formValue, scheme, rel } = await this.getCustomForm({ | |||
formData, | |||
schemeData, | |||
@@ -161,7 +160,6 @@ export default { | |||
code: null | |||
}) | |||
this.scheme = scheme | |||
console.log(scheme) | |||
this.formValue = formValue | |||
this.rel = rel | |||
} | |||
@@ -201,7 +199,7 @@ export default { | |||
return | |||
} | |||
this.LOADING(`提交${actionText}中…`) | |||
this.HTTP_POST(`/newwf${actionUrl}`, actionData, `提交${actionText}失败`).then(success => { | |||
this.HTTP_POST(`/learun/adms/newwf${actionUrl}`, actionData, `提交${actionText}失败`).then(success => { | |||
this.HIDE_LOADING() | |||
if (success) { | |||
this.EMIT('task-list-change') | |||
@@ -220,7 +218,7 @@ export default { | |||
this.LOADING('正在提交…') | |||
const draftFormValue = this.$refs.form.getFormValue() | |||
const draftPostData = await this.getPostData(draftFormValue, this.scheme) | |||
this.HTTP_POST('/newwf/draft', draftPostData, '提交草稿失败').then(success => { | |||
this.HTTP_POST('/learun/adms/newwf/draft', draftPostData, '提交草稿失败').then(success => { | |||
this.HIDE_LOADING() | |||
if (success) { | |||
this.EMIT('task-list-change') | |||
@@ -249,7 +247,7 @@ export default { | |||
postData.parentTaskId = this.taskId | |||
} | |||
const errorTips = '流程发起失败' | |||
this.HTTP_POST('/newwf/createchildflow', postData, errorTips).then(success => { | |||
this.HTTP_POST('/learun/adms/newwf/createchildflow', postData, errorTips).then(success => { | |||
this.HIDE_LOADING() | |||
if (success) { | |||
this.EMIT('task-list-change') | |||
@@ -110,7 +110,10 @@ export default { | |||
this.needTitle = this.type !== 'again' && Number(currentNode.isTitle) === 1 | |||
const formData = await this.fetchFormData(currentNode, processId) | |||
const schemeData = await this.fetchSchemeData(currentNode) | |||
const schemeData = await this.fetchSchemeData(currentNode); | |||
const fetchFolderkeyData=await this.fetchFolderkeyData(currentNode, processId); | |||
uni.setStorageSync('guids',JSON.stringify(fetchFolderkeyData)); | |||
const { formValue, scheme, rel } = await this.getCustomForm({ | |||
schemeData, | |||
processId, | |||
@@ -119,14 +122,15 @@ export default { | |||
code: this.type === 'again' ? null : code, | |||
useDefault: true | |||
}) | |||
this.rel = rel | |||
this.scheme = scheme | |||
this.formValue = formValue | |||
this.code = code | |||
this.processId = processId | |||
this.ready = true | |||
this.HIDE_LOADING() | |||
}, | |||
// 提交草稿按钮 | |||
@@ -153,9 +157,10 @@ export default { | |||
// 发起流程按钮 | |||
async submit() { | |||
const isAgain = this.type === 'again' | |||
// 先验证表单,验证不通过则提示 | |||
const verifyResult = this.verifyValue() | |||
if (verifyResult.length > 0) { | |||
this.CONFIRM('表单验证失败', verifyResult.join('\n')) | |||
return | |||
@@ -191,6 +196,7 @@ export default { | |||
// 获取表单验证结果,是一个包含错误信息的数组,长度为 0 则没有错误 | |||
verifyValue() { | |||
const errList = this.$refs.form.verifyValue() | |||
if (this.needTitle && !this.title) { | |||
errList.push(`流程的标题不能为空`) | |||
@@ -32,298 +32,383 @@ import customForm from '@/common/customform.js' | |||
* (以上只是简单介绍;实际使用中,如果打开子流程,需要拉取父/子两个流程信息) | |||
*/ | |||
export default { | |||
mixins: [customForm], | |||
methods: { | |||
/** | |||
* 从流程信息中生成 scheme、formValue | |||
* 参数: { schemeData (必填), processId, currentNode, formData (新建时为 null), code, useDefault } | |||
* 返回: { scheme, formValue, rel } | |||
* | |||
* 参数: | |||
* schemeData: 使用 fetchSchemeData 方法拉取到的原始 scheme 数据,未经过格式化处理 | |||
* processId: 表单 GUID;如果是新建表单,可以用 this.GUID('-') 生成一个 | |||
* currentNode: 使用 getCurrentNode 方法拉取到的当前节点信息,用于权限控制 | |||
* formData: 填入表单的表单值,新建表单时此项为 null 即可 | |||
* code: 表单编号 code,会被赋值到返回的 formValue.code;重新发起流程的场合赋 null | |||
* useDefault: 如果 formData 中某一项为空,是否对这一项填入默认值;通常在编辑草稿时启用 | |||
* | |||
* 该方法返回的 scheme 项可能带有以下属性: | |||
* __valuePath__: 表单值在 formValue 中的路径,使用 lodash 的 get、set 方法即可读写 | |||
* __sourceData__: 表单值的选单数据 | |||
* __defaultItem__: 类型为 girdtable 的表单项带有此属性,表示添加一行表格时候表格项的默认值 | |||
* __schemeIndex__: (暂时用不到)表单项位于 schemeData 根级内的第几个子项中 | |||
* __dataIndex__: (暂时用不到)表单项位于 F_Scheme.data 中的第几个子项中 | |||
*/ | |||
async getCustomForm(prop) { | |||
const { schemeData, formData, currentNode, code, processId, useDefault } = prop | |||
// 处理字段之间的级联、绑定关系 | |||
// 需要绑定 change 事件的: | |||
// datetime: 修改后重新计算 datetimerange | |||
// organize: 修改后重设级联到该组件的其他组件的值,user 一级无需处理 | |||
// 需要绑定某值的: | |||
// organize: 级联到某个组件,company 一级无需处理 | |||
const schemeRef = {} | |||
const refList = [] | |||
// 最终返回值:scheme、rel、formValue | |||
const scheme = [] | |||
const rel = {} | |||
const formValue = { processId, formreq: [] } | |||
if (code) { | |||
formValue.code = code | |||
} | |||
// 遍历 schemeData 中所有的 scheme | |||
const schemeList = Array.isArray(schemeData) ? schemeData : Object.values(schemeData) | |||
for (let schemeIndex = 0; schemeIndex < schemeList.length; ++schemeIndex) { | |||
const schemeItem = schemeList[schemeIndex] | |||
schemeItem.F_Scheme = JSON.parse(schemeItem.F_Scheme) | |||
// 已有表单值的时候,舍弃掉不存在表单值中的 scheme | |||
if (formData && !formData[schemeItem.F_SchemeInfoId]) { | |||
continue | |||
} | |||
// 设置 formreq 的内容,非新建模式下需要设置 keyValue | |||
const { formId, field } = get(currentNode, `wfForms.${schemeIndex}`, {}) | |||
const formreqObj = { schemeInfoId: formId, processIdName: field, formData: {} } | |||
if (formData) { | |||
if (Object.values(get(formData, `${schemeItem.F_SchemeInfoId}`, {})).some(t => t && t.length > 0)) { | |||
formreqObj.keyValue = processId | |||
} | |||
} | |||
formValue.formreq[schemeIndex] = formreqObj | |||
for (let dataIndex = 0; dataIndex < schemeItem.F_Scheme.data.length; ++dataIndex) { | |||
const { componts } = schemeItem.F_Scheme.data[dataIndex] | |||
for (const t of componts) { | |||
// 之后的 t 即表示每个 scheme 项 | |||
t.__valuePath__ = `formreq.${schemeIndex}.formData.${t.id}` | |||
// 以下两个属性暂时用不到 | |||
t.__schemeIndex__ = schemeIndex | |||
t.__dataIndex__ = dataIndex | |||
if (t.type === 'girdtable' && t.table) { | |||
// 数据项是表格的情况 | |||
// 先设置源数据,不然无法获取默认值 | |||
for (const fieldItem of t.fieldsData) { | |||
fieldItem.__sourceData__ = await this.getSourceData(fieldItem) | |||
} | |||
t.__defaultItem__ = await this.getDefaultData(t, prop) | |||
if (formData) { | |||
// 有表单值的情况,从表单值中获取数据 | |||
const val = [] | |||
for (const valueItem of get(formData, `${schemeItem.F_SchemeInfoId}.${t.table}`, [])) { | |||
const tableItemValue = {} | |||
for (const fieldItem of t.fieldsData.filter(t => t.field)) { | |||
const formDataValue = get(valueItem, fieldItem.field.toLowerCase()) | |||
tableItemValue[fieldItem.field] = await this.convertToFormValue(fieldItem, formDataValue) | |||
} | |||
val.push(tableItemValue) | |||
} | |||
// useDefault 表示在从 formData 取不到值的时候使用默认值 | |||
if ((!val || val.length <= 0) && useDefault) { | |||
set(formValue, t.__valuePath__, [this.COPY(t.__defaultItem__)]) | |||
} else { | |||
set(formValue, t.__valuePath__, val) | |||
} | |||
} else { | |||
// 无表单值的情况,默认值 | |||
set(formValue, t.__valuePath__, [this.COPY(t.__defaultItem__)]) | |||
} | |||
} else if (t.field) { | |||
// 数据项不是表格的情况 | |||
// 先设置源数据,不然无法获取默认值 | |||
t.__sourceData__ = await this.getSourceData(t) | |||
if (formData) { | |||
// 有表单值的情况,从表单值中获取数据 | |||
const path = `${schemeItem.F_SchemeInfoId}.${t.table}.${dataIndex}.${t.field.toLowerCase()}` | |||
const formDataValue = get(formData, path) | |||
// useDefault 表示在从 formData 取不到值的时候使用默认值 | |||
if (!formDataValue && useDefault) { | |||
set(formValue, t.__valuePath__, await this.getDefaultData(t, prop)) | |||
} else { | |||
set(formValue, t.__valuePath__, await this.convertToFormValue(t, formDataValue)) | |||
} | |||
} else { | |||
// 无表单值的情况,默认值 | |||
set(formValue, t.__valuePath__, await this.getDefaultData(t, prop)) | |||
} | |||
} | |||
// 权限控制 | |||
const authObj = get(currentNode, `wfForms.${schemeIndex}.authorize.${t.id}`, {}) | |||
t.edit = authObj.isEdit | |||
if (Number(t.isHide) !== 1 && authObj.isLook !== 0) { | |||
// 加入 scheme | |||
scheme.push(t) | |||
// organize、datetime 可能作为其他 organize 或 datetimerange 的依赖项,引用它们 | |||
if (['organize', 'datetime'].includes(t.type)) { | |||
schemeRef[t.id] = t | |||
} | |||
// datetimerange、带有 relation 级联字段的 organize,依赖其他项 | |||
if ((t.type === 'datetimerange' && t.startTime && t.endTime) || (t.type === 'organize' && t.relation)) { | |||
refList.push(t) | |||
} | |||
} | |||
} | |||
} | |||
} | |||
// 依次处理表单关联 | |||
refList.forEach(t => { | |||
if (t.type === 'organize') { | |||
// 处理组件结构级联 | |||
// 给当前组件赋上级级联的值路径 __relationPath__ | |||
const parent = schemeRef[t.relation] | |||
t.__relationPath__ = parent.__valuePath__ | |||
// 给上级级联的组件注册自动重置当前组件的 change 事件 | |||
const relItem = { type: 'organize', id: t.id, path: t.__valuePath__ } | |||
rel[parent.id] = rel[parent.id] ? rel[parent.id].concat(relItem) : [relItem] | |||
} else if (t.type === 'datetimerange') { | |||
// 处理日期区间 | |||
const start = schemeRef[t.startTime] | |||
const end = schemeRef[t.endTime] | |||
const relItem = { | |||
type: 'datetimerange', | |||
path: t.__valuePath__, | |||
id: t.id, | |||
startPath: start.__valuePath__, | |||
endPath: end.__valuePath__, | |||
} | |||
rel[start.id] = rel[start.id] ? rel[start.id].concat(relItem) : [relItem] | |||
rel[end.id] = rel[end.id] ? rel[end.id].concat(relItem) : [relItem] | |||
} | |||
}) | |||
return { scheme, formValue, rel } | |||
}, | |||
/** | |||
* 获取最终需要 POST 的数据 | |||
* 参数:formValue, scheme | |||
* 返回:用于提交的数据 | |||
* | |||
* 遍历 formValue,将其中的表单值依次使用 convertToPostData 这个方法转化为提交值 | |||
*/ | |||
async getPostData(originFormValue, scheme) { | |||
const formValue = this.COPY(originFormValue) | |||
// 依次按照 scheme 项目遍历 | |||
for (const item of scheme) { | |||
if (item.field) { | |||
// 不是表格的情况 | |||
const path = item.__valuePath__ | |||
const val = get(formValue, path) | |||
const result = await this.convertToPostData(item, val, originFormValue, scheme) | |||
set(formValue, path, result) | |||
} else if (item.table && item.fieldsData) { | |||
// 是表格的情况 | |||
const tableValue = get(formValue, item.__valuePath__, []) | |||
for (let valueIndex = 0; valueIndex < tableValue.length; ++valueIndex) { | |||
for (const schemeItem of item.fieldsData) { | |||
const path = `${item.__valuePath__}.${valueIndex}.${schemeItem.field}` | |||
const val = get(formValue, path) | |||
const result = await this.convertToPostData(schemeItem, val, originFormValue, scheme) | |||
set(formValue, path, result) | |||
} | |||
} | |||
} | |||
} | |||
formValue.formreq.forEach(t => { t.formData = JSON.stringify(t.formData) }) | |||
formValue.formreq = JSON.stringify(formValue.formreq) | |||
return formValue | |||
}, | |||
/** | |||
* 获取流程信息 | |||
* 参数: { code, processId, taskId } | |||
* | |||
*/ | |||
async fetchProcessInfo({ code, processId, taskId }) { | |||
const url = processId ? 'learun/adms/newwf/processinfo' : 'learun/adms/newwf/scheme' | |||
const reqObj = { processId } | |||
if (taskId) { | |||
reqObj.taskId = taskId | |||
} | |||
const data = processId ? reqObj : code | |||
const result = await this.HTTP_GET(url, data) | |||
if (!result) { return {} } | |||
if (result.info) { | |||
result.info.Scheme = JSON.parse(result.info.Scheme) | |||
} else if (result.F_Content) { | |||
result.F_Content = JSON.parse(result.F_Content) | |||
} | |||
return result | |||
}, | |||
/** | |||
* 从 processInfo 流程信息中,提取出 currentNode | |||
* 参数: processInfo | |||
* | |||
*/ | |||
getCurrentNode(processInfo) { | |||
if (processInfo.info) { | |||
return processInfo.info.Scheme.nodes.find(t => t.id === processInfo.info.CurrentNodeId) | |||
} else if (processInfo.F_Content) { | |||
return processInfo.F_Content.nodes.find(t => t.type === 'startround') | |||
} | |||
return {} | |||
}, | |||
/** | |||
* 拉取表单的 schemeData | |||
* 参数: currentNode | |||
* | |||
* 从当前节点 currentNode 中提取出表单 id,然后自 API 地址 /form/scheme 中拉取表单数据并返回 | |||
*/ | |||
async fetchSchemeData(currentNode, currentTask, type) { | |||
const { wfForms } = currentNode | |||
const data = wfForms.filter(t => t.formId).map(t => ({ id: t.formId, ver: '' })) | |||
const schemeData = await this.HTTP_GET('learun/adms/form/scheme', data) | |||
return schemeData || {} | |||
}, | |||
/** | |||
* 拉取表单的 formData | |||
* 参数: currentNode, keyValue | |||
* | |||
* 提取当前节点信息、表单主键信息,从 API 地址 /form/data 中拉取表单数据 | |||
*/ | |||
async fetchFormData({ wfForms }, keyValue) { | |||
const reqData = wfForms | |||
.filter(t => t.formId) | |||
.map(t => ({ | |||
schemeInfoId: t.formId, | |||
processIdName: t.field, | |||
keyValue | |||
})) | |||
const formData = await this.HTTP_GET('learun/adms/form/data', reqData) | |||
return formData || {} | |||
} | |||
} | |||
mixins: [customForm], | |||
methods: { | |||
/** | |||
* 从流程信息中生成 scheme、formValue | |||
* 参数: { schemeData (必填), processId, currentNode, formData (新建时为 null), code, useDefault } | |||
* 返回: { scheme, formValue, rel } | |||
* | |||
* 参数: | |||
* schemeData: 使用 fetchSchemeData 方法拉取到的原始 scheme 数据,未经过格式化处理 | |||
* processId: 表单 GUID;如果是新建表单,可以用 this.GUID('-') 生成一个 | |||
* currentNode: 使用 getCurrentNode 方法拉取到的当前节点信息,用于权限控制 | |||
* formData: 填入表单的表单值,新建表单时此项为 null 即可 | |||
* code: 表单编号 code,会被赋值到返回的 formValue.code;重新发起流程的场合赋 null | |||
* useDefault: 如果 formData 中某一项为空,是否对这一项填入默认值;通常在编辑草稿时启用 | |||
* | |||
* 该方法返回的 scheme 项可能带有以下属性: | |||
* __valuePath__: 表单值在 formValue 中的路径,使用 lodash 的 get、set 方法即可读写 | |||
* __sourceData__: 表单值的选单数据 | |||
* __defaultItem__: 类型为 girdtable 的表单项带有此属性,表示添加一行表格时候表格项的默认值 | |||
* __schemeIndex__: (暂时用不到)表单项位于 schemeData 根级内的第几个子项中 | |||
* __dataIndex__: (暂时用不到)表单项位于 F_Scheme.data 中的第几个子项中 | |||
*/ | |||
async getCustomForm(prop) { | |||
const { | |||
schemeData, | |||
formData, | |||
currentNode, | |||
code, | |||
processId, | |||
useDefault | |||
} = prop | |||
// 处理字段之间的级联、绑定关系 | |||
// 需要绑定 change 事件的: | |||
// datetime: 修改后重新计算 datetimerange | |||
// organize: 修改后重设级联到该组件的其他组件的值,user 一级无需处理 | |||
// 需要绑定某值的: | |||
// organize: 级联到某个组件,company 一级无需处理 | |||
const schemeRef = {} | |||
const refList = [] | |||
// 最终返回值:scheme、rel、formValue | |||
const scheme = [] | |||
const rel = {} | |||
const formValue = { | |||
processId, | |||
formreq: [] | |||
} | |||
if (code) { | |||
formValue.code = code | |||
} | |||
// 遍历 schemeData 中所有的 scheme | |||
const schemeList = Array.isArray(schemeData) ? schemeData : Object.values(schemeData) | |||
for (let schemeIndex = 0; schemeIndex < schemeList.length; ++schemeIndex) { | |||
const schemeItem = schemeList[schemeIndex] | |||
schemeItem.F_Scheme = JSON.parse(schemeItem.F_Scheme) | |||
// 已有表单值的时候,舍弃掉不存在表单值中的 scheme | |||
if (formData && !formData[schemeItem.F_SchemeInfoId]) { | |||
continue | |||
} | |||
// 设置 formreq 的内容,非新建模式下需要设置 keyValue | |||
const { | |||
formId, | |||
field | |||
} = get(currentNode, `wfForms.${schemeIndex}`, {}) | |||
const formreqObj = { | |||
schemeInfoId: formId, | |||
processIdName: field, | |||
formData: {} | |||
} | |||
if (formData) { | |||
if (Object.values(get(formData, `${schemeItem.F_SchemeInfoId}`, {})).some(t => t && t.length > | |||
0)) { | |||
formreqObj.keyValue = processId | |||
} | |||
} | |||
formValue.formreq[schemeIndex] = formreqObj | |||
for (let dataIndex = 0; dataIndex < schemeItem.F_Scheme.data.length; ++dataIndex) { | |||
const { | |||
componts | |||
} = schemeItem.F_Scheme.data[dataIndex] | |||
for (const t of componts) { | |||
// 之后的 t 即表示每个 scheme 项 | |||
t.__valuePath__ = `formreq.${schemeIndex}.formData.${t.id}` | |||
// 以下两个属性暂时用不到 | |||
t.__schemeIndex__ = schemeIndex | |||
t.__dataIndex__ = dataIndex | |||
if (t.type === 'girdtable' && t.table) { | |||
// 数据项是表格的情况 | |||
// 先设置源数据,不然无法获取默认值 | |||
for (const fieldItem of t.fieldsData) { | |||
fieldItem.__sourceData__ = await this.getSourceData(fieldItem) | |||
} | |||
t.__defaultItem__ = await this.getDefaultData(t, prop) | |||
if (formData) { | |||
// 有表单值的情况,从表单值中获取数据 | |||
const val = [] | |||
for (const valueItem of get(formData, `${schemeItem.F_SchemeInfoId}.${t.table}`, | |||
[])) { | |||
const tableItemValue = {} | |||
for (const fieldItem of t.fieldsData.filter(t => t.field)) { | |||
const formDataValue = get(valueItem, fieldItem.field.toLowerCase()) | |||
tableItemValue[fieldItem.field] = await this.convertToFormValue(fieldItem, | |||
formDataValue) | |||
} | |||
val.push(tableItemValue) | |||
} | |||
// useDefault 表示在从 formData 取不到值的时候使用默认值 | |||
if ((!val || val.length <= 0) && useDefault) { | |||
set(formValue, t.__valuePath__, [this.COPY(t.__defaultItem__)]) | |||
} else { | |||
set(formValue, t.__valuePath__, val) | |||
} | |||
} else { | |||
// 无表单值的情况,默认值 | |||
set(formValue, t.__valuePath__, [this.COPY(t.__defaultItem__)]) | |||
} | |||
} else if (t.field) { | |||
// 数据项不是表格的情况 | |||
// 先设置源数据,不然无法获取默认值 | |||
t.__sourceData__ = await this.getSourceData(t) | |||
if (formData) { | |||
// 有表单值的情况,从表单值中获取数据 | |||
const path = | |||
`${schemeItem.F_SchemeInfoId}.${t.table}.${dataIndex}.${t.field.toLowerCase()}` | |||
const formDataValue = get(formData, path) | |||
// useDefault 表示在从 formData 取不到值的时候使用默认值 | |||
if (!formDataValue && useDefault) { | |||
set(formValue, t.__valuePath__, await this.getDefaultData(t, prop)) | |||
} else { | |||
set(formValue, t.__valuePath__, await this.convertToFormValue(t, formDataValue)) | |||
} | |||
} else { | |||
// 无表单值的情况,默认值 | |||
set(formValue, t.__valuePath__, await this.getDefaultData(t, prop)) | |||
} | |||
} | |||
// 权限控制 | |||
const authObj = get(currentNode, `wfForms.${schemeIndex}.authorize.${t.id}`, {}) | |||
t.edit = authObj.isEdit | |||
if (Number(t.isHide) !== 1 && authObj.isLook !== 0) { | |||
// 加入 scheme | |||
scheme.push(t) | |||
// organize、datetime 可能作为其他 organize 或 datetimerange 的依赖项,引用它们 | |||
if (['organize', 'datetime'].includes(t.type)) { | |||
schemeRef[t.id] = t | |||
} | |||
// datetimerange、带有 relation 级联字段的 organize,依赖其他项 | |||
if ((t.type === 'datetimerange' && t.startTime && t.endTime) || (t.type === | |||
'organize' && t.relation)) { | |||
refList.push(t) | |||
} | |||
} | |||
} | |||
} | |||
} | |||
// 依次处理表单关联 | |||
refList.forEach(t => { | |||
if (t.type === 'organize') { | |||
// 处理组件结构级联 | |||
// 给当前组件赋上级级联的值路径 __relationPath__ | |||
const parent = schemeRef[t.relation] | |||
t.__relationPath__ = parent.__valuePath__ | |||
// 给上级级联的组件注册自动重置当前组件的 change 事件 | |||
const relItem = { | |||
type: 'organize', | |||
id: t.id, | |||
path: t.__valuePath__ | |||
} | |||
rel[parent.id] = rel[parent.id] ? rel[parent.id].concat(relItem) : [relItem] | |||
} else if (t.type === 'datetimerange') { | |||
// 处理日期区间 | |||
const start = schemeRef[t.startTime] | |||
const end = schemeRef[t.endTime] | |||
const relItem = { | |||
type: 'datetimerange', | |||
path: t.__valuePath__, | |||
id: t.id, | |||
startPath: start.__valuePath__, | |||
endPath: end.__valuePath__, | |||
} | |||
rel[start.id] = rel[start.id] ? rel[start.id].concat(relItem) : [relItem] | |||
rel[end.id] = rel[end.id] ? rel[end.id].concat(relItem) : [relItem] | |||
} | |||
}) | |||
return { | |||
scheme, | |||
formValue, | |||
rel | |||
} | |||
}, | |||
newguid() { | |||
return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) { | |||
var r = Math.random() * 16 | 0, | |||
v = c == 'x' ? r : (r & 0x3 | 0x8); | |||
return v.toString(16); | |||
}); | |||
}, | |||
/** | |||
* 获取最终需要 POST 的数据 | |||
* 参数:formValue, scheme | |||
* 返回:用于提交的数据 | |||
* | |||
* 遍历 formValue,将其中的表单值依次使用 convertToPostData 这个方法转化为提交值 | |||
*/ | |||
async getPostData(originFormValue, scheme) { | |||
const formValue = this.COPY(originFormValue) | |||
// 依次按照 scheme 项目遍历 | |||
for (const item of scheme) { | |||
if (item.field) { | |||
// 不是表格的情况 | |||
const path = item.__valuePath__ | |||
const val = get(formValue, path) | |||
if (item.type == 'upload') { | |||
// 先生成一个guid | |||
var guid = this.newguid(); | |||
// 取出当前列对应的labelId | |||
var labeId = item.id | |||
// 从缓存取出当前审批流程所有的guid | |||
var guids = JSON.parse(uni.getStorageSync('guids')) | |||
if (guids&&JSON.stringify(guids)!=='{}') { | |||
guid = guids[labeId] | |||
} | |||
} | |||
const result = await this.convertToPostData(item, val, originFormValue, scheme, guid) | |||
set(formValue, path, result) | |||
} else if (item.table && item.fieldsData) { | |||
// 是表格的情况 | |||
const tableValue = get(formValue, item.__valuePath__, []) | |||
for (let valueIndex = 0; valueIndex < tableValue.length; ++valueIndex) { | |||
for (const schemeItem of item.fieldsData) { | |||
const path = `${item.__valuePath__}.${valueIndex}.${schemeItem.field}` | |||
const val = get(formValue, path) | |||
const result = await this.convertToPostData(schemeItem, val, originFormValue, scheme, | |||
guid) | |||
set(formValue, path, result) | |||
} | |||
} | |||
} | |||
} | |||
formValue.formreq.forEach(t => { | |||
t.formData = JSON.stringify(t.formData) | |||
}) | |||
formValue.formreq = JSON.stringify(formValue.formreq) | |||
return formValue | |||
}, | |||
/** | |||
* 获取流程信息 | |||
* 参数: { code, processId, taskId } | |||
* | |||
*/ | |||
async fetchProcessInfo({ | |||
code, | |||
processId, | |||
taskId | |||
}) { | |||
const url = processId ? 'learun/adms/newwf/processinfo' : 'learun/adms/newwf/scheme' | |||
const reqObj = { | |||
processId | |||
} | |||
if (taskId) { | |||
reqObj.taskId = taskId | |||
} | |||
const data = processId ? reqObj : code | |||
const result = await this.HTTP_GET(url, data) | |||
if (!result) { | |||
return {} | |||
} | |||
if (result.info) { | |||
result.info.Scheme = JSON.parse(result.info.Scheme) | |||
} else if (result.F_Content) { | |||
result.F_Content = JSON.parse(result.F_Content) | |||
} | |||
return result | |||
}, | |||
/** | |||
* 从 processInfo 流程信息中,提取出 currentNode | |||
* 参数: processInfo | |||
* | |||
*/ | |||
getCurrentNode(processInfo) { | |||
if (processInfo.info) { | |||
return processInfo.info.Scheme.nodes.find(t => t.id === processInfo.info.CurrentNodeId) | |||
} else if (processInfo.F_Content) { | |||
return processInfo.F_Content.nodes.find(t => t.type === 'startround') | |||
} | |||
return {} | |||
}, | |||
/** | |||
* 拉取表单的 schemeData | |||
* 参数: currentNode | |||
* | |||
* 从当前节点 currentNode 中提取出表单 id,然后自 API 地址 /form/scheme 中拉取表单数据并返回 | |||
*/ | |||
async fetchSchemeData(currentNode, currentTask, type) { | |||
const { | |||
wfForms | |||
} = currentNode | |||
const data = wfForms.filter(t => t.formId).map(t => ({ | |||
id: t.formId, | |||
ver: '' | |||
})) | |||
const schemeData = await this.HTTP_GET('learun/adms/form/scheme', data) | |||
return schemeData || {} | |||
}, | |||
/** | |||
* 拉取表单的 formData | |||
* 参数: currentNode, keyValue | |||
* | |||
* 提取当前节点信息、表单主键信息,从 API 地址 /form/data 中拉取表单数据 | |||
*/ | |||
async fetchFormData({ | |||
wfForms | |||
}, keyValue) { | |||
const reqData = wfForms | |||
.filter(t => t.formId) | |||
.map(t => ({ | |||
schemeInfoId: t.formId, | |||
processIdName: t.field, | |||
keyValue | |||
})) | |||
const formData = await this.HTTP_GET('learun/adms/form/data', reqData) | |||
return formData || {} | |||
}, | |||
async fetchFolderkeyData(currentNode, keyValue) { | |||
const { | |||
wfForms | |||
} = currentNode | |||
const reqData = wfForms | |||
.filter(t => t.formId) | |||
.map(t => ({ | |||
id: t.formId, | |||
ver: '', | |||
schemeInfoId: t.formId, | |||
processIdName: t.field, | |||
keyValue | |||
})) | |||
const folderkeyData = await this.HTTP_GET('learun/adms/form/folderkey', reqData) | |||
return folderkeyData || {} | |||
}, | |||
} | |||
} |
@@ -14,6 +14,7 @@ | |||
<l-input title="住宿费" :value="formData.StuNo" placeholder="请填写" right /> | |||
<l-input title="应缴合计" :value="formData.StuNo" placeholder="请填写" right /> | |||
<view class="btn" @click="submit">支 付</view> | |||
<view class="btn" @click="lookInvoice">查看发票</view> | |||
</view> | |||
</template> | |||
@@ -44,6 +45,9 @@ export default { | |||
this.TOAST('缴费成功'); | |||
} | |||
}); | |||
}, | |||
lookInvoice(){ | |||
this.NAV_TO("./payInvioce") | |||
} | |||
}, | |||
created() { | |||
@@ -0,0 +1,63 @@ | |||
<template> | |||
<view> | |||
<view class="menu"> | |||
<view v-for="item in menuOptions" :key="item.active" :class="{menu_item:true,active:activeIndex==item.active}" @click="()=>{activeIndex = item.active;activeIndexChange(item)}"> | |||
{{item.label}} | |||
</view> | |||
</view> | |||
<iframe v-show="activeIndex == 1" src="https://www.baidu.com"></iframe> | |||
<iframe v-show="activeIndex == 2" src="https://www.baidu.com"></iframe> | |||
</view> | |||
</template> | |||
<script> | |||
export default { | |||
data() { | |||
return { | |||
menuOptions:[ | |||
{active:1,label:"123"}, | |||
{active:2,label:"456"} | |||
], | |||
activeIndex:1, | |||
} | |||
}, | |||
methods: { | |||
// 选项卡改变 | |||
activeIndexChange(item){ | |||
// | |||
} | |||
}, | |||
} | |||
</script> | |||
<style lang="scss" scoped> | |||
.menu{ | |||
display: flex; | |||
justify-content: space-between; | |||
background-color: #fff; | |||
border: 1px solid #E4E7ED; | |||
.menu_item{ | |||
flex: 1; | |||
text-align: center; | |||
box-sizing: border-box; | |||
line-height: 36px; | |||
border: 1px solid #E4E7ED; | |||
position: relative; | |||
} | |||
.menu_item.active::after{ | |||
content: ""; | |||
display: block; | |||
background-color: #409EFF; | |||
position: absolute; | |||
width: 50%; | |||
height: 2px; | |||
left: 0;right: 0; | |||
margin: auto; | |||
bottom: 0; | |||
} | |||
} | |||
iframe{ | |||
width: 100%; | |||
height: calc(100vh - 40px); | |||
} | |||
</style> |
@@ -0,0 +1,47 @@ | |||
<template> | |||
<view> | |||
<tki-qrcode | |||
style="display: flex;justify-content: center;margin-top: 18px;" | |||
ref="qrcode" | |||
val="http://localhost:8080/#/pages/onlienpay/payqrcode?id=15641654" | |||
:size="300" | |||
:onval="true" | |||
:loadMake="true" | |||
/> | |||
<view class="btn" @click="submit">查询结果</view> | |||
<view class="btn bg-white" @click="cancel">取消</view> | |||
</view> | |||
</template> | |||
<script> | |||
export default { | |||
data() { | |||
return { | |||
payData:"", | |||
} | |||
}, | |||
methods: { | |||
getPayData(id){ | |||
this.LOADING(); | |||
this.HTTP_GET('StuInfoFresh/saveStuInfoFresh', {id},).then(res => { | |||
this.HIDE_LOADING(); | |||
if (res) { | |||
this.payData = res | |||
} | |||
}); | |||
}, | |||
cancel(){ | |||
this.NAV_BACK() | |||
} | |||
}, | |||
onLoad({id}) { | |||
this.getPayData(id) | |||
} | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
.bg-white{ | |||
background-color: gray; | |||
} | |||
</style> |
@@ -36,7 +36,7 @@ | |||
<view v-if="weekData.rows.length == 0">暂时没有信息</view> | |||
<view v-if="weekData.rows.length != 0"> | |||
<view | |||
:class="timeTableClass(k.Sort)" | |||
:class="[timeTableClass(k.Sort)]" | |||
class="timeTableLi" v-for="(k, i) in weekData.rows" | |||
:key="k.StuNo" | |||
@click="tapTimeTable(i, timeTableClass(k.Sort))" | |||
@@ -46,7 +46,7 @@ | |||
</view> | |||
</view> | |||
</view> | |||
<view class="timeTableAlert" :class="flag? 'active' : ''"> | |||
<view class="timeTableAlert" :class="[flag? 'active' : '']"> | |||
<view class="timeTableAlertTop"> | |||
<view class="timeTableAlertT">{{ weekData.rows[ind].StuName }}</view> | |||
<view class="timeTableAlertTxt">学号: {{ weekData.rows[ind].StuNo }} </view> | |||
@@ -55,7 +55,7 @@ | |||
<view | |||
v-for="(n, i) in Statue" | |||
:key="i" | |||
:class="n.className == className? 'active ' + n.className : n.className" | |||
:class="[n.className == className? 'active ' + n.className : n.className]" | |||
class="timeTableAlertLi" | |||
@click="tapStatus(i)" | |||
><text></text>{{ n.txt }}</view> | |||
@@ -491,6 +491,7 @@ export default{ | |||
text-align: center; | |||
font-size: 14px; | |||
color: #1a1a1a; | |||
background-color: #ffffff; | |||
} | |||
.timeTableAlertLi.active { | |||
@@ -500,8 +501,4 @@ export default{ | |||
.timeTableAlertLi:nth-child(2n) { | |||
background-color: #fbfdff; | |||
} | |||
.timeTableAlertLi:nth-child(2n - 1) { | |||
background-color: #ffffff; | |||
} | |||
</style> |
@@ -72,7 +72,6 @@ export default { | |||
'加载数据时出错' | |||
).then( res => { | |||
this.HIDE_LOADING() | |||
// console.log(res) | |||
if (res == null || JSON.stringify(res) == '{}') { | |||
_this.flag = false; | |||
return; | |||
@@ -28,10 +28,10 @@ | |||
<view class="tSec2Box"> | |||
<view class="tSec2Con" v-for="(items, i) in weekArr" :key="items.num" v-show="i == num"> | |||
<view class="tSec2List"> | |||
<view v-if="dataArr[i+1].length <= 0" class="tSec2ListLi"> | |||
<view v-if="dataArr[i+1]&&dataArr[i+1].length <= 0" class="tSec2ListLi"> | |||
<view class="noHtml">该时间段没有课表</view> | |||
</view> | |||
<view v-if="dataArr[i+1].length > 0"> | |||
<view v-if="dataArr[i+1]&&dataArr[i+1].length > 0"> | |||
<view class="tSec2ListLi" v-for="(k, j) in dataArr[i+1]" :key="j" @click="classTap(k)"> | |||
<view class="tSec2ListL">第 {{ k.jc }} 节</view> | |||
<view class="tSec2ListR"> | |||
@@ -25,13 +25,13 @@ | |||
</view> | |||
<!-- 账户密码表单 --> | |||
<l-input v-if="ready" v-model="username" placeholder="手机号 / 账号" left> | |||
<l-input v-if="ready" v-model="username" placeholder="身份证号" left> | |||
<l-icon slot="title" type="people" /> | |||
</l-input> | |||
<l-input v-if="ready" v-model="password" placeholder="请输入身份证后八位" password left> | |||
<l-icon slot="title" type="lock" /> | |||
</l-input> | |||
<l-button @click="login(null)" size="lg" color="blue" class="margin-top-sm block" block>确 认</l-button> | |||
<l-button v-if="ready" @click="loginClick(null)" size="lg" color="blue" class="margin-top-sm block" block>确 认</l-button> | |||
<view class="otherLogin"> | |||
<navigator url="/pages/login" class="textBtn">常规登陆</text></navigator> | |||
</view> | |||
@@ -68,11 +68,14 @@ | |||
</template> | |||
<script> | |||
import moment from 'moment'; | |||
export default { | |||
data() { | |||
return { | |||
username: '', | |||
password: '', | |||
code:'', | |||
ready: false, | |||
showApiRootSelector: false, | |||
@@ -84,6 +87,9 @@ export default { | |||
}, | |||
async onLoad() { | |||
if(this.getHashSearchParam("code")){ | |||
this.code = this.getHashSearchParam("code") | |||
} | |||
await this.init() | |||
}, | |||
@@ -101,15 +107,103 @@ export default { | |||
this.username = account.username | |||
this.password = account.password | |||
} | |||
this.ready = true | |||
// this.ready = true | |||
this.loginInit() | |||
}, | |||
getHashSearchParam(key) { | |||
let search = location.search | |||
let array = [] | |||
if(search){ | |||
search = search.substring(1) | |||
array = search.split("&") | |||
let res = array.find((item)=>item.split("=")[0] == key) | |||
return res.split("=")[1] | |||
} | |||
return '' | |||
}, | |||
// 点击新用户注册 | |||
signUp() { | |||
this.NAV_TO('/pages/signup') | |||
}, | |||
// 切换后台地址 | |||
loginInit(){ | |||
if (this.code) { | |||
this.LOADING("加载中...") | |||
this.HTTP_POST("weixinapi/getweixinaccess_token?code="+this.code,null).then(success=>{ | |||
this.HIDE_LOADING() | |||
if(!success){ | |||
location.href = "http://" + window.location.host; | |||
return | |||
} | |||
if(success.logined){ | |||
// var logininfo = { | |||
// account: account, | |||
// token: success.baseinfo.token, | |||
// date: moment().format('yyyy-MM-dd hh:mm:ss') | |||
// }; | |||
this.SET_STORAGE("token",success.baseinfo.token) | |||
// this.SET_STORAGE("logininfo",logininfo) | |||
// this.SET_STORAGE("userinfo",success) | |||
location.href = "http://" + window.location.host + "/#/pages/my/newpassword"; | |||
// location.href = "http://" + window.location.host; | |||
}else{ | |||
this.ready = true | |||
this.openid = success.openid | |||
} | |||
}) | |||
} else { | |||
this.HIDE_LOADING(); | |||
this.HTTP_GET("weixinapi/weixinconfig").then(success=>{ | |||
if(!success){ | |||
return | |||
} | |||
window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + success.appid + "&redirect_uri=" + encodeURIComponent('http://' + window.location.host + '/#/pages/weixinLogin') + "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"; | |||
}) | |||
} | |||
}, | |||
loginClick(){ | |||
// 点击登录 | |||
// 账号密码登录时,验证输入,输入有误则返回 | |||
if (!this.check()) { | |||
return | |||
} | |||
let up = true | |||
var postData = { | |||
username: this.username, | |||
password: this.password, | |||
openid: this.openid, | |||
up: up | |||
}; | |||
this.LOADING("正在登录,请稍后") | |||
this.HTTP_POST("weixinapi/loginbyidcard", postData).then(success=>{ | |||
this.HIDE_LOADING() | |||
if(!success){ | |||
return | |||
} | |||
var logininfo = { | |||
account: this.username, | |||
token: success.baseinfo.token, | |||
date: moment().format('yyyy-MM-dd hh:mm:ss') | |||
}; | |||
this.SET_STORAGE("token",success.baseinfo.token) | |||
// this.SET_STORAGE('logininfo', logininfo); | |||
// this.SET_STORAGE('userinfo', success); | |||
this.username = "" | |||
this.password = "" | |||
if (success.pwd === true) { | |||
this.SET_STORAGE('pwd', true); | |||
this.TOAST("绑定失败!您的密码不满足强度要求,请您先修改密码后再执行系统其他操作"); | |||
} else { | |||
this.SET_STORAGE('pwd', false); | |||
} | |||
location.href = "http://" + window.location.host + "/#/pages/my/newpassword"; | |||
}) | |||
}, | |||
// 切换后台地址 | |||
changeApiRoot(newIndex) { | |||
const newApiRoot = this.apiRootList[newIndex] | |||
this.currentApiRoot = newApiRoot | |||
@@ -272,7 +366,7 @@ page { | |||
.otherLogin{ | |||
display: flex; | |||
justify-content: right; | |||
justify-content: flex-end; | |||
.textBtn{ | |||
width: 100px; | |||
color: #606266; | |||
@@ -170,6 +170,7 @@ export default { | |||
this.HTTP_GET('StuInfoFresh/saveStuInfoFresh', this.queryData).then(res => { | |||
this.HIDE_LOADING(); | |||
if (res) { | |||
this.NAV_TO("/pages/my/newpassword") | |||
this.TOAST('保存成功'); | |||
} | |||
}); | |||
@@ -20,6 +20,21 @@ | |||
<SccProvider> | |||
</SccProvider> | |||
<TargetFrameworkProfile /> | |||
<PublishUrl>publish\</PublishUrl> | |||
<Install>true</Install> | |||
<InstallFrom>Disk</InstallFrom> | |||
<UpdateEnabled>false</UpdateEnabled> | |||
<UpdateMode>Foreground</UpdateMode> | |||
<UpdateInterval>7</UpdateInterval> | |||
<UpdateIntervalUnits>Days</UpdateIntervalUnits> | |||
<UpdatePeriodically>false</UpdatePeriodically> | |||
<UpdateRequired>false</UpdateRequired> | |||
<MapFileExtensions>true</MapFileExtensions> | |||
<ApplicationRevision>0</ApplicationRevision> | |||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion> | |||
<IsWebBootstrapper>false</IsWebBootstrapper> | |||
<UseApplicationTrust>false</UseApplicationTrust> | |||
<BootstrapperEnabled>true</BootstrapperEnabled> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||
<PlatformTarget>x64</PlatformTarget> | |||
@@ -138,5 +153,17 @@ | |||
<Name>Learun.DataBase</Name> | |||
</ProjectReference> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1"> | |||
<Visible>False</Visible> | |||
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 和 x64%29</ProductName> | |||
<Install>true</Install> | |||
</BootstrapperPackage> | |||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> | |||
<Visible>False</Visible> | |||
<ProductName>.NET Framework 3.5 SP1</ProductName> | |||
<Install>false</Install> | |||
</BootstrapperPackage> | |||
</ItemGroup> | |||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |||
</Project> |