脚本控制

        
基本查询
--LINKCELLVALID              编辑数据时进行合法性校验
--LINKROWVALID               在编辑数据时进行合法性校验,校验不通过时,不允许离开正在编辑的行

--LINKLOADDATAIMMEDIATE      打开功能时直接加载数据

--DISABLEINPUTIMEMODE        是否禁用输入框的输入法

--LINKDATAMINEOVERVIEW       是否需要在当前界面显示数据挖掘内容,通过其他选项控制显示模式
    --LINKDATAMINEOVERVIEW,VERTICAL,50,AUTOREFRESH
    --LINKDATAMINEOVERVIEW,H,40,NOAUTOREFRESH
--LINKDATAMINELAYOUT         是否需要在当前界面分列式显示数据挖掘内容
    --LINKDATAMINELAYOUT:60,40

--LINKMULTIROWS              用来标记在进行附加模型处理时,是否需要根据基本脚本中的多行记录进行逐行处理

--LINKTOPBANDHEADERONLY      多层数据时,仅显示第一层的列标题
--LINKNOFILTER               隐藏表格的数据过滤行
--LINKNOSUBFILTER            多层数据时,隐藏除第一层之外的层级的过滤行
--LINKNOGROUP                不显示分组

--LINKREFRESH                开启数据挖掘完成后,是否自动刷新原始模型的数据
--LINKSHOWPROCESS            多行处理时,显示执行进度
--LINKAUTHORIZE              无需登录即可执行的模型

--LINKGANTTVIEW              将数据以甘特图显示
--LINKCALENDARVIEW           将数据以日历视图显示
--LINKLOGICALDAY=            设置日历视图显示是的每天其实和结束时间
--LINKPIVOTGRID              使用数据透视方式显示数据
--LINKNOEXPORT               控制数据只可以查看,不可导出

--LINKDATATRANSPOSITION      对数据进行转置处理
--LINKDETAILLIST             增加显示子模型的内容
    --LINKDETAILLIST(EXAMPLE90X,10,{0},P2,P3)

添加记录
--LINKADDNEWROWS             用来处理直接添加记录,启用时可以直接在表格中显示添加记录行
--LINKDATAMINE~              表格的添加按钮,启动LINKDATAMINE选择保存模式,按数据挖掘配置打开一个挖掘模型进行操作

编辑记录
--LINKEDITMODE               数据查询后,直接进入编辑模式,并保持在编辑模式
--LINKKEEPORIGINAL           标记脚本中的公式不被替换
--LINKAUTOREPLACEEMPTYCOLUMNS  标记是否将未提供的字段替换为空白
--LINKBATCHEDIT              判断是否默认启动批量编辑模式,批量编辑模式时,在头部的固定单元格输入数据,批量填写可见的所有行对应列
--LINKDATAAUTOSAVE           判断在离开时是否自动保存数据, 默认为需要用户确认,启用该功能时无需确认直接保存
--LINKROWDOUBLECLICK         触发的行双击事件,触发对当前行的编辑操作
--LINKINPUTBOX               功能上是否显示InputBox,可用于扫码输入,自动将扫描的内容(逗号分割)拆分到参数列表,并自动加载
--LINKCOPYLINE               添加记录时是否复制上一行内容
--LINKROWENTERACTION         非编辑状态下,用回车键处理当前行记录的编辑操作
--LINKSAVEONENTERKEY         判断是否启用回车保存模式
--LINKAUTOCLOSE              编辑保存之后,自动关闭当前窗口
--LINKJSONDATASUBMIT         以JToken的方式提交完整数据,做一次性数据提交处理,配合sql json数据处理脚本实现
--LINKSHOWPROCESS            数据保存时显示进度
--LINKCALLFUNCTION           默认CallFunction仅针对数据处理,添加、编辑、删除动作时,如果有 --LINKCALLFUNCTION 同样触发执行CALLFUNCTION
--LINKREQUIRED:              标记必填字段

删除记录

数据处理
--LINKREFRESH                附加模型处理完成后,是否触发原始模型的数据刷新
    --LINKREFRESH:LINKFORM.TLDTRP#9
                                输入处理完成后,按指定的模型进行数据加载刷新
--LINKSHOWPROCESS            是否需要显示进度
--LINKSHOWACTION             是否需要显示执行之后的进度,使用302附加模型显示进度执行情况,用于复杂数据处理
--LINKWAITTASKDONE           启动服务端执行的任务
--LINKUPDATESCRIPT           在数据处理脚本,如果标记了 --LINKUPDATESCRIPT,同时该模型存在“数据编辑”脚本,则先执行数据编辑脚本,再继续进行数据处理

--LINKUPLOAD_FILETYPE        附件上传时指定文件类型
--LINKUPLOAD_PATHASSIGN      附件上传时设定保存路径
--LINKUPLOAD_KEEPFILENAME     附件上传时保持文件名不变

--LINKSERVERTASK             启动服务端执行的任务
--LINKEXECOUTPUT             根据存储过程返回的 RPTMSG RPTFLG 进行后续处理

--LINKACTIONPUSH             登记一个任务
    --LINKACTIONPUSH(PRIORITY~JOBKEY~ACTIONUSER~ACTIONDM~ACTIONPARA)
    --LINKACTIONPUSH(10~PRINT~RANDY~JLHPDA3550X#701~#P1#,#P2#,#P3#)

标签脚本
--LINKBACKFUNC:              标签打印完成后,触发模型刷新

通用脚本
--LINKSHOWEXCEPTION          强制显示例外出错信息
--LINKTIMEOUT:               设置执行的超时时间
--LINKCONN@                  指定不同的数据连接执行脚本
--LINKIDACTION               当前动作的唯一动作序列号
        
    

脚本内容替换

        

脚本内容替换
##LINKECHARTDATASET##        数据集内容
##LINKLEVELDATA##            Json格式多层数据集

#TotalLINKScript.()
        '处理#TOTALLINKSCRIPT.10.0(C1,P1,C2,P2)#类型的信息,用统一管理的模型脚本进行替代
        '括号内的内容,表示用实际内容替换脚本中的变量('{xxx}'表示需要替换的变量)

#LINKLOCATIONJSON#           完整地理位置信息,
#LINKLOCATION#               简洁地理位置信息

#LINKJSON{...}#              Json对象内容替换
#LINKJSONVALUE:              提取Json对象的内容

'替换脚本中的 #LOGIN_USER# 为当前的用户代码
s = s.Replace("#LOGIN_USER#", DM.LinkVar.UserCode)
s = s.Replace("#LOGIN_NAME#", DM.LinkVar.UserName)
s = s.Replace("#LOGIN_LAN#", DM.LinkVar.LangCode)

'替换脚本中的 #LOGIN_ROLE# 为当前的用户的角色代码
s = s.Replace("#LOGIN_ROLE#", DM.LinkVar.Role)

'替换脚本中的 #LOGIN_COMPUTER# 为当前的机器名
s = s.Replace("#LOGIN_COMPUTER#", DM.LinkVar.DevID)

'替换脚本中的 #LOGIN_ID# 为当前的机器名
s = s.Replace("#LOGIN_ID#", DM.LinkVar.LoginID) ' DM.LinkToken)

'替换脚本中的 #CURR_MODELCODE# 为当前的模型代码
s = s.Replace("#CURR_MODELCODE#", DM.ModelCode)

'替换脚本中的 #CURR_MODELNUM# 为当前的模型编号
s = s.Replace("#CURR_MODELNUM#", DM.ModelNumber.ToString)

'替换脚本中的 #ATTACH_MODELCODE# 为当前的模型编号
s = s.Replace("#ATTACH_MODELCODE#", DM.AttachModelCode)

'替换脚本中的 #LINKSERVER# 为设定的默认服务路径
s = s.Replace("#LINKSERVER#", DM.LinkVar.Server)

'替换脚本中的 #LINKCUSCODE# 为设定的客户代码
s = s.Replace("#LINKCUSCODE#", DM.LinkVar.CusCode)

'2018-03-27
'替换脚本中的 #LINKID_ACTION# 为统一的GUID号码,每次执行附加模型的动作
s = s.Replace("#LINKID_ACTION#", DM.LinkIdAction)

'2018-08-29
'替换脚本中的 #LINKID_RESULT# 为统一的GUID号码,每次执行附加模型的动作
s = s.Replace("#LINKID_RESULT#", DM.LinkIdResult)

'替换脚本中的 #LINKDB# 为LINK数据库
s = s.Replace("#LINKDB#", BASE_LINKDB)

'替换当前用户的Token
s = s.Replace("#LINKTOKEN#", sDMToken)

'处理 LINKURLPWD
s = s.Replace("#LINKURLPWD#", MLTShared.GetLinkURLPwd)
        
    

正则表达式内容替换

        
脚本替换时按照如下顺序进行逐个处理,越早碰到越提前替换

'此模式用于管理重复使用的脚本,正则表达式使用非贪婪匹配模式
Dim regPattern As String = "#TotalLINKScript\.(\d+)\.([^)]*)\(([^)]*)\)#"

处理对应SYSUSER表中的自定义字段
Dim regPattern As String = "\#SYSUSER\.[\S ]+?\#"

多语言替换处理
Dim regPattern As String = "lang:\{[^}]*?\}"

日期时间通用格式
Dim regPattern As String = "\#LINKDATE\([\S ]+?\)\#"

处理需要加密的数据
Dim regPattern As String = "\#LINKENCRYPT\([\S ]+?\)\#"

不同用户自定义的变量代换
Dim regPattern As String = "\#LC\.[\S ]+?\#"

处理指定用户的信息
Dim regPattern As String = "\#LINKUSER\([\S ]+?\)\.[\S ]+?\#"

处理指定用户的Token信息
Dim regPattern As String = "\#LINKTOKEN\([\S ]+?\)\#"

处理对应_LINKSYS_模型的自定义字段
Dim regPattern As String = "\#_LINKSYS_\.\d+\.[\S ]+?\#"

LINKFUNC权限管理模式的判断
Dim regPattern As String = "\#LINKACTIVITY\([\S ]+?\)\#"

公式替换
Dim regPattern As String = "\#LINKFORMULA[\S\s]+?\#"

从 Json Array 中提取逗号分隔的字符串的信息
Dim regPattern As String = "\#LINKARRAYITEM(\([\s\S]+?\)){2}\#"

处理单据序列号
Dim regPattern As String = "\#LINKDOCNUM\.[\S ]+?\#"

动态处理单据序列号,根据第一个参数判断,有值时不产生新的单据号
Dim regPattern As String = "\#LINKDOCNUM\([\S ]+?\)\#"

处理单据序列号
Dim regPattern As String = "\#LINKDOCNUMBY\([\S ]+?\)\#"

用脚本定义的执行结果替换
Dim regPattern As String = "\#LINKFUNC\.[\S ]+?\#"

保存用户临时变量
Dim regPattern As String = "\#LINKSETVAL\([\S ]+?\)\#"

读取用户临时变量
Dim regPattern As String = "\#LINKGETVAL\([\S ]+?\)\#"

从完整路径中获取纯文件名
Dim regPattern As String = "\#LINKFILENAME\([\S ]+?\)\#"

设备信息采集
Dim regPattern As String = "\#LINKIOT\.[\S]+\.[\S]+?\#"

InfluxDB中的采集信息获取
Dim regPattern As String = "\#LINKINFLUX\([\S ]+?\)\#"

LINKSCRIPTGET/LINKSCRIPTRUN,执行脚本并替换信息
Dim regPattern As String = "\#LINKSCRIPT[\S\s]+\#"

处理 SIGNLIST 审批时的条件,返回提示信息,用于控制工作流
Dim regPattern As String = "\#LINKSIGNSTEPSETTING\([\S ]+?\)\#"

RSA加密
Dim regPattern As String = "\#LINKRSAENCRYPT\([\S ]+?\)\#"

Json格式多层数据
Dim regPattern As String = "\#LINKLEVELDATA\([\S ]+?\)\#"

XML格式多层数据
Dim regPattern As String = "\#LINKXMLDATA\([\S ]+?\)\#"
        
    

特殊Token替换

        
'处理微信TOKEN
If s.Contains("#LINKWEIXINTOKEN#") Then
    BASE_WeixinSetting.token = MLTMessage.weixinToken(BASE_WeixinSetting.corpid, BASE_WeixinSetting.corpsecret)
    s = s.Replace("#LINKWEIXINTOKEN#", BASE_WeixinSetting.token)
End If

'处理钉钉TOKEN
If s.Contains("#LINKDINGTALKTOKEN#") Then
    BASE_DingtalkSetting.token = MLTMessage.dingtalkToken(BASE_DingtalkSetting.corpid, BASE_DingtalkSetting.corpsecret)
    s = s.Replace("#LINKDINGTALKTOKEN#", BASE_DingtalkSetting.token)
End If

'处理百度AI TOKEN
If s.Contains("#LINKBAIDUAITOKEN") Then
    Call MLTBaiduAI.InitBaiduAIToken()
    s = s.Replace("#LINKBAIDUAITOKEN#", BASE_LinkBaiduAI.token)
End If

'处理飞书TOKEN
If s.Contains("#LINKFEISHUTOKEN") Then
    Call MLTFeishu.InitFeishuToken()
    s = s.Replace("#LINKFEISHUTOKEN#", BASE_LinkFeishu.token)
End If

'处理需要加密的数据
If s.Contains("#LINKENCRYPT(") Then
    Dim regPattern As String = "\#LINKENCRYPT\([\S ]+?\)\#"
End If
        
    

路径替换

        
#LINKLOCALPATH# 本地路径
public static string AppData = "";

public static string DataExportPath = "";
public static string LogPath = "";
public static string LayoutPath = "";
#LINKREPORTPATH#
public static string ReportPath = "";
public static string ImagePath = "";
public static string UploadPath = "";
public static string IoTSettingPath = "";
public static string DownloadPath = "";

'本地几个特殊路径的位置
LocalPath.AppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
LocalPath.DownloadPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "\Downloads"

If LocalPath.AppData.EndsWith("\") = False Then
    LocalPath.AppData = LocalPath.AppData & "\"
End If

LocalPath.DataExportPath = Path.Combine(LocalPath.AppData, "TotalLink\Export")
LocalPath.LogPath = Path.Combine(LocalPath.AppData, "TotalLink\Log")
LocalPath.LayoutPath = Path.Combine(LocalPath.AppData, "TotalLink\Layout")
LocalPath.ReportPath = Path.Combine(LocalPath.AppData, "TotalLink\Reports")
LocalPath.ImagePath = Path.Combine(LocalPath.AppData, "TotalLink\Images")
LocalPath.UploadPath = Path.Combine(LocalPath.AppData, "TotalLink\Upload")
LocalPath.IoTSettingPath = Path.Combine(LocalPath.AppData, "TotalLink\IoTSettings")

IIS初始化路径
LocalPath.AppData = System.Web.HttpContext.Current.Server.MapPath("~");

LocalPath.DataExportPath = Path.Combine(LocalPath.AppData, "Files\\Export");
LocalPath.LogPath = Path.Combine(LocalPath.AppData, "Files\\Log");
LocalPath.LayoutPath = Path.Combine(LocalPath.AppData, "Files\\Layout");
LocalPath.ReportPath = Path.Combine(LocalPath.AppData, "Files\\Reports");
LocalPath.ImagePath = Path.Combine(LocalPath.AppData, "Files\\Images");
LocalPath.UploadPath = Path.Combine(LocalPath.AppData, "Files\\Upload");
LocalPath.IoTSettingPath = Path.Combine(LocalPath.AppData, "Files\\IoTSettings");
//2025年1月26日,IIS初始化时,设置BASE_ReportPath与LocalPath.ReportPath相同
MultiSoft.Globle.BASE_ReportPath = LocalPath.ReportPath;
        
    

时间日期替换

        
s = s.Replace("#LINK_TODAY#", Now.ToString("yyyy-MM-dd"))
s = s.Replace("#LINK_YESTERDAY#", Now.AddDays(-1).ToString("yyyy-MM-dd"))
s = s.Replace("#LINK_TOMORROW#", Now.AddDays(1).ToString("yyyy-MM-dd"))

s = s.Replace("#LINK_THISYEAR#", Now.ToString("yyyy"))
s = s.Replace("#LINK_THISYEAR2#", Now.ToString("yy"))
s = s.Replace("#LINK_THISMONTH#", Now.ToString("MM"))
s = s.Replace("#LINK_THISMONTH4#", Now.ToString("yyMM"))

s = s.Replace("#LINK_THISYEARMONTH#", Now.ToString("yyyy-MM"))
s = s.Replace("#LINK_THISYEARMONTH6#", Now.ToString("yyyyMM"))

s = s.Replace("#LINK_FIRSTDAY_THISMONTH#", Now.ToString("yyyy-MM-01"))
s = s.Replace("#LINK_LASTDAY_THISMONTH#", New Date(Now.AddMonths(1).Year, Now.AddMonths(1).Month, 1).AddDays(-1).ToString("yyyy-MM-dd"))

s = s.Replace("#LINK_LASTYEAR#", Now.AddYears(-1).ToString("yyyy"))
s = s.Replace("#LINK_LASTMONTH#", Now.AddMonths(-1).ToString("MM"))

s = s.Replace("#LINK_LASTYEARMONTH#", Now.AddYears(-1).ToString("yyyy-MM"))
s = s.Replace("#LINK_LASTYEARMONTH6#", Now.AddYears(-1).ToString("yyyyMM"))

s = s.Replace("#LINK_FIRSTDAY_LASTMONTH#", Now.AddMonths(-1).ToString("yyyy-MM-01"))
s = s.Replace("#LINK_LASTDAY_LASTMONTH#", New Date(Now.Year, Now.Month, 1).AddDays(-1).ToString("yyyy-MM-dd"))

s = s.Replace("#LINK_TIMETICKS#", Now.Ticks.ToString)

s = s.Replace("#LINK_TODAY8#", Now.ToString("yyyyMMdd"))
s = s.Replace("#LINK_TIMESTAMPMS#", LinkSharedFuns.ToUnixTimeMilliseconds(Now).ToString)
s = s.Replace("#LINK_TIMESTAMPS#", LinkSharedFuns.ToUnixTimeSeconds(Now).ToString)

s = s.Replace("#LINK_TIMEHMS#", Now.ToString("HH:mm:ss"))
s = s.Replace("#LINK_TIMEHM#", Now.ToString("HH:mm"))

s = s.Replace("#LINK_FULLTIME#", Now.ToString("yyyy-MM-dd HH:mm:ss.fff"))

正则表达式替换处理
\#LINKDATE\([\S ]+?\)\# 
        
    

ModelSetting

        
{
    "DataScript": {
        //编辑脚本
        "UpdateScript": { 
            //可编辑列
            "EditCols": [ 
                "LoginUser",
                "Name",
                "Role",
                "Email",
                "Tel",
                "DINGtalkID",
                "WeixinID",
                "PWD",
                "UDF001",
                "DOCGRP",
                "LOADDROPVALIDSITE",
                "LOADDROPVALIDFAC",
                "LOADDROPVALIDDEPT",
                "ACTIVEFLAG",
                "MANAGER1",
                "PORTALCODE"
            ],
            //编辑列对应的开窗选择模型
            "EditValueList": { 
                "LOADDROPVALIDSITE": "LINKSITE#1",
                "LOADDROPVALIDFAC": "SYSUSER1X.FAC#10",
                "LOADDROPVALIDDEPT": "SYSUSER1X.DEPT#10",
                "Role": "SYSUSER1X.ROLE#10"
            }
        },
        //当前表格的数据保存前,根据需要先保存其他内容
        "BeforeSaveAction": { 
            "dmCode": "TEST011X",
            "dmNum": 700
        },
        //当前表格的数据保存后,自动触发相关内容的保存
        "AfterSaveAction": { 
            "dmCode": "TEST011X",
            "dmNum": 701
        }
    },
    //附加模型的逻辑执行前,先按模型保存数据
    "GridDataSave": [ 
        "TMESAPS0110X#710",
        "TMESAPS0110X#711",
        "TMESAPS01#10"
    ],
    //数据选择弹窗大小控制,相对屏幕的比例(基数为1),默认为0.6,0.6
    "WindowSize": [
        0.5,
        0.5
    ],
    "leveldatasetting": {
        //每一层子节点的名称,默认为 children
        "children": "days",
        //每一层不显示的字段列表,除最后一层外id列需要保留
        "hidecols": [
            "",
            "pid"
        ],
        //是否需要产生一个节点的key
        "linktreenodekey": false
    },
    //对应列启用双击挖掘
    "DoubleClickDataMine": [
        {
            "ITMVER": 10
        },
        {
            "MFGNUM": 20
        }
    ],
    //控制参数只读,0-可读写,1-只读
    "paraDisabled": [
        0,
        0,
        1
    ],
    //设置默认列宽度
    "ColumnWidth": [
        {
            "LINKTEXTYMFMEMO": 400
        },
        {
            "YIUNUMEN": 200
        },
        {
            "LINKTEXTYLOT": 200
        },
        {
            "LINKTEXTYARTREQ": 200
        }
    ]
}