diff --git a/.gitignore b/.gitignore index 991a9d1..29c9cac 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,9 @@ .idea/ lib/report/*.jar target/ -.DS_Store \ No newline at end of file +.DS_Store +.gradle +build +local.properties +classes/ +transform-classes/ \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..0013a31 --- /dev/null +++ b/build.gradle @@ -0,0 +1,128 @@ + +apply plugin: 'java' + + +ext { + /** + * 项目中依赖的jar的路径 + * 1.如果依赖的jar需要打包到zip中,放置在lib根目录下 + * 2.如果依赖的jar仅仅是编译时需要,防止在lib下子目录下即可 + */ + libPath = "$projectDir/../webroot/WEB-INF/lib" + + /** + * 是否对插件的class进行加密保护,防止反编译 + */ + guard = false + + def pluginInfo = getPluginInfo() + pluginPre = "fine-plugin" + pluginName = pluginInfo.id + pluginVersion = pluginInfo.version + + privateLib = "$projectDir/../webroot/WEB-INF/plugins/plugin-" + pluginName + "-1.0" + outputPath = privateLib + "/classes" +} + +group = 'com.fr.plugin' +version = '10.0' +sourceCompatibility = '8' + +sourceSets { + main { + java.outputDir = file(outputPath) + output.resourcesDir = file(outputPath) + } +} + +ant.importBuild("encrypt.xml") +//定义ant变量 +ant.projectDir = projectDir +ant.references["compile.classpath"] = ant.path { + fileset(dir: libPath, includes: '**/*.jar') + fileset(dir: ".",includes:"**/*.jar" ) +} + +classes.dependsOn('clean') + +task copyFiles(type: Copy,dependsOn: 'classes'){ + from outputPath + into "$projectDir/classes" +} + +task preJar(type:Copy,dependsOn: guard ? 'compile_encrypt_javas' : 'compile_plain_javas'){ + from "$projectDir/classes" + into "$projectDir/transform-classes" + include "**/*.*" +} +jar.dependsOn("preJar") + +task makeJar(type: Jar,dependsOn: preJar){ + from fileTree(dir: "$projectDir/transform-classes") + baseName pluginPre + appendix pluginName + version pluginVersion + destinationDir = file("$buildDir/libs") + + doLast(){ + delete file("$projectDir/classes") + delete file("$projectDir/transform-classes") + } +} + +task copyFile(type: Copy,dependsOn: ["makeJar"]){ + from "$buildDir/libs" + from("$projectDir/lib") { + include "*.jar" + } + from "$projectDir/plugin.xml" + into file("$buildDir/temp/plugin") +} + +task zip(type:Zip,dependsOn:["copyFile"]){ + from "$buildDir/temp/plugin" + destinationDir file("$buildDir/install") + baseName pluginPre + appendix pluginName + version pluginVersion +} + +//控制build时包含哪些文件,排除哪些文件 +processResources { +// exclude everything +// 用*.css没效果 +// exclude '**/*.css' +// except this file +// include 'xx.xml' +} + +/*读取plugin.xml中的version*/ +def getPluginInfo(){ + def xmlFile = file("plugin.xml") + if (!xmlFile.exists()) { + return ["id":"none", "version":"1.0.0"] + } + def plugin = new XmlParser().parse(xmlFile) + def version = plugin.version[0].text() + def id = plugin.id[0].text() + return ["id":id,"version":version] +} + +repositories { + mavenLocal() + maven { + url = uri('http://mvn.finedevelop.com/repository/maven-public/') + } +} + +task prepare(type: Copy) { + into privateLib + from configurations.runtimeClasspath +} + +dependencies { + //使用本地jar + implementation fileTree(dir: 'lib', include: ['**/*.jar']) + implementation fileTree(dir: libPath, include: ['**/*.jar']) +} + diff --git a/encrypt.xml b/encrypt.xml new file mode 100644 index 0000000..1401cd1 --- /dev/null +++ b/encrypt.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..490fda8 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..f3d3406 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://downloads.gradle-dn.com/distributions/gradle-6.3-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..2fe81a7 --- /dev/null +++ b/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..62bd9b9 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,103 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/plugin.xml b/plugin.xml index ca9a779..eaaf8c6 100755 --- a/plugin.xml +++ b/plugin.xml @@ -3,12 +3,21 @@ com.fr.solution.plugin.db.redis.v10 yes - 7.2 + 7.4.1 10.0 - 2019-03-29 + 2020-01-20 richie + [2020-10-28]支持单一主机的集群模式连接选项。
+ [2020-07-07]修复了数据集没有随着参数的变化而变化的问题。
+ [2020-06-30]修复了一个失误导致连接被重复关闭的问题。
+ [2020-06-22]修改hkeys没能正确调用的问题。
+ [2020-06-09]修复redis连接没有正确关闭的问题。
+ [2020-06-05]搜索key的时候可以选择不同的数据库。
+ [2020-04-26]修复插件被标记为需要付费的问题。
+ [2020-04-21]修复redis集群下的一个问题。
[2019-10-30]适配新服务器数据集接口,在决策平台可以直接定义
[2019-09-29]修复无法兼容老版本的问题。
[2019-09-18]支持手动选择不同JavaScript脚本引擎。
diff --git a/readme.md b/readme.md index de4a6f2..37e72be 100644 --- a/readme.md +++ b/readme.md @@ -1,8 +1,8 @@ # 帆软报表连接redis缓存数据库插件 ## 插件编译 进入插件源码目录,执行命令 -`ant -f build.xml jar` -即可 +`gradle zip` +即可在build/install下获得插件安装包 ## 插件安装 使用帆软设计器自带的插件管理器即可安装。 diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..4604463 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,5 @@ +/* + * This file was generated by the Gradle 'init' task. + */ + +rootProject.name = 'demo-tabledata-redis' diff --git a/src/main/java/com/fr/plugin/db/redis/RedisLocaleFinder.java b/src/main/java/com/fr/plugin/db/redis/RedisLocaleFinder.java index ccb1218..e458f7a 100755 --- a/src/main/java/com/fr/plugin/db/redis/RedisLocaleFinder.java +++ b/src/main/java/com/fr/plugin/db/redis/RedisLocaleFinder.java @@ -1,11 +1,8 @@ package com.fr.plugin.db.redis; -import com.fr.plugin.db.redis.core.RedisConstants; -import com.fr.stable.fun.Authorize; import com.fr.stable.fun.impl.AbstractLocaleFinder; -@Authorize(callSignKey = RedisConstants.PLUGIN_ID) public class RedisLocaleFinder extends AbstractLocaleFinder { @Override public String find() { diff --git a/src/main/java/com/fr/plugin/db/redis/RedisUniversalConnectionImpl.java b/src/main/java/com/fr/plugin/db/redis/RedisUniversalConnectionImpl.java index 18dea85..a32034e 100644 --- a/src/main/java/com/fr/plugin/db/redis/RedisUniversalConnectionImpl.java +++ b/src/main/java/com/fr/plugin/db/redis/RedisUniversalConnectionImpl.java @@ -44,7 +44,9 @@ public class RedisUniversalConnectionImpl extends AbstractUniversalConnectionPro public JSONObject serialize(RedisDatabaseConnection connection) { JSONObject jsonObject = new JSONObject(); try { - jsonObject.put(BASIC_INFO, JSONObject.mapFrom(connection.clone())); + JSONObject basicInfo = JSONObject.mapFrom(connection.clone()); + basicInfo.put("password", DecisionServiceConstants.DEFAULT_PASSWORD); + jsonObject.put(BASIC_INFO, basicInfo); //将ConnectionPoolConfig和RedisConnectionProxyConfig也一次塞给前台展示 jsonObject.put(POOL_INFO, JSONObject.mapFrom(RedisConnectionPoolConfig.getInstance().clone())); JSONObject proxy = JSONObject.mapFrom(RedisConnectionProxyConfig.getInstance().clone()); diff --git a/src/main/java/com/fr/plugin/db/redis/action/SearchKeysAction.java b/src/main/java/com/fr/plugin/db/redis/action/SearchKeysAction.java index 29e13da..876c269 100644 --- a/src/main/java/com/fr/plugin/db/redis/action/SearchKeysAction.java +++ b/src/main/java/com/fr/plugin/db/redis/action/SearchKeysAction.java @@ -40,10 +40,11 @@ public class SearchKeysAction extends BaseHttpHandler { String[] keys = new String[0]; String pattern = request.getParameter("pattern"); String connectionName = request.getParameter("database"); - if (StringKit.isNotEmpty(pattern) && StringKit.isNotEmpty(connectionName)) { + String orderValue = request.getParameter("orderValue"); + if (StringKit.isNotEmpty(pattern) && StringKit.isNotEmpty(connectionName) && StringKit.isNotEmpty(orderValue)) { Connection connection = ConnectionKit.getConnection(connectionName); if (connection instanceof RedisDatabaseConnection) { - keys = connection.summary(pattern); + keys = connection.summary(pattern, orderValue); } } FlushKit.printAsJSON(response, JSONFactory.createJSON(Arrays.asList(keys))); diff --git a/src/main/java/com/fr/plugin/db/redis/core/RedisDatabaseConnection.java b/src/main/java/com/fr/plugin/db/redis/core/RedisDatabaseConnection.java index 5946fd5..6d78f5b 100755 --- a/src/main/java/com/fr/plugin/db/redis/core/RedisDatabaseConnection.java +++ b/src/main/java/com/fr/plugin/db/redis/core/RedisDatabaseConnection.java @@ -9,6 +9,7 @@ import com.fanruan.api.util.StringKit; import com.fanruan.api.util.TypeKit; import com.fr.config.holder.Conf; import com.fr.data.impl.Connection; +import com.fr.plugin.db.redis.core.accessor.EmbedRedis; import com.fr.plugin.db.redis.core.emb.Redis; import com.fr.stable.xml.XMLPrintWriter; import com.fr.stable.xml.XMLableReader; @@ -25,6 +26,7 @@ public class RedisDatabaseConnection extends BaseConnection { private Conf host = HolderKit.simple(StringKit.EMPTY); private Conf port = HolderKit.simple(String.valueOf(DEFAULT_REDIS_PORT)); private Conf password = HolderKit.simple(StringKit.EMPTY); + private Conf cluster = HolderKit.simple(false); public RedisDatabaseConnection() { @@ -54,6 +56,13 @@ public class RedisDatabaseConnection extends BaseConnection { this.password.set(password); } + public boolean isCluster() { + return cluster.get(); + } + + public void setCluster(boolean cluster) { + this.cluster.set(cluster); + } @Override public void testConnection() throws Exception { @@ -70,7 +79,7 @@ public class RedisDatabaseConnection extends BaseConnection { } public Redis createRedisClient() { - return RedisPool.getFinal(getHost(), getPort(), getPassword()); + return RedisPool.getFinal(isCluster(), getHost(), getPort(), getPassword()); } @Override @@ -79,10 +88,18 @@ public class RedisDatabaseConnection extends BaseConnection { return ArrayKit.EMPTY_STRING_ARRAY; } else { Redis redis = createRedisClient(); - Set keys = redis.getClient().keys(args[0]); - String[] array = keys.toArray(new String[0]); - redis.close(); - return array; + try { + EmbedRedis embedRedis = redis.getClient(); + int len = ArrayKit.getLength(args); + if (len > 1) { + int dbIndex = Integer.parseInt(args[1]); + embedRedis.select(dbIndex); + } + Set keys = embedRedis.keys(args[0]); + return keys.toArray(new String[0]); + } finally { + redis.close(); + } } } @@ -142,6 +159,7 @@ public class RedisDatabaseConnection extends BaseConnection { if (StringKit.isNotEmpty(pwd)) { setPassword(SecurityKit.encrypt(pwd)); } + setCluster(reader.getAttrAsBoolean("cluster", false)); } } } @@ -155,15 +173,17 @@ public class RedisDatabaseConnection extends BaseConnection { if (StringKit.isNotEmpty(getPassword())) { writer.attr("password", SecurityKit.decrypt(getPassword())); } + writer.attr("cluster", isCluster()); writer.end(); } @Override public Object clone() throws CloneNotSupportedException { - com.fr.plugin.db.redis.core.RedisDatabaseConnection cloned = (com.fr.plugin.db.redis.core.RedisDatabaseConnection) super.clone(); + com.fr.plugin.db.redis.core.RedisDatabaseConnection cloned = (RedisDatabaseConnection) super.clone(); cloned.host = (Conf) host.clone(); cloned.port = (Conf) port.clone(); cloned.password = (Conf) password.clone(); + cloned.cluster = (Conf) cluster.clone(); return cloned; } } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/db/redis/core/RedisPool.java b/src/main/java/com/fr/plugin/db/redis/core/RedisPool.java index b7aa12a..5198d8a 100644 --- a/src/main/java/com/fr/plugin/db/redis/core/RedisPool.java +++ b/src/main/java/com/fr/plugin/db/redis/core/RedisPool.java @@ -61,9 +61,11 @@ public class RedisPool { jedisPoolMap.clear(); } - public static Redis getFinal(String host, String port, String password) { + public static Redis getFinal(boolean isCluster, String host, String port, String password) { List> pairs = findAllHostAndPassword(host, port); - if (pairs.size() == 1) { + if (isCluster) { + return pool.getJedisCluster(pairs, password); + } else if (pairs.size() == 1) { return pool.getStandaloneResource(pairs.get(0), password); } else { return pool.getJedisCluster(pairs, password); diff --git a/src/main/java/com/fr/plugin/db/redis/core/RedisScriptTableData.java b/src/main/java/com/fr/plugin/db/redis/core/RedisScriptTableData.java index 7da58aa..a795722 100644 --- a/src/main/java/com/fr/plugin/db/redis/core/RedisScriptTableData.java +++ b/src/main/java/com/fr/plugin/db/redis/core/RedisScriptTableData.java @@ -18,7 +18,6 @@ import com.fr.plugin.db.redis.core.script.EngineType; import com.fr.plugin.db.redis.util.RedisUtils; import com.fr.record.analyzer.EnableMetrics; import com.fr.script.Calculator; -import com.fr.stable.NameReference; import com.fr.stable.ParameterProvider; import com.fr.stable.xml.XMLPrintWriter; import com.fr.stable.xml.XMLableReader; diff --git a/src/main/java/com/fr/plugin/db/redis/core/RedisScriptTableDataModel.java b/src/main/java/com/fr/plugin/db/redis/core/RedisScriptTableDataModel.java index 3ff402d..16d805f 100644 --- a/src/main/java/com/fr/plugin/db/redis/core/RedisScriptTableDataModel.java +++ b/src/main/java/com/fr/plugin/db/redis/core/RedisScriptTableDataModel.java @@ -38,13 +38,17 @@ public class RedisScriptTableDataModel extends BaseDataModel { return; } Redis redis = mc.createRedisClient(); - redis.getClient().select(dbIndex); - RedisClient redisClient = RedisClientSelector.select(redis, engineType); - SimpleDataModel simple = redisClient.build(redis, script, rowCount); - if (simple != null) { - this.columnNames = simple.getColumnNames(); - this.data = simple.getData(); - this.rowCount = simple.getRowCount(); + try { + redis.getClient().select(dbIndex); + RedisClient redisClient = RedisClientSelector.select(redis, engineType); + SimpleDataModel simple = redisClient.build(redis, script, rowCount); + if (simple != null) { + this.columnNames = simple.getColumnNames(); + this.data = simple.getData(); + this.rowCount = simple.getRowCount(); + } + } finally { + redis.close(); } } diff --git a/src/main/java/com/fr/plugin/db/redis/core/RedisTableData.java b/src/main/java/com/fr/plugin/db/redis/core/RedisTableData.java index 606a2ef..2fd2881 100644 --- a/src/main/java/com/fr/plugin/db/redis/core/RedisTableData.java +++ b/src/main/java/com/fr/plugin/db/redis/core/RedisTableData.java @@ -77,7 +77,8 @@ public class RedisTableData extends BaseTableData { @Focus(id = RedisConstants.PLUGIN_ID, text = "Plugin-Redis_DB", source = Original.PLUGIN) public DataModel createDataModel(Calculator calculator, int rowCount) { long start = System.currentTimeMillis(); - ParameterProvider[] ps = getParameters(calculator); + ParameterProvider[] providers = getParameters(calculator); + ParameterProvider[] ps = Calculator.processParameters(calculator, providers); Connection connection = database.get(); String name = RedisUtils.getName(connection); if (StringKit.isNotEmpty(name)) { diff --git a/src/main/java/com/fr/plugin/db/redis/core/RedisTableDataModel.java b/src/main/java/com/fr/plugin/db/redis/core/RedisTableDataModel.java index 5bc5c40..5d9317a 100644 --- a/src/main/java/com/fr/plugin/db/redis/core/RedisTableDataModel.java +++ b/src/main/java/com/fr/plugin/db/redis/core/RedisTableDataModel.java @@ -28,18 +28,18 @@ public class RedisTableDataModel extends BaseDataModel { return; } Redis redis = mc.createRedisClient(); - redis.getClient().select(dbIndex); - LogKit.info("Connect to redis and select database:" + dbIndex); try { + redis.getClient().select(dbIndex); + LogKit.info("Connect to redis and select database:" + dbIndex); long start = System.currentTimeMillis(); DataWrapper wrapper = VisitorFactory.getKeyValueResult(calculator, ps, redis.getClient(), query, rowCount); LogKit.info("Fetch data from redis spend time {} ms.", System.currentTimeMillis() - start); - wrapper.transform(script); data = wrapper.getData(); columnNames = wrapper.getColumnNames(); - redis.close(); } catch (Exception e) { throw new RuntimeException(e.getCause()); + } finally { + redis.close(); } } diff --git a/src/main/java/com/fr/plugin/db/redis/core/accessor/category/ClusterRedisClient.java b/src/main/java/com/fr/plugin/db/redis/core/accessor/category/ClusterRedisClient.java index 69d3124..733d2e7 100644 --- a/src/main/java/com/fr/plugin/db/redis/core/accessor/category/ClusterRedisClient.java +++ b/src/main/java/com/fr/plugin/db/redis/core/accessor/category/ClusterRedisClient.java @@ -91,7 +91,10 @@ public class ClusterRedisClient implements EmbedRedis { @Override public void select(int index) { - jedisCluster.select(index); + Map clusterNodes = jedisCluster.getClusterNodes(); + for (Map.Entry entry : clusterNodes.entrySet()) { + entry.getValue().getResource().select(index); + } } @Override diff --git a/src/main/java/com/fr/plugin/db/redis/help/client/BaseRedisClient.java b/src/main/java/com/fr/plugin/db/redis/help/client/BaseRedisClient.java index 9d809b8..7581c19 100644 --- a/src/main/java/com/fr/plugin/db/redis/help/client/BaseRedisClient.java +++ b/src/main/java/com/fr/plugin/db/redis/help/client/BaseRedisClient.java @@ -50,7 +50,7 @@ public abstract class BaseRedisClient implements RedisClient { @ScriptBridge public String hkeys(String key) { long start = System.currentTimeMillis(); - Set set = jedis.keys(key); + Set set = jedis.hkeys(key); LogKit.info("Fetch data from redis spend time {} ms.", System.currentTimeMillis() - start); return object2JSONString(set); } diff --git a/src/main/java/com/fr/plugin/db/redis/ui/RedisConnectionPane.java b/src/main/java/com/fr/plugin/db/redis/ui/RedisConnectionPane.java index 33f3bfa..9e3570f 100755 --- a/src/main/java/com/fr/plugin/db/redis/ui/RedisConnectionPane.java +++ b/src/main/java/com/fr/plugin/db/redis/ui/RedisConnectionPane.java @@ -4,6 +4,7 @@ import com.fanruan.api.conf.ConfigurationKit; import com.fanruan.api.design.DesignKit; import com.fanruan.api.design.ui.component.UIActionLabel; import com.fanruan.api.design.ui.component.UIButton; +import com.fanruan.api.design.ui.component.UICheckBox; import com.fanruan.api.design.ui.component.UILabel; import com.fanruan.api.design.ui.component.UIPasswordField; import com.fanruan.api.design.ui.component.UITextField; @@ -31,6 +32,7 @@ public class RedisConnectionPane extends DatabaseConnectionPane listeners = new ArrayList(); private UIPlaceholderTextField keysPatternTextField; + private UIIntNumberField dbIndexNumberField; public RedisDBConnectionChosePane() { setLayout(new BorderLayout(4, 4)); @@ -51,6 +54,10 @@ public class RedisDBConnectionChosePane extends BasicPane { keysPatternTextField = new UIPlaceholderTextField(10); keysPatternTextField.setPlaceholder(DesignKit.i18nText("Plugin-Redis_Keys_Pattern")); + dbIndexNumberField = new UIIntNumberField(); + dbIndexNumberField.setColumns(2); + dbIndexNumberField.setInt(0); + JPanel centerPane = new JPanel(new BorderLayout()); UIButton searchButton = new UIButton(DesignKit.i18nText("Plugin-Redis_Keys_Pattern_Search")); @@ -63,6 +70,10 @@ public class RedisDBConnectionChosePane extends BasicPane { centerPane.add(GUICoreKit.createBorderLayoutPane( keysPatternTextField, BorderLayout.CENTER, + GUICoreKit.createBorderLayoutPane( + new UILabel(DesignKit.i18nText("Plugin-Redis_DB_Simple_Index")), BorderLayout.WEST, + dbIndexNumberField, BorderLayout.CENTER + ), BorderLayout.WEST, searchButton, BorderLayout.EAST), BorderLayout.NORTH); centerPane.add(list, BorderLayout.CENTER); @@ -97,7 +108,8 @@ public class RedisDBConnectionChosePane extends BasicPane { if (StringKit.isEmpty(keysPattern)) { return ArrayKit.EMPTY_STRING_ARRAY; } else { - return DataOperator.getInstance().getTableSummary(connection, keysPattern); + String dbIndex = String.valueOf(dbIndexNumberField.getInt()); + return DataOperator.getInstance().getTableSummary(connection, keysPattern, dbIndex); } } diff --git a/src/main/resources/com/fr/plugin/db/redis/locale/redis.properties b/src/main/resources/com/fr/plugin/db/redis/locale/redis.properties index 2d83961..36ecf38 100755 --- a/src/main/resources/com/fr/plugin/db/redis/locale/redis.properties +++ b/src/main/resources/com/fr/plugin/db/redis/locale/redis.properties @@ -9,6 +9,7 @@ Plugin-Redis_Help=Help Doc Plugin-Redis_Keys_Pattern=Keys Pattern Plugin-Redis_Keys_Pattern_Search=Search Plugin-Redis_DB_Index=DB Index +Plugin-Redis_DB_Simple_Index=Index Plugin-Redis_Preview=Preview Plugin-Redis_Refresh=Refresh Plugin-Redis_Formula=Formula @@ -38,3 +39,4 @@ Plugin-Redis_Cluster_Config_Description=Input multiple hosts with commas separat Plugin-Redis_Script_Engine_Type=Script Engine Type Plugin-Redis_Script_Engine_Type_Default=Default Plugin-Redis_Script_Engine_Type_V8=V8 +Plugin-Redis_Cluster_Mode=Cluster Mode diff --git a/src/main/resources/com/fr/plugin/db/redis/locale/redis_en_US.properties b/src/main/resources/com/fr/plugin/db/redis/locale/redis_en_US.properties index 2f69c39..9263988 100755 --- a/src/main/resources/com/fr/plugin/db/redis/locale/redis_en_US.properties +++ b/src/main/resources/com/fr/plugin/db/redis/locale/redis_en_US.properties @@ -9,6 +9,7 @@ Plugin-Redis_Help=Help Doc Plugin-Redis_Keys_Pattern=Keys Pattern Plugin-Redis_Keys_Pattern_Search=Search Plugin-Redis_DB_Index=DB Index +Plugin-Redis_DB_Simple_Index=Index Plugin-Redis_Preview=Preview Plugin-Redis_Refresh=Refresh Plugin-Redis_Formula=Formula @@ -38,3 +39,9 @@ Plugin-Redis_Cluster_Config_Description=Input multiple hosts with commas separat Plugin-Redis_Script_Engine_Type=Script Engine Type Plugin-Redis_Script_Engine_Type_Default=Default Plugin-Redis_Script_Engine_Type_V8=V8 +Plugin-Redis_Cluster_Mode=Cluster Mode +Plugin-Redis_Index=Index +Plugin-Redis_Set_Parameter=Parameter +Plugin-Redis_Set_Parameter_Name=Parameter Name +Plugin-Redis_Set_Parameter_Type=Parameter Type +Plugin-Redis_Set_Parameter_Value=Parameter Value \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/db/redis/locale/redis_zh_CN.properties b/src/main/resources/com/fr/plugin/db/redis/locale/redis_zh_CN.properties index 59b03d9..d22250a 100755 --- a/src/main/resources/com/fr/plugin/db/redis/locale/redis_zh_CN.properties +++ b/src/main/resources/com/fr/plugin/db/redis/locale/redis_zh_CN.properties @@ -9,6 +9,7 @@ Plugin-Redis_Help=\u5E2E\u52A9\u6587\u6863 Plugin-Redis_Keys_Pattern=\u952E\u503C\u7684\u6B63\u5219\u8868\u8FBE\u5F0F Plugin-Redis_Keys_Pattern_Search=\u641C\u7D22 Plugin-Redis_DB_Index=\u6570\u636E\u5E93\u7F16\u53F7 +Plugin-Redis_DB_Simple_Index=\u7F16\u53F7 Plugin-Redis_Preview=\u9884\u89C8 Plugin-Redis_Refresh=\u5237\u65B0 Plugin-Redis_Formula=\u516C\u5F0F @@ -38,15 +39,30 @@ Plugin-Redis_Cluster_Config_Description=1\u3001\u4F7F\u7528\u9017\u53F7\u5206\u5 Plugin-Redis_Script_Engine_Type=\u811A\u672C\u5F15\u64CE Plugin-Redis_Script_Engine_Type_Default=\u9ED8\u8BA4 Plugin-Redis_Script_Engine_Type_V8=V8\u9AD8\u901F\u5F15\u64CE -Plugin-Redis_Proxy_Private_Key_Path_Mark=\u8bf7\u8f93\u5165\u670d\u52a1\u5668\u6587\u4ef6\u8def\u5f84 -Plugin-Redis_Connection_Form_OriginalCharsetName= \u7f16\u7801 -Plugin-Redis_Check_Integer=\u8bf7\u8f93\u5165\u4e0d\u5c0f\u4e8e\u0030\u7684\u6574\u6570 -Plugin-Redis_View=\u89c6\u56fe +Plugin-Redis_Cluster_Mode=\u96C6\u7FA4\u6A21\u5F0F +Plugin-Redis_Proxy_Private_Key_Path_Mark=\u8BF7\u8F93\u5165\u670D\u52A1\u5668\u6587\u4EF6\u8DEF\u5F84 +Plugin-Redis_Connection_Form_OriginalCharsetName= \u7F16\u7801 +Plugin-Redis_Check_Integer=\u8BF7\u8F93\u5165\u4E0D\u5C0F\u4E8E0\u7684\u6574\u6570 +Plugin-Redis_Parameter_Insert=\u63D2\u5165 +Plugin-Redis_Parameter_Delete=\u5220\u9664 +Plugin-Redis_Parameter_Move_Up=\u4E0A\u79FB +Plugin-Redis_Parameter_Move_Down=\u4E0B\u79FB +Plugin-Redis_Parameter_Refresh=\u5237\u65B0 +Plugin-Redis_Dataset_Parameter_Name=\u53C2\u6570 +Plugin-Redis_Dataset_Parameter_Value=\u503C +Plugin-Redis_Parameter_Please_Set_Parameter_Name=\u8BF7\u5148\u8BBE\u7F6E\u53C2\u6570\u540D +Plugin-Redis_Parameter_Type_String=\u5B57\u7B26\u4E32 +Plugin-Redis_Parameter_Type_Int=\u6574\u578B +Plugin-Redis_Parameter_Type_Number=\u53CC\u7CBE\u5EA6\u578B +Plugin-Redis_Parameter_Type_Date=\u65E5\u671F +Plugin-Redis_Parameter_Type_Boolean=\u5E03\u5C14\u578B +Plugin-Redis_Parameter_Type_Formula=\u516C\u5F0F +Plugin-Redis_Parameter_Delete_Confirm=\u4F60\u786E\u5B9A\u51B3\u5B9A\u5220\u9664\u9009\u4E2D\u7684\u9879\uFF1F +Plugin-Redis_Parameter_Delete_Alert=\u5F53\u524D\u5217\u8868\u4E3A\u7A7A\u6216\u8005\u4F60\u6CA1\u6709\u9009\u4E2D\u4EFB\u4F55\u9879 +Plugin-Redis_View=\u89C6\u56FE Plugin-Redis_Table=\u8868 -Plugin-Redis_Preview=\u9884\u89c8 -Plugin-Redis_Refresh=\u5237\u65B0 -Plugin-Redis_Data_Connection=\u6570\u636e\u8fde\u63a5 -Plugin-Redis_Set_Parameter=\u53c2\u6570\u8bbe\u7f6e -Plugin-Redis_Set_Parameter_Name=\u53c2\u6570\u540d -Plugin-Redis_Set_Parameter_Type=\u53c2\u6570\u7c7b\u578b -Plugin-Redis_Set_Parameter_Value=\u9ed8\u8ba4\u503c \ No newline at end of file +Plugin-Redis_Index=\u7F16\u53F7 +Plugin-Redis_Set_Parameter=\u53C2\u6570 +Plugin-Redis_Set_Parameter_Name=\u53C2\u6570\u540D +Plugin-Redis_Set_Parameter_Type=\u53C2\u6570\u7C7B\u578B +Plugin-Redis_Set_Parameter_Value=\u53C2\u6570\u503C \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/db/redis/web/redis.js b/src/main/resources/com/fr/plugin/db/redis/web/redis.js index 2c0e9b6..38ec51b 100644 --- a/src/main/resources/com/fr/plugin/db/redis/web/redis.js +++ b/src/main/resources/com/fr/plugin/db/redis/web/redis.js @@ -1,15 +1,23 @@ -/*! time: 2019-11-12 11:24:08 */!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=11)}([function(e,t,n){"use strict";function r(e){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var o=n(3),i=n(16),a=Object.prototype.toString;function u(e){return"[object Array]"===a.call(e)}function c(e){return null!==e&&"object"===r(e)}function s(e){return"[object Function]"===a.call(e)}function l(e,t){if(null!=e)if("object"!==r(e)&&(e=[e]),u(e))for(var n=0,o=e.length;n=200&&e<300}};c.headers={common:{Accept:"application/json, text/plain, */*"}},r.forEach(["delete","get","head"],(function(e){c.headers[e]={}})),r.forEach(["post","put","patch"],(function(e){c.headers[e]=r.merge(i)})),e.exports=c}).call(this,n(2))},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function u(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:a}catch(e){r=a}}();var c,s=[],l=!1,f=-1;function p(){l&&c&&(l=!1,c.length?s=c.concat(s):f=-1,s.length&&y())}function y(){if(!l){var e=u(p);l=!0;for(var t=s.length;t;){for(c=s,s=[];++f1)for(var n=1;n=200&&e<300}};c.headers={common:{Accept:"application/json, text/plain, */*"}},r.forEach(["delete","get","head"],function(e){c.headers[e]={}}),r.forEach(["post","put","patch"],function(e){c.headers[e]=r.merge(i)}),e.exports=c}).call(this,n(2))},function(e,t){var n,r,o=e.exports={};function i(){throw new Error("setTimeout has not been defined")}function a(){throw new Error("clearTimeout has not been defined")}function u(e){if(n===setTimeout)return setTimeout(e,0);if((n===i||!n)&&setTimeout)return n=setTimeout,setTimeout(e,0);try{return n(e,0)}catch(t){try{return n.call(null,e,0)}catch(t){return n.call(this,e,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:i}catch(e){n=i}try{r="function"==typeof clearTimeout?clearTimeout:a}catch(e){r=a}}();var c,s=[],l=!1,f=-1;function p(){l&&c&&(l=!1,c.length?s=c.concat(s):f=-1,s.length&&y())}function y(){if(!l){var e=u(p);l=!0;for(var t=s.length;t;){for(c=s,s=[];++f1)for(var n=1;n * @license MIT */ -e.exports=function(e){return null!=e&&(n(e)||function(e){return"function"==typeof e.readFloatLE&&"function"==typeof e.slice&&n(e.slice(0,0))}(e)||!!e._isBuffer)}},function(e,t,n){"use strict";var r=n(1),o=n(0),i=n(26),a=n(27);function u(e){this.defaults=e,this.interceptors={request:new i,response:new i}}u.prototype.request=function(e){"string"==typeof e&&(e=o.merge({url:arguments[0]},arguments[1])),(e=o.merge(r,{method:"get"},this.defaults,e)).method=e.method.toLowerCase();var t=[a,void 0],n=Promise.resolve(e);for(this.interceptors.request.forEach((function(e){t.unshift(e.fulfilled,e.rejected)})),this.interceptors.response.forEach((function(e){t.push(e.fulfilled,e.rejected)}));t.length;)n=n.then(t.shift(),t.shift());return n},o.forEach(["delete","get","head","options"],(function(e){u.prototype[e]=function(t,n){return this.request(o.merge(n||{},{method:e,url:t}))}})),o.forEach(["post","put","patch"],(function(e){u.prototype[e]=function(t,n,r){return this.request(o.merge(r||{},{method:e,url:t,data:n}))}})),e.exports=u},function(e,t,n){"use strict";var r=n(0);e.exports=function(e,t){r.forEach(e,(function(n,r){r!==t&&r.toUpperCase()===t.toUpperCase()&&(e[t]=n,delete e[r])}))}},function(e,t,n){"use strict";var r=n(5);e.exports=function(e,t,n){var o=n.config.validateStatus;n.status&&o&&!o(n.status)?t(r("Request failed with status code "+n.status,n.config,null,n.request,n)):e(n)}},function(e,t,n){"use strict";e.exports=function(e,t,n,r,o){return e.config=t,n&&(e.code=n),e.request=r,e.response=o,e}},function(e,t,n){"use strict";var r=n(0);function o(e){return encodeURIComponent(e).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}e.exports=function(e,t,n){if(!t)return e;var i;if(n)i=n(t);else if(r.isURLSearchParams(t))i=t.toString();else{var a=[];r.forEach(t,(function(e,t){null!=e&&(r.isArray(e)?t+="[]":e=[e],r.forEach(e,(function(e){r.isDate(e)?e=e.toISOString():r.isObject(e)&&(e=JSON.stringify(e)),a.push(o(t)+"="+o(e))})))})),i=a.join("&")}return i&&(e+=(-1===e.indexOf("?")?"?":"&")+i),e}},function(e,t,n){"use strict";var r=n(0),o=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"];e.exports=function(e){var t,n,i,a={};return e?(r.forEach(e.split("\n"),(function(e){if(i=e.indexOf(":"),t=r.trim(e.substr(0,i)).toLowerCase(),n=r.trim(e.substr(i+1)),t){if(a[t]&&o.indexOf(t)>=0)return;a[t]="set-cookie"===t?(a[t]?a[t]:[]).concat([n]):a[t]?a[t]+", "+n:n}})),a):a}},function(e,t,n){"use strict";var r=n(0);e.exports=r.isStandardBrowserEnv()?function(){var e,t=/(msie|trident)/i.test(navigator.userAgent),n=document.createElement("a");function o(e){var r=e;return t&&(n.setAttribute("href",r),r=n.href),n.setAttribute("href",r),{href:n.href,protocol:n.protocol?n.protocol.replace(/:$/,""):"",host:n.host,search:n.search?n.search.replace(/^\?/,""):"",hash:n.hash?n.hash.replace(/^#/,""):"",hostname:n.hostname,port:n.port,pathname:"/"===n.pathname.charAt(0)?n.pathname:"/"+n.pathname}}return e=o(window.location.href),function(t){var n=r.isString(t)?o(t):t;return n.protocol===e.protocol&&n.host===e.host}}():function(){return!0}},function(e,t,n){"use strict";var r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";function o(){this.message="String contains an invalid character"}o.prototype=new Error,o.prototype.code=5,o.prototype.name="InvalidCharacterError",e.exports=function(e){for(var t,n,i=String(e),a="",u=0,c=r;i.charAt(0|u)||(c="=",u%1);a+=c.charAt(63&t>>8-u%1*8)){if((n=i.charCodeAt(u+=.75))>255)throw new o;t=t<<8|n}return a}},function(e,t,n){"use strict";var r=n(0);e.exports=r.isStandardBrowserEnv()?{write:function(e,t,n,o,i,a){var u=[];u.push(e+"="+encodeURIComponent(t)),r.isNumber(n)&&u.push("expires="+new Date(n).toGMTString()),r.isString(o)&&u.push("path="+o),r.isString(i)&&u.push("domain="+i),!0===a&&u.push("secure"),document.cookie=u.join("; ")},read:function(e){var t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove:function(e){this.write(e,"",Date.now()-864e5)}}:{write:function(){},read:function(){return null},remove:function(){}}},function(e,t,n){"use strict";var r=n(0);function o(){this.handlers=[]}o.prototype.use=function(e,t){return this.handlers.push({fulfilled:e,rejected:t}),this.handlers.length-1},o.prototype.eject=function(e){this.handlers[e]&&(this.handlers[e]=null)},o.prototype.forEach=function(e){r.forEach(this.handlers,(function(t){null!==t&&e(t)}))},e.exports=o},function(e,t,n){"use strict";var r=n(0),o=n(28),i=n(6),a=n(1),u=n(29),c=n(30);function s(e){e.cancelToken&&e.cancelToken.throwIfRequested()}e.exports=function(e){return s(e),e.baseURL&&!u(e.url)&&(e.url=c(e.baseURL,e.url)),e.headers=e.headers||{},e.data=o(e.data,e.headers,e.transformRequest),e.headers=r.merge(e.headers.common||{},e.headers[e.method]||{},e.headers||{}),r.forEach(["delete","get","head","post","put","patch","common"],(function(t){delete e.headers[t]})),(e.adapter||a.adapter)(e).then((function(t){return s(e),t.data=o(t.data,t.headers,e.transformResponse),t}),(function(t){return i(t)||(s(e),t&&t.response&&(t.response.data=o(t.response.data,t.response.headers,e.transformResponse))),Promise.reject(t)}))}},function(e,t,n){"use strict";var r=n(0);e.exports=function(e,t,n){return r.forEach(n,(function(n){e=n(e,t)})),e}},function(e,t,n){"use strict";e.exports=function(e){return/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(e)}},function(e,t,n){"use strict";e.exports=function(e,t){return t?e.replace(/\/+$/,"")+"/"+t.replace(/^\/+/,""):e}},function(e,t,n){"use strict";var r=n(7);function o(e){if("function"!=typeof e)throw new TypeError("executor must be a function.");var t;this.promise=new Promise((function(e){t=e}));var n=this;e((function(e){n.reason||(n.reason=new r(e),t(n.reason))}))}o.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},o.source=function(){var e;return{token:new o((function(t){e=t})),cancel:e}},e.exports=o},function(e,t,n){"use strict";e.exports=function(e){return function(t){return e.apply(null,t)}}},function(e,t,n){"use strict";function r(e){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{};return function(n){return function(n){function r(){return i(this,r),c(this,l(r).apply(this,arguments))}return f(r,n),u(r,[{key:"_store",value:function(){var n=t.props?t.props.apply(this):void 0;return BI.Models.getModel(e.xtype,n)}}]),r}(n)}}n.r(t);var b,h,g,v=function(e){function t(){var e,n;i(this,t);for(var r=arguments.length,a=new Array(r),u=0;u0&&void 0!==u[0]?u[0]:{},n=t.url,r=t.type,o=t.headers,i=t.data,a=t.params,e.abrupt("return",vt.a.request({url:n,baseURL:Tt,method:r,headers:Et({},At,{},o,{Authorization:"Bearer ".concat(Pt("fine_auth_token")),"Content-Type":"application/json;charset=UTF-8"}),params:a,paramsSerializer:wt,data:i}).then(It).catch((function(e){console.log(e)})));case 3:case"end":return e.stop()}}),e)})),(Rt=function(){var t=this,n=arguments;return new Promise((function(r,o){var i=e.apply(t,n);function a(e){xt(i,r,o,a,u,"next",e)}function u(e){xt(i,r,o,a,u,"throw",e)}a(void 0)}))}).apply(this,arguments)}function Dt(e){return St({url:e,type:"GET",params:Et({},arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},{_:(new Date).getTime()})})}var Nt,Ct,jt,Bt={vars:[{text:"$$page_number",value:"$$page_number",type:"VARS",def:"当前的页数。"},{text:"$$totalPage_number",value:"$$totalPage_number",type:"VARS",def:"总页数。"}],JSONs:[{def:"ABS(number): 返回指定数字的绝对值。绝对值是指没有正负符号的数值。Number:需要求出绝对值的任意实数。示例:ABS(-1.5)等于1.5。ABS(0)等于0。ABS(2.5)等于2.5。",name:"ABS",type:"MATH"},{def:"ABS(number): 返回指定数字的绝对值。绝对值是指没有正负符号的数值。Number:需要求出绝对值的任意实数。示例:ABS(-1.5)等于1.5。ABS(0)等于0。ABS(2.5)等于2.5。",name:"ABS",type:"COMMON"},{def:"acc_sum(x_agg(array),range)根据横纵轴或行列维度添加的字段对指标进行跨行累计的计算。第一个参数为用户计算的指标,该指标必须为聚合函数或聚合指标;第二个参数range为用户设置计算的范围,0为对所有行进行累计,1为对组内所有行进行累计示例:acc_sum(sum_agg(array),0)用户横轴轴拖拽销售日期(年分组),则该指标计算结果为,根据销售日期(年)对销量进行分组汇总,然后根据对所有行从上到下进行累加,获得每年的累计销量",name:"ACC_SUM",type:"TABLE_CAL"},{def:"ACOS(number): 返回指定数值的反余弦值。反余弦值为一个角度,返回角度以弧度形式表示。Number:需要返回角度的余弦值。备注: 函数的参数必须在-1和1之间,包括-1和1。 返回的角度值在0和Pi之间。 如果要把返回的角度用度数来表示,用180/PI()乘返回值即可。示例:ACOS(1)等于0(弧度)。ACOS(0.5)等于1.047197551(Pi/3弧度)。ACOS(0.5)*180/PI()等于60(度)。",name:"ACOS",type:"MATH"},{def:"AND(logical1,logical2,…): 当所有参数的值为真时,返回TRUE;当任意参数的值为假时,返回FALSE。Logical1,logical2,…:指1到30个需要检验TRUE或FALSE的条件值。备注: 参数必须是逻辑值,或是含有逻辑值的数组或引用。 如果数组或引用中含有文本或空的单元格,则忽略其值。 如果在指定的单元格区域中没有逻辑值,AND函数将返回错误信息*NAME?。示例:AND(1+7=8,5+7=12)等于TRUE。AND(1+7=8,5+7=11)等于FALSE。如果单元格A1到A4的值分别为TRUE、TRUE、FALSE和TRUE,则:AND(A1:A4)等于FALSE。如果单元格A5的值在0~50之间,则: AND(0 0,b > 0 or a > 0, b < 0时,公式直接成立;a < 0,b > 0, ATAN2(a,b)=PI()-ABS(ATAN(b/a))a < 0,b < 0, ATAN2(a,b)=ABS(ATAN(b/a))-PI() 当x_num与y_num都为0时,ATAN2返回错误信息*DIV/0!。 用角度制显示返回数值时,把返回数值乘以180/PI()。 返回值以弧度表示(返回值大于-pi且小于等于pi)。示例:ATAN2(-2,2)等于2.356194490192345(弧度制的3*pi/4)。ATAN2(2,2)等于0.785398163(弧度制的pi/4)。ATAN2(-2,2)*180/PI()等于135(角度制)。",name:"ATAN2",type:"MATH"},{def:"AVG_AGG(array): 根据当前分析维度,动态返回指标字段的汇总平均值,生成结果为一动态数据列,行数与当前分析维度行数一致。\n array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。 \n 示例:用户横轴为维度字段'日'时,纵轴的计算字段AVG_AGG(销量)返回的值为每日的平均销量;当用户横轴为维度字段'月'时,AVG_AGG(销量)返回的值为每月的平均销量。",name:"AVG_AGG",type:"AGG"},{def:"CEILING(number): 将参数number沿绝对值增大的方向,舍入为最接近的整数Number:指待舍入的数值。CEILING(-2.5)等于-3。CEILING(0.5)等于1。",name:"CEILING",type:"MATH"},{def:"CHAR(number): 根据指定数字返回对应的字符。CHAR函数可将计算机其他类型的数字代码转换为字符。Number:用于指定字符的数字,介于1~65535之间(包括1和65535)。示例:CHAR(88)等于“X”。CHAR(45)等于“-”。",name:"CHAR",type:"TEXT"},{def:'CODE(text): 计算文本串中第一个字符的数字代码。返回的代码对应于计算机使用的字符集。Text:需要计算第一个字符代码的文本或单元格引用。示例:CODE("S")等于83。CODE("Spreadsheet")等于83。',name:"CODE",type:"TEXT"},{def:'CONCATENATE(text1,text2,...): 将数个字符串合并成一个字符串。Text1,text2,...:需要合并成单个文本的文本项,可以是字符,数字或是单元格引用。示例:CONCATENATE("Average ","Price")等于“Average Price”。CONCATENATE("1","2")等于12。',name:"CONCATENATE",type:"TEXT"},{def:"COS(number): 返回一个角度的余弦值。Number:以弧度表示的需要求余弦值的角度。备注: 要把一个角度转换成弧度值,将角度乘于PI()/180。 COS(n*2*PI()+number)=COS(number)(其中n为整数,number从-pi到pi)。示例:COS(0.5)等于0.877582562。COS(30*PI()/180)等于0.866025404。",name:"COS",type:"MATH"},{def:"COUNTD_AGG(array): 根据当前分析维度,动态返回某字段的去重计数,生成结果为一动态数据列,行数与当前分析维度行数一致。\n \"array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n \"示例:用户横轴为维度字段'日'时,纵轴的计算字段COUNTD_AGG(销量)返回的值为每日的销量的去重个数;当用户横轴为维度字段'月'时,COUNTD_AGG(销量)返回的值为每月的销量的去重个数。\"",name:"COUNTD_AGG",type:"AGG"},{def:"COUNT_AGG(array): 根据当前分析维度,动态返回某字段的计数,生成结果为一动态数据列,行数与当前分析维度行数一致。\n array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n 示例:用户横轴为维度字段'日'时,纵轴的计算字段COUNT_AGG(销量)返回的值为每日的销量的个数;当用户横轴为维度字段'月'时,COUNT_AGG(销量)返回的值为每月的销量的个数。",name:"COUNT_AGG",type:"AGG"},{def:"DATE(year,month,day): 返回一个表示某一特定日期的系列数。Year:代表年,可为一到四位数。Month:代表月份。若1 month 12,则函数把参数值作为月。若month>12,则函数从年的一月份开始往上累加。例如: DATE(2000,25,2)等于2002年1月2日的系列数。Day:代表日。若日期小于等于某指定月的天数,则函数将此参数值作为日。若日期大于某指定月的天数,则函数从指定月份的第一天开始往上累加。若日期大于两个或多个月的总天数,则函数把减去两个月或多个月的余数加到第三或第四个月上,依此类推。例如:DATE(2000,3,35)等于2000年4月4日的系列数。备注: 若需要处理公式中日期的一部分,如年或月等,则可用此公式。 若年,月和日是函数而不是函数中的常量,则此公式最能体现其作用。示例:DATE(1978, 9, 19) 等于1978-09-19.DATE(1211, 12, 1) 等于1211-12-01. ",name:"DATE",type:"DATETIME"},{def:'DATEDELTA(date, deltadays):返回一个日期date后deltadays的日期。deltaDays可以为正值,负值,零。示例:DATEDELTA("2008-08-08", -10)等于2008-07-29。DATEDELTA("2008-08-08", 10)等于2008-08-18。',name:"DATEDELTA",type:"DATETIME"},{def:'DATEDIF(start_date,end_date,unit):返回两个指定日期间的天数、月数或年数。Start_date:代表所指定时间段的初始日期。End_date:代表所指定时间段的终止日期。Unit:函数返回信息的类型。若unit=“Y”,则DATEDIF返回指定时间段的年差数。若unit=“M”,则DATEDIF返回指定时间段的月差数。若unit=“D”,则DATEDIF返回指定时间段的日差数。若unit=“MD”,则DATEDIF忽略年和月,返回指定时间段的日差数。若unit=“YM”,则DATEDIF忽略年和日,返回指定时间段的月差数。若unit=“YD”,则DATEDIF忽略年,返回指定时间段的日差数。示例:DATEDIF("2001/2/28","2004/3/20","Y")等于3,即在2001年2月28日与2004年3月20日之间有3个整年。DATEDIF("2001/2/28","2004/3/20","M")等于37,即在2001年2月28日与2004年3月20日之间有36个整月。DATEDIF("2001/2/28","2004/3/20","D")等于1116,即在2001年2月28日与2004年3月20日之间有1116个整天。DATEDIF("2001/2/28","2004/3/20","MD")等于8,即忽略月和年后,2001年2月28日与2004年3月20日的差为8天。DATEDIF("2001/1/28","2004/3/20","YM")等于2,即忽略日和年后,2001年1月28日与2004年3月20日的差为2个月。DATEDIF("2001/2/28","2004/3/20","YD")等于21,即忽略年后,2001年2月28日与2004年3月20日的差为21天。',name:"DATEDIF",type:"DATETIME"},{def:'DATESUBDATE(date1, date2, op):返回两个日期之间的时间差。op表示返回的时间单位:"s",以秒为单位。"m",以分钟为单位。"h",以小时为单位。"d",以天为单位。"w",以周为单位。示例:DATESUBDATE("2008-08-08", "2008-06-06","h")等于1512。',name:"DATESUBDATE",type:"DATETIME"},{def:'DATETONUMBER(date):返回自 1970 年 1 月 1 日 00:00:00 GMT 经过的毫秒数。示例:DATETONUMBER("2008-08-08")等于1218124800000。',name:"DATETONUMBER",type:"DATETIME"},{def:'DAY:(serial_number)返回日期中的日。DAY是介于1和31之间的一个数。Serial_number:含有所求的年的日期.备注:FineReport将日期保存为系列数,一个系列数代表一个与之匹配的日期,以方便用户对日期进行数值式计算。在1900年日期系统中,FineReport电子表格将1900年1月1日保存为系列数2,将1900年1月2日保存为系列数3,将1900年1月3日保存为系列数4……依此类推。如在1900年日期系统,1998年1月1日存为系列数35796。示例:DAY("2000/1/1")等于1。DAY("2006/05/05")等于5。DAY("1997/04/20")等于20。DAY("2000-1-1", "yyyy-MM-dd")等于1。DAY("2006-05-05", "yyyy-MM-dd")等于5。DAY("1997-04-20", "yyyy-MM-dd")等于20。DAY(35796)等于1。',name:"DAY",type:"DATETIME"},{def:'DAYS360(start_date,end_date,method):按照一年 360 天的算法(每个月以 30 天计,一年共计 12 个月),返回两日期间相差的天数,这在会计计算中将会用到。如果财务系统是基于一年 12 个月,每月 30 天,可用此函数帮助计算支付款项。Start_date 和 end_date :是用于计算期间天数的起止日期。Method : 它指定了在计算中是采用欧洲方法还是美国方法。Method 定义 :FALSE或忽略 美国方法 (NASD)。如果起始日期是一个月的 31 号,则等于同月的 30 号。如果终止日期是一个月的31号,并且起始日期早于 30 号,则终止日期等于下一个月的 1 号,否则,终止日期等于本月的 30 号。TRUE 欧洲方法。无论是起始日期还是终止日期为一个月的 31 号,都将等于本月的 30 号。备注:FineReport将日期保存为系列数,一个系列数代表一个与之匹配的日期,以方便用户对日期进行数值式计算。在1900年日期系统中,FineReport电子表格将1900年1月1日保存为系列数2,将1900年1月2日保存为系列数3,将1900年1月3日保存为系列数4……依此类推。如在1900年日期系统,1998年1月1日存为系列数35796。示例:DAYS360("1998/1/30", "1998/2/1") 等于 1',name:"DAYS360",type:"DATETIME"},{def:'DAYSOFMONTH(date):返回从1900年1月后某年某月包含的天数。示例:DAYSOFMONTH("1900-02-01")等于28。DAYSOFMONTH("2008/04/04")等于30。',name:"DAYSOFMONTH",type:"DATETIME"},{def:'DAYSOFQUARTER(date): 返回从1900年1月后某年某季度的天数。示例:DAYSOFQUARTER("2009-02-01")等于90。DAYSOFQUARTER("2009/05/05")等于91。',name:"DAYSOFQUARTER",type:"DATETIME"},{def:'DAYSOFYEAR(year):返回某年包含的天数。示例:DAYSOFYEAR(2008)等于365,等价于DAYSOFYEAR("2008-01-01")。',name:"DAYSOFYEAR",type:"DATETIME"},{def:'DAYVALUE(date):返回1900年至 date日期所经历的天数。示例:DAYVALUE("2008/08/08")等于39669。',name:"DAYVALUE",type:"DATETIME"},{def:"DEGREES(angle): 将弧度转化为度。angle:待转换的弧度角。示例:DEGREES(PI()/2)等于90。DEGREES(3.1415926)等于179.9999969。",name:"DEGREES",type:"MATH"},{def:'ENDWITH(str1,str2):判断字符串str1是否以str2结束。备注: str1和str2都是大小写敏感的。示例:ENDWITH("FineReport","Report")等于true。ENDWITH("FineReport","Fine")等于false。ENDWITH("FineReport","report")等于false。',name:"ENDWITH",type:"TEXT"},{def:'EXACT(text1,text2): 检测两组文本是否相同。如果完全相同,EXACT函数返回TRUE;否则,返回FALSE。EXACT函数可以区分大小写,但忽略格式的不同。同时也可以利用EXACT函数来检测输入文档的文字。Text1:需要比较的第一组文本。Text2:需要比较的第二组文本。示例:EXACT("Spreadsheet","Spreadsheet")等于TRUE。EXACT("Spreadsheet","S preadsheet")等于FALSE。EXACT("Spreadsheet","spreadsheet")等于FALSE。',name:"EXACT",type:"TEXT"},{def:"EXP(number): 返回e的n次幂。常数e为自然对数的底数,等于2.71828182845904。Number:为任意实数,作为常数e的指数。备注: 如果要返回其他常数作为底数的幂,可以使用指数运算符(^)。例如: 在4^2中,4是底数,而2是指数。 EXP函数与LN函数互为反函数。示例:EXP(0)等于1。EXP(3)等于20.08553692。EXP(LN(2))等于2。",name:"EXP",type:"MATH"},{def:"FACT(number):返回数的阶乘,一个数的阶乘等于 1*2*3*...*该数。number:要计算其阶乘的非负数。如果输入的 number 不是整数,则截尾取整。示例:FACT(1) 等于 1FACT(1.9) 等于 FACT(1) 等于 1FACT(0) 等于 1FACT(5) 等于 1*2*3*4*5 等于 120",name:"FACT",type:"MATH"},{def:'FIND(find_text,within_text,start_num):从指定的索引(start_num)处开始,返回第一次出现的指定子字符串(find_text)在此字符串(within_text)中的索引。Find_text:需要查找的文本或包含文本的单元格引用。Within_text:包含需要查找文本的文本或单元格引用。Start_num:指定进行查找字符的索引位置。within_text里的索引从1开始。如果省略start_num,则假设值为1。备注: 如果find_text不在within_text中,FIND函数返回值为0。 如果start_num不大于0,FIND函数返回错误信息*VALUE!。 如果start_num大于within_text的长度,FIND函数返回值为0。 如果find_text是空白文本,FIND函数将在搜索串中匹配第一个字符(即编号为start_num或1的字符)。示例:FIND("I","Information")等于1。FIND("i","Information")等于9。FIND("o","Information",2)等于4。FIND("o","Information",12)等于0。FIND("o","Information",-1)等于*VALUE!。',name:"FIND",type:"TEXT"},{def:"FLOOR(number): 将参数number沿绝对值减小的方向去尾舍入。Number:待舍入的数值。示例:FLOOR(-2.5)等于-2。FLOOR(2.5)等于2。",name:"FLOOR",type:"MATH"},{def:'FORMAT(object,format) : 返回object的format格式。object 需要被格式化对象,可以是String,数字,Object(常用的有Date, Time)。format 格式化的样式。示例FORMAT(1234.5, "#,##0.00") => 1234.50FORMAT(1234.5, "#,##0") => 1234FORMAT(1234.5, "¥#,##0.00") => ¥1234.50FORMAT(1.5, "0%") => 150%FORMAT(1.5, "0.000%") => 150.000%FORMAT(6789, "##0.0E0") => 6.789E3FORMAT(6789, "0.00E00") => 6.79E03FORMAT(date(2007,1,1), "EEEEE, MMMMM dd, yyyy") => 星期一,一月 01,2007FORMAT(date(2007,1,13), "MM/dd/yyyy") => 01/13/2007FORMAT(date(2007,1,13), "M-d-yy") => 1-13-07FORMAT(time(16,23,56), "h:mm:ss a") => 4:23:56 下午',name:"FORMAT",type:"TEXT"},{def:'HOUR(serial_number):返回某一指定时间的小时数。函数指定HOUR为0(0:00)到23(23:00)之间的一个整数。Serial_number:包含所求小时的时间。示例:HOUR("11:32:40")等于11。HOUR("11:32:40", "HH:mm:ss")等于11。',name:"HOUR",type:"DATETIME"},{def:'IF(boolean,number1/string1,number2/string2):判断函数,boolean为true时返回第二个参数,为false时返回第三个。boolean: 用于判断的布尔值,true或者false。number1/string1: 第一个参数,如果boolean为ture,返回这个值。number2/string2: 第二个参数,如果boolean为false,返回这个值。示例:IF(true,2,8)等于2IF(false,"first","second")等于secondIF(true,"first",7)等于first',name:"IF",type:"LOGIC"},{def:'IF(boolean,number1/string1,number2/string2):判断函数,boolean为true时返回第二个参数,为false时返回第三个。boolean: 用于判断的布尔值,true或者false。number1/string1: 第一个参数,如果boolean为ture,返回这个值。number2/string2: 第二个参数,如果boolean为false,返回这个值。示例:IF(true,2,8)等于2IF(false,"first","second")等于secondIF(true,"first",7)等于first',name:"IF",type:"COMMON"},{def:'INDEXOF(str1,index):返回字符串str1在index位置上的字符。备注: index是从0开始计数的。示例:INDEXOF("FineReport",0)等于\'F\'。INDEXOF("FineReport",2)等于\'n\'。INDEXOF("FineReport",9)等于\'t\'。INDEXOF(array, index):返回数组在index位置上的元素。备注: index是从1开始计数的。示例:String[] array = {"a", "b", "c"}INDEXOF(array, 1)等于"a".',name:"INDEXOF",type:"TEXT"},{def:"INT(number): 返回数字下舍入(数值减小的方向)后最接近的整数值。Number:需要下舍入为整数的实数。示例:INT(4.8)等于4。INT(-4.8)等于-5。INT(4.3)等于4。INT(-4.3)等于-5。公式INT(A1)将返回A1单元格中的一个正实数的整数数部分。",name:"INT",type:"MATH"},{def:"INT(number): 返回数字下舍入(数值减小的方向)后最接近的整数值。Number:需要下舍入为整数的实数。示例:INT(4.8)等于4。INT(-4.8)等于-5。INT(4.3)等于4。INT(-4.3)等于-5。公式INT(A1)将返回A1单元格中的一个正实数的整数数部分。",name:"INT",type:"COMMON"},{def:"ISNULL(object):判断对象中所有的值是否全部都是NULL或者为空字符串。",name:"ISNULL",type:"OTHER"},{def:'LEFT(text,num_chars): 根据指定的字符数返回文本串中的第一个或前几个字符。Text:包含需要选取字符的文本串或单元格引用。Num_chars:指定返回的字符串长度。备注: Num_chars的值必须等于或大于0。 如果num_chars大于整个文本的长度,LEFT函数将返回所有的文本。 如果省略num_chars,则默认值为1。示例:LEFT("Fine software",8)等于“Fine sof”。LEFT("Fine software")等于“F”。如果单元格A3中含有“China”,则LEFT(A3,2)等于“Ch”。',name:"LEFT",type:"TEXT"},{def:"LEN(args): 返回文本串中的字符数或者数组的长度。需要注意的是:参数args为文本串时,空格也计为字符。参数args为数组时,直接返回数组长度。示例:LEN(\"Evermore software\")等于17。LEN(\" \")等于1。LEN(['a','b'])等于2。",name:"LEN",type:"TEXT"},{def:"LN(number):返回一个数的自然对数。自然对数以常数项 e(2.71828182845904)为底。number:是用于计算其自然对数的正实数。示例:LN(86) 等于 4.45437LN(2.7182818) 等于 1LN(EXP(3)) 等于 3EXP(LN(4)) 等于 4",name:"LN",type:"MATH"},{def:"LOG(number,base): 按指定的任意底数,返回数值的对数。Number:需要求对数的正实数。Base:对数的底数。如果省略底数,默认值为10。示例:LOG(16,2)等于4。LOG(10)等于1。LOG(24,3)等于2.892789261。",name:"LOG",type:"MATH"},{def:"LOG10(number):返回以 10 为底的对数。number: 用于常用对数计算的正实数。示例:LOG10(86) 等于 1.934498451LOG10(10) 等于 1LOG10(1E5) 等于 5",name:"LOG10",type:"MATH"},{def:'LOWER(text): 将所有的大写字母转化为小写字母。Text:需要转化为小写字母的文本串。LOWER函数不转化文本串中非字母的字符。示例:LOWER("A.M.10:30")等于“a.m.10:30”。LOWER("China")等于“china”。',name:"LOWER",type:"TEXT"},{def:"LUNAR(year,day,month): 返回当前日期对应的农历时间。year,month,day:分别对应年月日。示例:如果需要查询2011年7月21日对应的农历时间,则只需输入LUNAR(2011,7,21)结果将显示为:辛卯年六月廿一同样,如输入LUNAR(2001,7,21),则显示:辛巳年六月初一 。本公式支持的时间段为1900-2100年。",name:"LUNAR",type:"DATETIME"},{def:"MAX(number1,number2,…): 返回参数列表中的最大值。Number1,number2,…:1到30个需要找出最大值的参数。备注: 参数可以是数字、空白单元格、逻辑值或数字的文本表达式。 如果数组或引用参数中包含可解析文本值,逻辑值,零值或空白单元格,这些值都将参与计算,而不可解析的文本值忽略不计。 如果参数中没有任何数字,MAX将返回0。示例:MAX(0.1,0,1.2)等于1.2。",name:"MAX",type:"MATH"},{def:"MAX_AGG(array): 根据当前分析维度,动态返回指标字段的最大值,生成结果为一动态数据列,行数与当前分析维度行数一致。\n \"array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n \"示例:用户横轴为维度字段'日'时,纵轴的计算字段MAX_AGG(销量)返回的值为每日的最大值销量;当用户横轴为维度字段'月'时,MAX_AGG(销量)返回的值为每月的最大值销量。",name:"MAX_AGG",type:"AGG"},{def:"MEDIAN_AGG(array): 根据当前分析维度,动态返回指标字段的中位数,生成结果为一动态数据列,行数与当前分析维度行数一致。\n \"array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n \"示例:用户横轴为维度字段'日'时,纵轴的计算字段MEDIAN_AGG(销量)返回的值为每日的中位数销量;当用户横轴为维度字段'月'时,MEDIAN_AGG(销量)返回的值为每月的中位数销量。",name:"MEDIAN_AGG",type:"AGG"},{def:'MID(text,start_num,num_chars): 返回文本串中从指定位置开始的一定数目的字符,该数目由用户指定。Text:包含要提取字符的文本串。Start_num:文本中需要提取字符的起始位置。文本中第一个字符的start_num为1,依此类推。Num_chars:返回字符的长度。备注: 如果start_num大于文本长度,MID函数返回“”(空文本)。 如果start_num小于文本长度,并且start_num加上num_chars大于文本长度,MID函数将从start_num指定的起始字符直至文本末的所有字符。 如果start_num小于1,MID函数返回错误信息*VALUE!。 如果num_chars是负数,MID函数返回错误信息*VALUE!。示例:MID("Finemore software",10,8)返回“software”。MID("Finemore software",30,5)返回“”(空文本)。MID("Finemore software",0,8)返回*VALUE!。MID("Finemore software",5,-1)返回*VALUE!。',name:"MID",type:"TEXT"},{def:"MIN(number1,number2,…): 返回参数列表中的最小值。Number1,number2,…:1到30个需要找出最小值的参数。备注: 若参数中没有数字,函数MIN将返回0。 参数应为数字、空白单元格、逻辑值或是表示数值的文本串。如果参数是错误值时,MIN将返回错误信息。 如果数组或引用参数中包含可解析文本值,逻辑值,零值或空白单元格,这些值都将参与计算,而不可解析的文本值忽略不计。示例:如果B1:B4包含3,6,9,12,则:MIN(B1:B4)等于3。MIN(B1:B4,0)等于0。",name:"MIN",type:"MATH"},{def:'MINUTE(serial_number):返回某一指定时间的分钟数,其值是介于0与59之间的一个整数。serial_number:包含所求分钟数的时间。示例:MINUTE("15:36:25")等于36。MINUTE("15:36:25", "HH:mm:ss")等于36。',name:"MINUTE",type:"DATETIME"},{def:"MIN_AGG(array): 根据当前分析维度,动态返回指标字段的最小值,生成结果为一动态数据列,行数与当前分析维度行数一致。\n \"array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n \"示例:用户横轴为维度字段'日'时,纵轴的计算字段MIN_AGG(销量)返回的值为每日的最小值销量;当用户横轴为维度字段'月'时,MIN_AGG(销量)返回的值为每月的最小值销量。",name:"MIN_AGG",type:"AGG"},{def:"MOD(number,divisor):返回两数相除的余数。结果的正负号与除数相同。number:为被除数。divisor:为除数。示例:MOD(3, 2) 等于 1MOD(-3, 2) 等于 1MOD(3, -2) 等于 -1MOD(-3, -2) 等于 -1",name:"MOD",type:"MATH"},{def:'MONTH:(serial_number)返回日期中的月。月是介于1和12之间的一个数。Serial_number:含有所求的月的日期.备注:FineReport将日期保存为系列数,一个系列数代表一个与之匹配的日期,以方便用户对日期进行数值式计算。在1900年日期系统中,FineReport电子表格将1900年1月1日保存为系列数2,将1900年1月2日保存为系列数3,将1900年1月3日保存为系列数4……依此类推。如在1900年日期系统,1998年1月1日存为系列数35796。示例:MONTH("2000/1/1")等于1。MONTH("2006/05/05")等于5。MONTH("1997/04/20")等于4。MONTH("2000-1-1", "yyyy-MM-dd")等于1。MONTH("2006-05-05", "yyyy-MM-dd")等于5。MONTH("1997-04-20", "yyyy-MM-dd")等于4。MONTH(35796)等于1。',name:"MONTH",type:"DATETIME"},{def:'MONTHDELTA(date,delta):返回指定日期date后delta个月的日期。示例:MONTHDELTA("2008-08-08", 4)等于2008-12-08。',name:"MONTHDELTA",type:"DATETIME"},{def:"NOW():获取当前时间。示例:如果系统时间是2012年5月12日 15点18分38秒则NOW()等于2012-05-12 15:18:36。",name:"NOW",type:"DATETIME"},{def:"NUMTO(number,bool)或NUMTO(number):返回number的中文表示。其中bool用于选择中文表示的方式,当没有bool时采用默认方式显示。示例:NUMTO(2345,true)等于二三四五。示例:NUMTO(2345,false)等于二千三百四十五。示例:NUMTO(2345)等于二千三百四十五。",name:"NUMTO",type:"TEXT"},{def:"NVL(value1,value2,value3,...):在所有参数中返回第一个不是null的值value1:可以为任意数,也可以为null。value2:可以为任意数,也可以为null。当字符串长度为0时, 返回也为null示例:NVL(12,20)等于12。NVL(null,12)等于12。NVL(null,null)等于null。NVL(20,null)等于20。NVL(null,null,10)等于10。",name:"NVL",type:"OTHER"},{def:"OR(logical1,logical2,…): 当所有参数的值为假时,返回FALSE;当任意参数的值为真时,返回TRUE。Logical1,logical2,…:指1到30个需要检验TRUE或FALSE的条件值。备注: 参数必须是逻辑值,或是含有逻辑值的数组或引用。 如果数组或引用中含有文本或空的单元格,则忽略其值。 如果在指定的单元格区域中没有逻辑值,AND函数将返回错误信息*NAME?。示例:OR(1+7=9,5+7=11)等于FALSE。OR(1+7=8,5+7=11)等于TRUE。",name:"OR",type:"LOGIC"},{def:'period_anls(x_agg(array),datepart)根据横纵轴或行列维度添加的日期字段进行上期末的计算。第一个参数为用于计算的指标,该指标必须为聚合函数或聚合指标;第二个参数用于配置计算的上期末为上年期末或者上月期末。横纵轴拖拽的字段不满足函数的计算要求时,该指标会标红。示例:period_anls(sum_agg(amount),"Y") 用户横纵轴拖拽销售日期(年月日分组),则该指标计算结果为,根据年月日对销量进行分组汇总,然后计算出该日数据上年年末的销量;如果参数2为“M”,则计算结果为该日销量上月月末的销量。',name:"PERIOD_ANLS",type:"TABLE_CAL"},{def:"PI(number): 是一个数学常量函数,当number为空时,函数返回精确到15位的数值3.141592653589793;当参数不为空时,number表示PI的倍数。示例:SIN(PI()/2)等于1。计算圆的面积的公式: S=PI()*(r^2),其中S为圆的面积,R为圆的半径。PI(3)等于9.42477796076938。",name:"PI",type:"MATH"},{def:"POWER(number,power): 返回指定数字的乘幂。Number:底数,可以为任意实数。Power:指数。参数number按照该指数次幂乘方。备注: 可以使用符号“^”代替POWER,如: POWER(5,2)等于5^2。示例:POWER(6,2)等于36。POWER(14,5)等于537824。POWER(4,2/3)等于2.519842100。POWER(3,-2.3)等于0.079913677。",name:"POWER",type:"MATH"},{def:"previous_period(x_agg(array))根据横纵轴或行列维度添加的日期字段进行环期值的计算。参数为用于计算的指标,该指标必须为聚合函数或聚合指标。横纵轴拖拽的字段不满足函数的计算要求时,该指标会标红。示例:previous_period(sum_agg(amount)) 用户横纵轴拖拽销售日期(年月日分组),则该指标计算结果为,根据年月日对销量进行分组汇总,然后计算出该日数据上一日的销量。",name:"PREVIOUS_PERIOD",type:"TABLE_CAL"},{def:"PROMOTION(value1,value2):返回value2在value1上提升的比例。示例:PROMOTION(12, 14)等于0.166666666,即提升了16.6666666%.PROMOTION(-12, 14)等于2.166666666,即提升了216.6666666%.",name:"PROMOTION",type:"MATH"},{def:'PROPER(text): 将文本中的第一个字母和所有非字母字符后的第一个字母转化成大写,其他字母变为小写。Text:需要转化为文本的公式、由双引号引用的文本串或是单元格引用。示例:PROPER("Finemore Integrated Office")等于“Finemore Integrated Office”。PROPER("100 percent")等于“100 Percent”。PROPER("SpreaDSheEt")等于“Spreadsheet”。',name:"PROPER",type:"TEXT"},{def:"RADIANS(angle): 将角度转换成弧度。Angle:需要转换为弧度的角度。示例:RADIANS(90)等于1.570796327。",name:"RADIANS",type:"MATH"},{def:"RAND(): 返回均匀分布的随机数。每计算一次工作表,函数都会返回一个新的随机数值。备注: 要生成一个位于a和b之间的随机数,可以使用以下的公式: C=RAND()*(b-a)+a。 如果要使一个随机产生的数值不随单元格的重计算而改变,可以在编辑框中输入=RAND()并保持编辑状态,然后按F9,将公式永久性地改为随机数。示例:假如需要生成一个大于等于0,小于60的随机数,使用公式: =RAND()*60。假如需要生成一个大于等于0,小于19的随机数,使用公式: =RAND()*19。假如需要生成一个大于等于0,小于50的随机数,使用公式: =RAND()*50。",name:"RAND",type:"MATH"},{def:"RANDBETWEEN(value1,value2):返回value1和value2之间的一个随机整数。示例:RANDBETWEEN(12.333, 13.233)只会返回13。RANDBETWEEN(11.2, 13.3)有可能返回12或者13。",name:"RANDBETWEEN",type:"MATH"},{def:'rank_anls(x_agg(array),range,order)根据横纵轴或行列维度添加的字段对指标进行跨行排名的计算。第一个参数为用户计算的指标,该指标必须为聚合函数或聚合指标;第二个参数range为用户设置计算的范围,0为对所有行进行排名,1为对组内所有行进行排名;第三个参数order为排名的计算规则,"asc"为升序排名,"desc"为降序排名。示例:rank_anls(sum_agg(amount),0,"asc")用户横轴轴拖拽省份,则该指标计算结果为,根据省份对销量进行分组汇总,然后计算每个省份的销量在所有省份中的升序排名情况。',name:"RANK_ANLS",type:"TABLE_CAL"},{def:'REGEXP(str, pattern):字符串str是否与正则表达式pattern相匹配。示例:REGEXP("aaaaac","a*c")等于true。REGEXP("abc","a*c")等于false。REGEXP(str, pattern, intNumber):字符串str是否与具有给定模式 intNumber的正则表达式pattern相匹配。示例:CASE_INSENSITIVE = 0 启用不区分大小写的匹配。 默认情况下,不区分大小写的匹配假定仅匹配 US-ASCII 字符集中的字符。可以通过指 定 UNICODE_CASE 标志连同此标志来启用 Unicode 感知的、不区分大小写的匹配。 MULTILINE = 1 启用多行模式。DOTALL = 2 启用 dotall 模式。在 dotall 模式中,表达式 . 可以匹配任何字符,包括行结束符。默认情况下,此表达式不匹配行 结束符。UNICODE_CASE = 3 启用 Unicode 感知的大小写折叠。指定此标志后,由 CASE_INSENSITIVE 标志启用时,不区分大小写的匹配将以 符合 Unicode Standard 的方式完成。CANON_EQ = 4 启用规范等价。 指定此标志后,当且仅当其完整规范分解匹配时,两个字符才可视为匹配。UNIX_LINES = 5 启用 Unix 行模式。 在此模式中,.、^ 和 $ 的行为中仅识别 \'\n\' 行结束符。LITERAL = 6 启用模式的字面值解析。 指定此标志后,指定模式的输入字符串就会作为字面值字符序列来对待。输入序列中的 元字符或转义序列不具有任何特殊意义。 标志 CASE_INSENSITIVE 和 UNICODE_CASE 在与此标志一起使用时将 对匹配产生影响。其他标志都变得多余了。COMMENTS = 7 模式中允许空白和注释。 此模式将忽略空白和在结束行之前以 # 开头的嵌入式注释。 REGEXP("Aaaaabbbbc","a*b*c", 3)等于true。REGEXP("Aaaaabbbbc","a*b*c", 1)等于false。',name:"REGEXP",type:"TEXT"},{def:'REPEAT(text,number_times): 根据指定的次数重复显示文本。REPEAT函数可用来显示同一字符串,并对单元格进行填充。Text:需要重复显示的文本或包含文本的单元格引用。Number_times:指定文本重复的次数,且为正数。如果number_times为0,REPEAT函数将返回“”(空文本)。如果number_times不是整数,将被取整。REPEAT函数的最终结果通常不大于32767个字符。备注: 该函数可被用于在工作表中创建简单的直方图。示例:REPEAT("$",4)等于“$$$$”。如果单元格B10的内容为“你好”,REPEAT(B10,3)等于“你好你好你好”。',name:"REPEAT",type:"TEXT"},{def:'REPLACE(text, texttoreplace, replacetext):根据指定字符串,用其他文本来代替原始文本中的内容。text:需要被替换部分字符的文本或单元格引用。texttoreplace:指定的字符串。replacetext:需要替换部分旧文本的文本。示例:REPLACE("abcd", "a", "re")等于"rebcd"。REPLACE("a**d", "**d", "rose")等于"arose"。REPLACE(old_text,start_num,num_chars,new_text): 根据指定的字符数,用其他文本串来替换某个文本串中的部分内容。Old_text:需要被替换部分字符的文本或单元格引用。Start_num:需要用new_text来替换old_text中字符的起始位置。Num_chars:需要用new_text来替换old_text中字符的个数。New_text:需要替换部分旧文本的文本。示例:REPLACE("0123456789",5,4,"*")等于“0123*89”。REPLACE("1980",3,2,"99")等于“1999”。',name:"REPLACE",type:"TEXT"},{def:'RIGHT(text,num_chars): 根据指定的字符数从右开始返回文本串中的最后一个或几个字符。Text:包含需要提取字符的文本串或单元格引用。Num_chars:指定RIGHT函数从文本串中提取的字符数。Num_chars不能小于0。如果num_chars大于文本串长度,RIGHT函数将返回整个文本。如果不指定num_chars,则默认值为1。示例:RIGHT("It is interesting",6)等于“esting”。RIGHT("Share Holder")等于“r”。RIGHT("Huge sale",4)等于“sale”。',name:"RIGHT",type:"TEXT"},{def:"ROUND(number,num_digits):返回某个数字按指定位数舍入后的数字。number:需要进行舍入的数字。num_digits:指定的位数,按此位数进行舍入。如果 num_digits 大于 0,则舍入到指定的小数位。如果 num_digits 等于 0,则舍入到最接近的整数。如果 num_digits 小于 0,则在小数点左侧进行舍入。示例:ROUND(2.15, 1) 等于 2.2ROUND(2.149, 1) 等于 2.1ROUND(-1.475, 2) 等于 -1.48ROUND(21.5, -1) 等于 20因浮点数存在精度计算丢失问题, 导致计算结果里可能带上9999, 0000这些, 因此加入第三个参数来控制是否需要去除9999. true表示需要过滤9999, 0000这些数据.",name:"ROUND",type:"MATH"},{def:"ROUND(number,num_digits):返回某个数字按指定位数舍入后的数字。number:需要进行舍入的数字。num_digits:指定的位数,按此位数进行舍入。如果 num_digits 大于 0,则舍入到指定的小数位。如果 num_digits 等于 0,则舍入到最接近的整数。如果 num_digits 小于 0,则在小数点左侧进行舍入。示例:ROUND(2.15, 1) 等于 2.2ROUND(2.149, 1) 等于 2.1ROUND(-1.475, 2) 等于 -1.48ROUND(21.5, -1) 等于 20因浮点数存在精度计算丢失问题, 导致计算结果里可能带上9999, 0000这些, 因此加入第三个参数来控制是否需要去除9999. true表示需要过滤9999, 0000这些数据.",name:"ROUND",type:"COMMON"},{def:'same_period(x_agg(array),datepart)根据横纵轴或行列维度添加的日期字段进行同期值的计算。第一个参数为用于计算的指标,该指标必须为聚合函数或聚合指标;第二个参数用于配置计算同期时计算某日的年同期或者某日的月同期。横纵轴拖拽的字段不满足函数的计算要求时,该指标会标红。示例:same_period(sum_agg(amount),"Y") 用户横纵轴拖拽销售日期(年月日分组),则该指标计算结果为,根据年月日对销量进行分组汇总,然后计算出该日数据上年同日的销量;如果参数2为“M”,则计算结果为该日销量上月同日的销量。',name:"SAME_PERIOD",type:"TABLE_CAL"},{def:'SECOND(serial_number):返回某一指定时间的秒数,其值是介于0与59之间的一个整数。Serial_number:包含所求秒数的时间。示例:SECOND("15:36:25")等于25。SECOND("15:36:25", "HH:mm:ss")等于25。',name:"SECOND",type:"DATETIME"},{def:"SIGN(number):返回数字的符号。当数字为正数时返回 1,为零时返回 0,为负数时返回 -1。Number:为任意实数。示例:SIGN(10) 等于 1SIGN(4-4) 等于 0SIGN(-0.00001) 等于 -1",name:"SIGN",type:"MATH"},{def:"SIN(number): 计算给定角度的正弦值。Number:待求正弦值的以弧度表示的角度。备注: 如果参数的单位是度,将其乘以PI()/180即可转换成弧度。示例:SIN(10)等于-0.5440211108893698。SIN(45*PI()/180)等于0.707106781。",name:"SIN",type:"MATH"},{def:'SPLIT(String1,String2):返回由String2分割String1组成的字符串数组。String1:以双引号表示的字符串。String2:以双引号表示的分隔符。例如逗号","示例:SPLIT("hello,world,yes",",") = ["hello","world","yes"]。SPLIT("this is very good"," ") = ["this","is","very","good"]。备注:如果只有一个参数,则返回一个错误。如果有多个参数,则只有前两个起作用。',name:"SPLIT",type:"TEXT"},{def:"SQRT(number): 返回一个正数的平方根。Number:要求其平方根的任一正数。备注:Number必须是一个正数,否则函数返回错误信息*NUM!。示例:SQRT(64)等于8。SQRT(-64)返回*NUM!。",name:"SQRT",type:"MATH"},{def:'STARTWITH(str1,str2):判断字符串str1是否以str2开始。备注: str1和str2都是大小写敏感的。示例:STARTWITH("FineReport","Fine")等于true。STARTWITH("FineReport","Report")等于false。STARTWITH("FineReport","fine")等于false。',name:"STARTWITH",type:"TEXT"},{def:"STDEV_AGG(array): 根据当前分析维度,动态返回指标字段的标准差,生成结果为一动态数据列,行数与当前分析维度行数一致。\n \"array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n \"示例:用户横轴为维度字段'日'时,纵轴的计算字段STDEV_AGG(销量)返回的值为每日的销量标准差;当用户横轴为维度字段'月'时,STDEV_AGG(销量)返回的值为每月的销量标准差。",name:"STDEV_AGG",type:"AGG"},{def:'SUBSTITUTE(text,old_text,new_text,instance_num): 用new_text替换文本串中的old_text。Text:需要被替换字符的文本,或含有文本的单元格引用。Old_text:需要被替换的部分文本。New_text:用于替换old_text的文本。Instance_num:指定用new_text来替换第几次出现的old_text。如果指定了instance_num,则只有指定位置上的old_text被替换,否则文字串中出现的所有old_text都被new_text替换。备注: 如果需要替换文本串中的指定文本,则使用SUBSTITUTE函数;如果需要替换文本串中指定位置上的任意文本,则使用REPLACE函数。示例:SUBSTITUTE("data base","base","model")等于“data model”。SUBSTITUTE("July 28, 2000","2","1",1)等于“July 18, 2000”。SUBSTITUTE("July 28, 2000","2","1")等于“July 18, 1000”。SUBSTITUTE("July 28, 2000","2","1",2)等于“July 28, 1000”。 ',name:"SUBSTITUTE",type:"TEXT"},{def:"SUM_AGG(array):根据当前分析维度,动态返回指标字段的汇总求和值,生成结果为一动态数据列,行数与当前分析维度行数一致。\n array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n 示例:用户横轴为维度字段'日'时,纵轴的计算字段SUM_AGG(销量)返回的值为每日的汇总销量;当用户横轴为维度字段'月'时,SUM_AGG(销量)返回的值为每月的汇总销量。",name:"SUM_AGG",type:"AGG"},{def:"switch(表达式, 值1, 结果1, 值2, 结果2, ...)如果表达式的结果是值1,整个函数返回结果1如果表达式的结果是值2,整个函数返回结果2如果表达式的结果是值3,整个函数返回结果3等等",name:"SWITCH",type:"LOGIC"},{def:"TAN(number): 返回指定角度的正切值。Number:待求正切值的角度,以弧度表示。如果参数是以度为单位的,乘以Pi()/180后转换为弧度。示例:TAN(0.8)等于1.029638557。TAN(45*Pi()/180)等于1。",name:"TAN",type:"MATH"},{def:"TIME(hour,minute,second): 返回代表指定时间的小数。介于0:00:00(12:00:00 A.M.)与23:59:59(11:59:59 P.M.)之间的时间可返回0到0.99999999之间的对应数值。Hour:介于0到23之间的数。Minute:介于0到59之间的数。Second:介于0到59之间的数。示例:TIME(14,40,0)等于2:40 PM。TIME(19,43,24)等于7:43 PM。",name:"TIME",type:"DATETIME"},{def:'TODATE()函数可以将各种日期形式的参数转换为日期类型。它有三种参数的形式:1 参数是一个日期型的参数,那么直接将这个参数返回。示例:TODATE(DATE(2007,12,12))返回2007年12月12日组成的日期。2 参数是以从1970年1月1日0时0分0秒开始的毫秒数,返回对应的时间。示例:TODATE(1023542354746)返回2002年6月8日。3 参数是日期格式的文本,那么返回这个文本对应的日期。示例:TODATE("2007/10/15")返回2007年10月5日组成的日期。TODATE("2007-6-8")返回2007年6月8日组成的日期。4 有两个参数,第一个参数是一个日期格式的文本,第二个参数是用来解析日期的格式。示例:TODATE("1/15/07","mm/dd/yy")返回07年1月15日组成的日期。特别的,"yyyyMMdd"是用来解析形如“20081230”之类的日期格式的。比如TODATE("20110830","yyyyMMdd")返回11年08月30日组成的日期5 有三个参数,第一个参数是一个日期格式的文本,第二个参数是用来解析日期的格式,第三个参数为解析日期的语言,如:zh(中文),en(英文)。示例:TODATE("星期三 1/15/07","EEE mm/dd/yy", "zh")返回07年1月15日组成的日期,使用“zh(中文)”才能够正常解析“星期三”这个字符串。',name:"TODATE",type:"DATETIME"},{def:"TODAY():获取当前日期。示例:如果系统日期是2005年9月10日则TODAY()等于2005-9-10。",name:"TODAY",type:"DATETIME"},{def:'TODOUBLE(text): 将文本转换成Double对象。Text:需要转换的文本。示例:TODOUBLE("123.21")等于 new Double(123.21)。',name:"TODOUBLE",type:"TEXT"},{def:'TOINTEGER(text): 将文本转换成Integer对象。Text:需要转换的文本。示例:TOINTEGER("123")等于 new Integer(123)。',name:"TOINTEGER",type:"TEXT"},{def:'total(x_agg(array),range,agg)根据横纵轴或行列维度添加的字段对指标进行跨行汇总的计算。第一个参数为用户计算的指标,该指标必须为聚合函数或聚合指标;第二个参数range为用户设置计算的范围,0为对所有行进行汇总,1为对组内所有行进行汇总;第三个参数agg为汇总的计算规则,"sum"为求和;"avg"为求平均,"max"为求最大值,"min"为求最小值示例:total(sum_agg(array),0,"avg")用户横纵轴拖拽省份,则该指标计算结果为,根据省份对销量进行分组汇总,然后计算平均每个省份的销量',name:"TOTAL",type:"TABLE_CAL"},{def:'TRIM(text): 清除文本中所有空格,单词间的单个空格除外,也可用于带有不规则空格的文本。Text:需要清除空格的文本。示例:TRIM(" Monthly Report")等于Monthly Report。',name:"TRIM",type:"TEXT"},{def:"TRUNC(number,num_digits):将数字的小数部分截去,返回整数。number:需要截尾取整的数字。num_digits:用于指定取整精度的数字。示例:TRUNC(8.9) 等于 8TRUNC(-8.9) 等于 -8TRUNC(PI()) 等于 3",name:"TRUNC",type:"MATH"},{def:'UPPER(text): 将文本中所有的字符转化为大写。Text:需要转化为大写字符的文本,或是包含文本的单元格引用。示例:UPPER("notes")等于“NOTES”。如果单元格E5的值为“Examples”,则UPPER(E5)等于“EXAMPLES”。',name:"UPPER",type:"TEXT"},{def:"VAR_AGG(array): 根据当前分析维度,动态返回指标字段的方差,生成结果为一动态数据列,行数与当前分析维度行数一致。\n \"array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n \"示例:用户横轴为维度字段'日'时,纵轴的计算字段VAR_AGG(销量)返回的值为每日的销量方差;当用户横轴为维度字段'月'时,VAR_AGG(销量)返回的值为每月的销量方差。",name:"VAR_AGG",type:"AGG"},{def:'WEEK(serial_num):返回一个代表一年中的第几周的数字。Serial_num:表示输入的日期。备注:FineReport将日期保存为系列数,一个系列数代表一个与之匹配的日期,以方便用户对日期进行数值式计算。在1900年日期系统中,FineReport电子表格将1900年1月1日保存为系列数2,将1900年1月2日保存为系列数3,将1900年1月3日保存为系列数4……依此类推。如在1900年日期系统,1998年1月1日存为系列数35796。示例:WEEK("2010/1/1")等于52。WEEK("2010/1/6")等于1。WEEK(35796)等于1。',name:"WEEK",type:"DATETIME"},{def:"weekdate(year,month,weekOfMonth,dayOfWeek): 返回指定年月的指定周的周几的具体日期。示例:weekdate(2009,10,2,1)返回的是2009年的10月的第二个周的第一天即星期天的日期,返回的是2009-10-04最后一个参数dayOfWeek为-1时,表示这个周的最后一天示例:weekdate(2009,12,1,-1)返回的是2009年的12月的第一个周的最后一天即星期六的日期,返回的是2009-12-05",name:"WEEKDATE",type:"DATETIME"},{def:'WEEKDAY(Serial_number):获取日期并返回星期数。返回值为介于0到6之间的某一整数,分别代表星期中的某一天(从星期日到星期六)。Serial_number:输入的日期备注:FineReport将日期保存为系列数,一个系列数代表一个与之匹配的日期,以方便用户对日期进行数值式计算。在1900年日期系统中,FineReport电子表格将1900年1月1日保存为系列数2,将1900年1月2日保存为系列数3,将1900年1月3日保存为系列数4……依此类推。如在1900年日期系统,1998年1月1日存为系列数35796。举例:WEEKDAY("2005/9/10")等于6(星期六)。WEEKDAY("2005/9/11")等于0(星期日)。WEEKDAY(35796)等于4(星期四)。',name:"WEEKDAY",type:"DATETIME"},{def:'YEAR:(serial_number)返回日期中的年。Year是介于1900和9999之间的一个数。Serial_number:含有所求的年的日期.备注:FineReport将日期保存为系列数,一个系列数代表一个与之匹配的日期,以方便用户对日期进行数值式计算。在1900年日期系统中,FineReport电子表格将1900年1月1日保存为系列数2,将1900年1月2日保存为系列数3,将1900年1月3日保存为系列数4……依此类推。如在1900年日期系统,1998年1月1日存为系列数35796。示例:YEAR("2000/1/1")等于2000。YEAR("2006/05/05")等于2006。YEAR("1997/04/20")等于1997。YEAR("2000-1-1", "yyyy-MM-dd")等于2000。YEAR("2006-05-05", "yyyy-MM-dd")等于2006。YEAR("1997-04-20", "yyyy-MM-dd")等于1997。YEAR(35796)等于1998。',name:"YEAR",type:"DATETIME"},{def:'YEARDELTA(date, delta):返回指定日期后delta年的日期。示例:YEARDELTA("2008-10-10",10)等于2018-10-10。',name:"YEARDELTA",type:"DATETIME"}]};function Mt(){return new Promise((function(e){e(Bt)}))}function Lt(e){return(Lt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function Ut(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:""})}(n.model.selectedConnection,n.model.search).then((function(e){n.model.tables=e||[]})):n.model.tables=[]},setSearch:function(e){this.model.search=e},setSelectedConnection:function(e){this.model.selectedConnection=e}}),n}var n,r,o;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&Vt(e,t)}(t,e),n=t,(r=[{key:"state",value:function(){return{connections:[],tables:[],search:"",selectedConnection:""}}}])&&Ut(n.prototype,r),o&&Ut(n,o),t}(v),kt(Ct,"xtype","dec.model.dcm.connection.plugin.redis.table_list"),Nt=jt))||Nt;function qt(e){return(qt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function Kt(e,t){for(var n=0;n0?n.model.connections[0]:"";n.connectionTextValue.setValue(e),n.store.setSelectedConnection(e)},"selectedConnection || search":function(){n.store.initTableList()},tables:function(e){n.buttonGroup.populate(n.renderTableList())}}),n}var n,r,o;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&zt(e,t)}(t,BI.Widget),n=t,(r=[{key:"render",value:function(){var e=this;return{type:"bi.vtape",hgap:10,bgap:5,items:[{el:{type:"bi.htape",items:[{type:"bi.text_value_combo",ref:function(t){e.connectionTextValue=t},items:[],listeners:[{eventName:BI.TextValueCombo.EVENT_CHANGE,action:function(){var t=e.connectionTextValue.getValue()[0];e.store.setSelectedConnection(t)}}]},{el:{type:"bi.icon_button",cls:"redis-site-font",title:BI.i18nText("Plugin-Redis_Data_Connection"),handler:function(){window.location.href="".concat(Tt,"#management/connection")}},width:25},{el:{type:"bi.icon_button",cls:"redis-refresh-font",title:BI.i18nText("Plugin-Redis_Refresh"),handler:function(){e.store.initData()}},width:25}]},height:25},{el:{type:"bi.htape",items:[{type:"bi.text_editor",height:24,watermark:BI.i18nText("Plugin-Redis_Keys_Pattern"),ref:function(t){e.searchText=t}},{el:{type:"bi.button",minWidth:50,text:BI.i18nText("Plugin-Redis_Keys_Pattern_Search"),handler:function(){e.store.setSearch(e.searchText.getValue())}},width:50}]},height:25},{type:"bi.vtape",items:[{type:"bi.button_group",chooseType:BI.Selection.None,layouts:[{type:"bi.vertical"}],items:[],ref:function(t){e.buttonGroup=t}}]}]}}},{key:"renderConnectionList",value:function(){return this.model.connections.map((function(e){return{text:e,value:e}}))}},{key:"renderTableList",value:function(){return this.model.tables.map((function(e){return{type:ht.xtype,text:e,value:e}}))}},{key:"mounted",value:function(){this.store.initData()}},{key:"getSelectedDatabase",value:function(){return this.model.selectedConnection}}])&&Kt(n.prototype,r),o&&Kt(n,o),t}(),Qt(Wt,"xtype","dec.dcm.connection.plugin.redis.table_list"),Ht=Xt))||Ht)||Ht;n(8);function rn(e){return(rn="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function on(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:BI.RegularFormulaInserter.xtype;return new Promise((function(n,r){var o,i=BI.UUID();BI.Popovers.create(i,{type:_,width:900,height:600,header:BI.i18nText("Plugin-JSON_Function_Definition"),body:{type:BI.FormulaOpeartingPanel.xtype,configLoader:Mt,ref:function(e){o=e},inserterType:t,value:e},listeners:[{eventName:BI.Popover.EVENT_CANCEL,action:function(){r(),BI.Popovers.remove(i)}},{eventName:BI.Popover.EVENT_CONFIRM,action:function(){n(o.getValue()),BI.Popovers.remove(i)}}]}).open(i)}))}({formula:0===this.model.inputValue?"":this.model.inputValue},BI.ComplexFormulaInserter.xtype).then((function(e){t.store.setInpueValue(e.formula),t.formulaPane.setValue(e.formula)}))}},{key:"getValue",value:function(){return"int"===this.model.inputType?parseInt("".concat(this.model.inputValue),10):this.model.inputValue}}])&&mn(n.prototype,r),o&&mn(n,o),t}(),vn(fn,"xtype","plugin.report.redis.components.database_index"),ln=pn))||ln)||ln,xn=[{text:BI.i18nText("Plugin-Redis_Set_Parameter_Name")},{text:BI.i18nText("Plugin-Redis_Set_Parameter_Type")},{text:BI.i18nText("Plugin-Redis_Set_Parameter_Value")}],An=[{text:BI.i18nText("Dec-Basic_String"),value:DecCst.Schedule.Parameter.Type.STRING,iconCls:"string-field-font"},{text:BI.i18nText("Dec-Basic_Integer"),value:DecCst.Schedule.Parameter.Type.INTEGER,iconCls:"number-field-font"},{text:BI.i18nText("Dec-Basic_Double"),value:DecCst.Schedule.Parameter.Type.DOUBLE,iconCls:"number-field-font"},{text:BI.i18nText("Dec-Basic_Date"),value:DecCst.Schedule.Parameter.Type.DATE,iconCls:"date-field-font"},{text:BI.i18nText("Dec-Basic_Boolean"),value:DecCst.Schedule.Parameter.Type.BOOLEAN,iconCls:"string-field-font"},{text:BI.i18nText("Dec-Basic_Formula"),value:DecCst.Schedule.Parameter.Type.FORMULA,iconCls:"string-field-font"}];function wn(e){return(wn="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function Pn(e,t){for(var n=0;n=0)return;a[t]="set-cookie"===t?(a[t]?a[t]:[]).concat([n]):a[t]?a[t]+", "+n:n}}),a):a}},function(e,t,n){"use strict";var r=n(0);e.exports=r.isStandardBrowserEnv()?function(){var e,t=/(msie|trident)/i.test(navigator.userAgent),n=document.createElement("a");function o(e){var r=e;return t&&(n.setAttribute("href",r),r=n.href),n.setAttribute("href",r),{href:n.href,protocol:n.protocol?n.protocol.replace(/:$/,""):"",host:n.host,search:n.search?n.search.replace(/^\?/,""):"",hash:n.hash?n.hash.replace(/^#/,""):"",hostname:n.hostname,port:n.port,pathname:"/"===n.pathname.charAt(0)?n.pathname:"/"+n.pathname}}return e=o(window.location.href),function(t){var n=r.isString(t)?o(t):t;return n.protocol===e.protocol&&n.host===e.host}}():function(){return!0}},function(e,t,n){"use strict";var r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";function o(){this.message="String contains an invalid character"}o.prototype=new Error,o.prototype.code=5,o.prototype.name="InvalidCharacterError",e.exports=function(e){for(var t,n,i=String(e),a="",u=0,c=r;i.charAt(0|u)||(c="=",u%1);a+=c.charAt(63&t>>8-u%1*8)){if((n=i.charCodeAt(u+=.75))>255)throw new o;t=t<<8|n}return a}},function(e,t,n){"use strict";var r=n(0);e.exports=r.isStandardBrowserEnv()?{write:function(e,t,n,o,i,a){var u=[];u.push(e+"="+encodeURIComponent(t)),r.isNumber(n)&&u.push("expires="+new Date(n).toGMTString()),r.isString(o)&&u.push("path="+o),r.isString(i)&&u.push("domain="+i),!0===a&&u.push("secure"),document.cookie=u.join("; ")},read:function(e){var t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove:function(e){this.write(e,"",Date.now()-864e5)}}:{write:function(){},read:function(){return null},remove:function(){}}},function(e,t,n){"use strict";var r=n(0);function o(){this.handlers=[]}o.prototype.use=function(e,t){return this.handlers.push({fulfilled:e,rejected:t}),this.handlers.length-1},o.prototype.eject=function(e){this.handlers[e]&&(this.handlers[e]=null)},o.prototype.forEach=function(e){r.forEach(this.handlers,function(t){null!==t&&e(t)})},e.exports=o},function(e,t,n){"use strict";var r=n(0),o=n(28),i=n(6),a=n(1),u=n(29),c=n(30);function s(e){e.cancelToken&&e.cancelToken.throwIfRequested()}e.exports=function(e){return s(e),e.baseURL&&!u(e.url)&&(e.url=c(e.baseURL,e.url)),e.headers=e.headers||{},e.data=o(e.data,e.headers,e.transformRequest),e.headers=r.merge(e.headers.common||{},e.headers[e.method]||{},e.headers||{}),r.forEach(["delete","get","head","post","put","patch","common"],function(t){delete e.headers[t]}),(e.adapter||a.adapter)(e).then(function(t){return s(e),t.data=o(t.data,t.headers,e.transformResponse),t},function(t){return i(t)||(s(e),t&&t.response&&(t.response.data=o(t.response.data,t.response.headers,e.transformResponse))),Promise.reject(t)})}},function(e,t,n){"use strict";var r=n(0);e.exports=function(e,t,n){return r.forEach(n,function(n){e=n(e,t)}),e}},function(e,t,n){"use strict";e.exports=function(e){return/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(e)}},function(e,t,n){"use strict";e.exports=function(e,t){return t?e.replace(/\/+$/,"")+"/"+t.replace(/^\/+/,""):e}},function(e,t,n){"use strict";var r=n(7);function o(e){if("function"!=typeof e)throw new TypeError("executor must be a function.");var t;this.promise=new Promise(function(e){t=e});var n=this;e(function(e){n.reason||(n.reason=new r(e),t(n.reason))})}o.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},o.source=function(){var e;return{token:new o(function(t){e=t}),cancel:e}},e.exports=o},function(e,t,n){"use strict";e.exports=function(e){return function(t){return e.apply(null,t)}}},function(e,t,n){"use strict";function r(e){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{};return function(n){return function(r){function o(){return i(this,o),c(this,l(o).apply(this,arguments))}return f(o,n),u(o,[{key:"_store",value:function(){var n=t.props?t.props.apply(this):void 0;return BI.Models.getModel(e.xtype,n)}}]),o}()}}n.r(t);var b,h,g,v=function(e){function t(){var e,n;i(this,t);for(var r=arguments.length,a=new Array(r),u=0;u0&&void 0!==u[0]?u[0]:{},n=t.url,r=t.type,o=t.headers,i=t.data,a=t.params,e.abrupt("return",vt.a.request({url:n,baseURL:Tt,method:r,headers:Et({},At,{},o,{Authorization:"Bearer ".concat(Pt("fine_auth_token")),"Content-Type":"application/json;charset=UTF-8"}),params:a,paramsSerializer:wt,data:i}).then(It).catch(function(e){console.log(e)}));case 3:case"end":return e.stop()}},e)}),(Rt=function(){var t=this,n=arguments;return new Promise(function(r,o){var i=e.apply(t,n);function a(e){xt(i,r,o,a,u,"next",e)}function u(e){xt(i,r,o,a,u,"throw",e)}a(void 0)})}).apply(this,arguments)}function Dt(e){return St({url:e,type:"GET",params:Et({},arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},{_:(new Date).getTime()})})}var Nt,Ct,jt,Bt={vars:[{text:"$$page_number",value:"$$page_number",type:"VARS",def:"当前的页数。"},{text:"$$totalPage_number",value:"$$totalPage_number",type:"VARS",def:"总页数。"}],JSONs:[{def:"ABS(number): 返回指定数字的绝对值。绝对值是指没有正负符号的数值。Number:需要求出绝对值的任意实数。示例:ABS(-1.5)等于1.5。ABS(0)等于0。ABS(2.5)等于2.5。",name:"ABS",type:"MATH"},{def:"ABS(number): 返回指定数字的绝对值。绝对值是指没有正负符号的数值。Number:需要求出绝对值的任意实数。示例:ABS(-1.5)等于1.5。ABS(0)等于0。ABS(2.5)等于2.5。",name:"ABS",type:"COMMON"},{def:"acc_sum(x_agg(array),range)根据横纵轴或行列维度添加的字段对指标进行跨行累计的计算。第一个参数为用户计算的指标,该指标必须为聚合函数或聚合指标;第二个参数range为用户设置计算的范围,0为对所有行进行累计,1为对组内所有行进行累计示例:acc_sum(sum_agg(array),0)用户横轴轴拖拽销售日期(年分组),则该指标计算结果为,根据销售日期(年)对销量进行分组汇总,然后根据对所有行从上到下进行累加,获得每年的累计销量",name:"ACC_SUM",type:"TABLE_CAL"},{def:"ACOS(number): 返回指定数值的反余弦值。反余弦值为一个角度,返回角度以弧度形式表示。Number:需要返回角度的余弦值。备注: 函数的参数必须在-1和1之间,包括-1和1。 返回的角度值在0和Pi之间。 如果要把返回的角度用度数来表示,用180/PI()乘返回值即可。示例:ACOS(1)等于0(弧度)。ACOS(0.5)等于1.047197551(Pi/3弧度)。ACOS(0.5)*180/PI()等于60(度)。",name:"ACOS",type:"MATH"},{def:"AND(logical1,logical2,…): 当所有参数的值为真时,返回TRUE;当任意参数的值为假时,返回FALSE。Logical1,logical2,…:指1到30个需要检验TRUE或FALSE的条件值。备注: 参数必须是逻辑值,或是含有逻辑值的数组或引用。 如果数组或引用中含有文本或空的单元格,则忽略其值。 如果在指定的单元格区域中没有逻辑值,AND函数将返回错误信息*NAME?。示例:AND(1+7=8,5+7=12)等于TRUE。AND(1+7=8,5+7=11)等于FALSE。如果单元格A1到A4的值分别为TRUE、TRUE、FALSE和TRUE,则:AND(A1:A4)等于FALSE。如果单元格A5的值在0~50之间,则: AND(0 0,b > 0 or a > 0, b < 0时,公式直接成立;a < 0,b > 0, ATAN2(a,b)=PI()-ABS(ATAN(b/a))a < 0,b < 0, ATAN2(a,b)=ABS(ATAN(b/a))-PI() 当x_num与y_num都为0时,ATAN2返回错误信息*DIV/0!。 用角度制显示返回数值时,把返回数值乘以180/PI()。 返回值以弧度表示(返回值大于-pi且小于等于pi)。示例:ATAN2(-2,2)等于2.356194490192345(弧度制的3*pi/4)。ATAN2(2,2)等于0.785398163(弧度制的pi/4)。ATAN2(-2,2)*180/PI()等于135(角度制)。",name:"ATAN2",type:"MATH"},{def:"AVG_AGG(array): 根据当前分析维度,动态返回指标字段的汇总平均值,生成结果为一动态数据列,行数与当前分析维度行数一致。\n array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。 \n 示例:用户横轴为维度字段'日'时,纵轴的计算字段AVG_AGG(销量)返回的值为每日的平均销量;当用户横轴为维度字段'月'时,AVG_AGG(销量)返回的值为每月的平均销量。",name:"AVG_AGG",type:"AGG"},{def:"CEILING(number): 将参数number沿绝对值增大的方向,舍入为最接近的整数Number:指待舍入的数值。CEILING(-2.5)等于-3。CEILING(0.5)等于1。",name:"CEILING",type:"MATH"},{def:"CHAR(number): 根据指定数字返回对应的字符。CHAR函数可将计算机其他类型的数字代码转换为字符。Number:用于指定字符的数字,介于1~65535之间(包括1和65535)。示例:CHAR(88)等于“X”。CHAR(45)等于“-”。",name:"CHAR",type:"TEXT"},{def:'CODE(text): 计算文本串中第一个字符的数字代码。返回的代码对应于计算机使用的字符集。Text:需要计算第一个字符代码的文本或单元格引用。示例:CODE("S")等于83。CODE("Spreadsheet")等于83。',name:"CODE",type:"TEXT"},{def:'CONCATENATE(text1,text2,...): 将数个字符串合并成一个字符串。Text1,text2,...:需要合并成单个文本的文本项,可以是字符,数字或是单元格引用。示例:CONCATENATE("Average ","Price")等于“Average Price”。CONCATENATE("1","2")等于12。',name:"CONCATENATE",type:"TEXT"},{def:"COS(number): 返回一个角度的余弦值。Number:以弧度表示的需要求余弦值的角度。备注: 要把一个角度转换成弧度值,将角度乘于PI()/180。 COS(n*2*PI()+number)=COS(number)(其中n为整数,number从-pi到pi)。示例:COS(0.5)等于0.877582562。COS(30*PI()/180)等于0.866025404。",name:"COS",type:"MATH"},{def:"COUNTD_AGG(array): 根据当前分析维度,动态返回某字段的去重计数,生成结果为一动态数据列,行数与当前分析维度行数一致。\n \"array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n \"示例:用户横轴为维度字段'日'时,纵轴的计算字段COUNTD_AGG(销量)返回的值为每日的销量的去重个数;当用户横轴为维度字段'月'时,COUNTD_AGG(销量)返回的值为每月的销量的去重个数。\"",name:"COUNTD_AGG",type:"AGG"},{def:"COUNT_AGG(array): 根据当前分析维度,动态返回某字段的计数,生成结果为一动态数据列,行数与当前分析维度行数一致。\n array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n 示例:用户横轴为维度字段'日'时,纵轴的计算字段COUNT_AGG(销量)返回的值为每日的销量的个数;当用户横轴为维度字段'月'时,COUNT_AGG(销量)返回的值为每月的销量的个数。",name:"COUNT_AGG",type:"AGG"},{def:"DATE(year,month,day): 返回一个表示某一特定日期的系列数。Year:代表年,可为一到四位数。Month:代表月份。若1 month 12,则函数把参数值作为月。若month>12,则函数从年的一月份开始往上累加。例如: DATE(2000,25,2)等于2002年1月2日的系列数。Day:代表日。若日期小于等于某指定月的天数,则函数将此参数值作为日。若日期大于某指定月的天数,则函数从指定月份的第一天开始往上累加。若日期大于两个或多个月的总天数,则函数把减去两个月或多个月的余数加到第三或第四个月上,依此类推。例如:DATE(2000,3,35)等于2000年4月4日的系列数。备注: 若需要处理公式中日期的一部分,如年或月等,则可用此公式。 若年,月和日是函数而不是函数中的常量,则此公式最能体现其作用。示例:DATE(1978, 9, 19) 等于1978-09-19.DATE(1211, 12, 1) 等于1211-12-01. ",name:"DATE",type:"DATETIME"},{def:'DATEDELTA(date, deltadays):返回一个日期date后deltadays的日期。deltaDays可以为正值,负值,零。示例:DATEDELTA("2008-08-08", -10)等于2008-07-29。DATEDELTA("2008-08-08", 10)等于2008-08-18。',name:"DATEDELTA",type:"DATETIME"},{def:'DATEDIF(start_date,end_date,unit):返回两个指定日期间的天数、月数或年数。Start_date:代表所指定时间段的初始日期。End_date:代表所指定时间段的终止日期。Unit:函数返回信息的类型。若unit=“Y”,则DATEDIF返回指定时间段的年差数。若unit=“M”,则DATEDIF返回指定时间段的月差数。若unit=“D”,则DATEDIF返回指定时间段的日差数。若unit=“MD”,则DATEDIF忽略年和月,返回指定时间段的日差数。若unit=“YM”,则DATEDIF忽略年和日,返回指定时间段的月差数。若unit=“YD”,则DATEDIF忽略年,返回指定时间段的日差数。示例:DATEDIF("2001/2/28","2004/3/20","Y")等于3,即在2001年2月28日与2004年3月20日之间有3个整年。DATEDIF("2001/2/28","2004/3/20","M")等于37,即在2001年2月28日与2004年3月20日之间有36个整月。DATEDIF("2001/2/28","2004/3/20","D")等于1116,即在2001年2月28日与2004年3月20日之间有1116个整天。DATEDIF("2001/2/28","2004/3/20","MD")等于8,即忽略月和年后,2001年2月28日与2004年3月20日的差为8天。DATEDIF("2001/1/28","2004/3/20","YM")等于2,即忽略日和年后,2001年1月28日与2004年3月20日的差为2个月。DATEDIF("2001/2/28","2004/3/20","YD")等于21,即忽略年后,2001年2月28日与2004年3月20日的差为21天。',name:"DATEDIF",type:"DATETIME"},{def:'DATESUBDATE(date1, date2, op):返回两个日期之间的时间差。op表示返回的时间单位:"s",以秒为单位。"m",以分钟为单位。"h",以小时为单位。"d",以天为单位。"w",以周为单位。示例:DATESUBDATE("2008-08-08", "2008-06-06","h")等于1512。',name:"DATESUBDATE",type:"DATETIME"},{def:'DATETONUMBER(date):返回自 1970 年 1 月 1 日 00:00:00 GMT 经过的毫秒数。示例:DATETONUMBER("2008-08-08")等于1218124800000。',name:"DATETONUMBER",type:"DATETIME"},{def:'DAY:(serial_number)返回日期中的日。DAY是介于1和31之间的一个数。Serial_number:含有所求的年的日期.备注:FineReport将日期保存为系列数,一个系列数代表一个与之匹配的日期,以方便用户对日期进行数值式计算。在1900年日期系统中,FineReport电子表格将1900年1月1日保存为系列数2,将1900年1月2日保存为系列数3,将1900年1月3日保存为系列数4……依此类推。如在1900年日期系统,1998年1月1日存为系列数35796。示例:DAY("2000/1/1")等于1。DAY("2006/05/05")等于5。DAY("1997/04/20")等于20。DAY("2000-1-1", "yyyy-MM-dd")等于1。DAY("2006-05-05", "yyyy-MM-dd")等于5。DAY("1997-04-20", "yyyy-MM-dd")等于20。DAY(35796)等于1。',name:"DAY",type:"DATETIME"},{def:'DAYS360(start_date,end_date,method):按照一年 360 天的算法(每个月以 30 天计,一年共计 12 个月),返回两日期间相差的天数,这在会计计算中将会用到。如果财务系统是基于一年 12 个月,每月 30 天,可用此函数帮助计算支付款项。Start_date 和 end_date :是用于计算期间天数的起止日期。Method : 它指定了在计算中是采用欧洲方法还是美国方法。Method 定义 :FALSE或忽略 美国方法 (NASD)。如果起始日期是一个月的 31 号,则等于同月的 30 号。如果终止日期是一个月的31号,并且起始日期早于 30 号,则终止日期等于下一个月的 1 号,否则,终止日期等于本月的 30 号。TRUE 欧洲方法。无论是起始日期还是终止日期为一个月的 31 号,都将等于本月的 30 号。备注:FineReport将日期保存为系列数,一个系列数代表一个与之匹配的日期,以方便用户对日期进行数值式计算。在1900年日期系统中,FineReport电子表格将1900年1月1日保存为系列数2,将1900年1月2日保存为系列数3,将1900年1月3日保存为系列数4……依此类推。如在1900年日期系统,1998年1月1日存为系列数35796。示例:DAYS360("1998/1/30", "1998/2/1") 等于 1',name:"DAYS360",type:"DATETIME"},{def:'DAYSOFMONTH(date):返回从1900年1月后某年某月包含的天数。示例:DAYSOFMONTH("1900-02-01")等于28。DAYSOFMONTH("2008/04/04")等于30。',name:"DAYSOFMONTH",type:"DATETIME"},{def:'DAYSOFQUARTER(date): 返回从1900年1月后某年某季度的天数。示例:DAYSOFQUARTER("2009-02-01")等于90。DAYSOFQUARTER("2009/05/05")等于91。',name:"DAYSOFQUARTER",type:"DATETIME"},{def:'DAYSOFYEAR(year):返回某年包含的天数。示例:DAYSOFYEAR(2008)等于365,等价于DAYSOFYEAR("2008-01-01")。',name:"DAYSOFYEAR",type:"DATETIME"},{def:'DAYVALUE(date):返回1900年至 date日期所经历的天数。示例:DAYVALUE("2008/08/08")等于39669。',name:"DAYVALUE",type:"DATETIME"},{def:"DEGREES(angle): 将弧度转化为度。angle:待转换的弧度角。示例:DEGREES(PI()/2)等于90。DEGREES(3.1415926)等于179.9999969。",name:"DEGREES",type:"MATH"},{def:'ENDWITH(str1,str2):判断字符串str1是否以str2结束。备注: str1和str2都是大小写敏感的。示例:ENDWITH("FineReport","Report")等于true。ENDWITH("FineReport","Fine")等于false。ENDWITH("FineReport","report")等于false。',name:"ENDWITH",type:"TEXT"},{def:'EXACT(text1,text2): 检测两组文本是否相同。如果完全相同,EXACT函数返回TRUE;否则,返回FALSE。EXACT函数可以区分大小写,但忽略格式的不同。同时也可以利用EXACT函数来检测输入文档的文字。Text1:需要比较的第一组文本。Text2:需要比较的第二组文本。示例:EXACT("Spreadsheet","Spreadsheet")等于TRUE。EXACT("Spreadsheet","S preadsheet")等于FALSE。EXACT("Spreadsheet","spreadsheet")等于FALSE。',name:"EXACT",type:"TEXT"},{def:"EXP(number): 返回e的n次幂。常数e为自然对数的底数,等于2.71828182845904。Number:为任意实数,作为常数e的指数。备注: 如果要返回其他常数作为底数的幂,可以使用指数运算符(^)。例如: 在4^2中,4是底数,而2是指数。 EXP函数与LN函数互为反函数。示例:EXP(0)等于1。EXP(3)等于20.08553692。EXP(LN(2))等于2。",name:"EXP",type:"MATH"},{def:"FACT(number):返回数的阶乘,一个数的阶乘等于 1*2*3*...*该数。number:要计算其阶乘的非负数。如果输入的 number 不是整数,则截尾取整。示例:FACT(1) 等于 1FACT(1.9) 等于 FACT(1) 等于 1FACT(0) 等于 1FACT(5) 等于 1*2*3*4*5 等于 120",name:"FACT",type:"MATH"},{def:'FIND(find_text,within_text,start_num):从指定的索引(start_num)处开始,返回第一次出现的指定子字符串(find_text)在此字符串(within_text)中的索引。Find_text:需要查找的文本或包含文本的单元格引用。Within_text:包含需要查找文本的文本或单元格引用。Start_num:指定进行查找字符的索引位置。within_text里的索引从1开始。如果省略start_num,则假设值为1。备注: 如果find_text不在within_text中,FIND函数返回值为0。 如果start_num不大于0,FIND函数返回错误信息*VALUE!。 如果start_num大于within_text的长度,FIND函数返回值为0。 如果find_text是空白文本,FIND函数将在搜索串中匹配第一个字符(即编号为start_num或1的字符)。示例:FIND("I","Information")等于1。FIND("i","Information")等于9。FIND("o","Information",2)等于4。FIND("o","Information",12)等于0。FIND("o","Information",-1)等于*VALUE!。',name:"FIND",type:"TEXT"},{def:"FLOOR(number): 将参数number沿绝对值减小的方向去尾舍入。Number:待舍入的数值。示例:FLOOR(-2.5)等于-2。FLOOR(2.5)等于2。",name:"FLOOR",type:"MATH"},{def:'FORMAT(object,format) : 返回object的format格式。object 需要被格式化对象,可以是String,数字,Object(常用的有Date, Time)。format 格式化的样式。示例FORMAT(1234.5, "#,##0.00") => 1234.50FORMAT(1234.5, "#,##0") => 1234FORMAT(1234.5, "¥#,##0.00") => ¥1234.50FORMAT(1.5, "0%") => 150%FORMAT(1.5, "0.000%") => 150.000%FORMAT(6789, "##0.0E0") => 6.789E3FORMAT(6789, "0.00E00") => 6.79E03FORMAT(date(2007,1,1), "EEEEE, MMMMM dd, yyyy") => 星期一,一月 01,2007FORMAT(date(2007,1,13), "MM/dd/yyyy") => 01/13/2007FORMAT(date(2007,1,13), "M-d-yy") => 1-13-07FORMAT(time(16,23,56), "h:mm:ss a") => 4:23:56 下午',name:"FORMAT",type:"TEXT"},{def:'HOUR(serial_number):返回某一指定时间的小时数。函数指定HOUR为0(0:00)到23(23:00)之间的一个整数。Serial_number:包含所求小时的时间。示例:HOUR("11:32:40")等于11。HOUR("11:32:40", "HH:mm:ss")等于11。',name:"HOUR",type:"DATETIME"},{def:'IF(boolean,number1/string1,number2/string2):判断函数,boolean为true时返回第二个参数,为false时返回第三个。boolean: 用于判断的布尔值,true或者false。number1/string1: 第一个参数,如果boolean为ture,返回这个值。number2/string2: 第二个参数,如果boolean为false,返回这个值。示例:IF(true,2,8)等于2IF(false,"first","second")等于secondIF(true,"first",7)等于first',name:"IF",type:"LOGIC"},{def:'IF(boolean,number1/string1,number2/string2):判断函数,boolean为true时返回第二个参数,为false时返回第三个。boolean: 用于判断的布尔值,true或者false。number1/string1: 第一个参数,如果boolean为ture,返回这个值。number2/string2: 第二个参数,如果boolean为false,返回这个值。示例:IF(true,2,8)等于2IF(false,"first","second")等于secondIF(true,"first",7)等于first',name:"IF",type:"COMMON"},{def:'INDEXOF(str1,index):返回字符串str1在index位置上的字符。备注: index是从0开始计数的。示例:INDEXOF("FineReport",0)等于\'F\'。INDEXOF("FineReport",2)等于\'n\'。INDEXOF("FineReport",9)等于\'t\'。INDEXOF(array, index):返回数组在index位置上的元素。备注: index是从1开始计数的。示例:String[] array = {"a", "b", "c"}INDEXOF(array, 1)等于"a".',name:"INDEXOF",type:"TEXT"},{def:"INT(number): 返回数字下舍入(数值减小的方向)后最接近的整数值。Number:需要下舍入为整数的实数。示例:INT(4.8)等于4。INT(-4.8)等于-5。INT(4.3)等于4。INT(-4.3)等于-5。公式INT(A1)将返回A1单元格中的一个正实数的整数数部分。",name:"INT",type:"MATH"},{def:"INT(number): 返回数字下舍入(数值减小的方向)后最接近的整数值。Number:需要下舍入为整数的实数。示例:INT(4.8)等于4。INT(-4.8)等于-5。INT(4.3)等于4。INT(-4.3)等于-5。公式INT(A1)将返回A1单元格中的一个正实数的整数数部分。",name:"INT",type:"COMMON"},{def:"ISNULL(object):判断对象中所有的值是否全部都是NULL或者为空字符串。",name:"ISNULL",type:"OTHER"},{def:'LEFT(text,num_chars): 根据指定的字符数返回文本串中的第一个或前几个字符。Text:包含需要选取字符的文本串或单元格引用。Num_chars:指定返回的字符串长度。备注: Num_chars的值必须等于或大于0。 如果num_chars大于整个文本的长度,LEFT函数将返回所有的文本。 如果省略num_chars,则默认值为1。示例:LEFT("Fine software",8)等于“Fine sof”。LEFT("Fine software")等于“F”。如果单元格A3中含有“China”,则LEFT(A3,2)等于“Ch”。',name:"LEFT",type:"TEXT"},{def:"LEN(args): 返回文本串中的字符数或者数组的长度。需要注意的是:参数args为文本串时,空格也计为字符。参数args为数组时,直接返回数组长度。示例:LEN(\"Evermore software\")等于17。LEN(\" \")等于1。LEN(['a','b'])等于2。",name:"LEN",type:"TEXT"},{def:"LN(number):返回一个数的自然对数。自然对数以常数项 e(2.71828182845904)为底。number:是用于计算其自然对数的正实数。示例:LN(86) 等于 4.45437LN(2.7182818) 等于 1LN(EXP(3)) 等于 3EXP(LN(4)) 等于 4",name:"LN",type:"MATH"},{def:"LOG(number,base): 按指定的任意底数,返回数值的对数。Number:需要求对数的正实数。Base:对数的底数。如果省略底数,默认值为10。示例:LOG(16,2)等于4。LOG(10)等于1。LOG(24,3)等于2.892789261。",name:"LOG",type:"MATH"},{def:"LOG10(number):返回以 10 为底的对数。number: 用于常用对数计算的正实数。示例:LOG10(86) 等于 1.934498451LOG10(10) 等于 1LOG10(1E5) 等于 5",name:"LOG10",type:"MATH"},{def:'LOWER(text): 将所有的大写字母转化为小写字母。Text:需要转化为小写字母的文本串。LOWER函数不转化文本串中非字母的字符。示例:LOWER("A.M.10:30")等于“a.m.10:30”。LOWER("China")等于“china”。',name:"LOWER",type:"TEXT"},{def:"LUNAR(year,day,month): 返回当前日期对应的农历时间。year,month,day:分别对应年月日。示例:如果需要查询2011年7月21日对应的农历时间,则只需输入LUNAR(2011,7,21)结果将显示为:辛卯年六月廿一同样,如输入LUNAR(2001,7,21),则显示:辛巳年六月初一 。本公式支持的时间段为1900-2100年。",name:"LUNAR",type:"DATETIME"},{def:"MAX(number1,number2,…): 返回参数列表中的最大值。Number1,number2,…:1到30个需要找出最大值的参数。备注: 参数可以是数字、空白单元格、逻辑值或数字的文本表达式。 如果数组或引用参数中包含可解析文本值,逻辑值,零值或空白单元格,这些值都将参与计算,而不可解析的文本值忽略不计。 如果参数中没有任何数字,MAX将返回0。示例:MAX(0.1,0,1.2)等于1.2。",name:"MAX",type:"MATH"},{def:"MAX_AGG(array): 根据当前分析维度,动态返回指标字段的最大值,生成结果为一动态数据列,行数与当前分析维度行数一致。\n \"array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n \"示例:用户横轴为维度字段'日'时,纵轴的计算字段MAX_AGG(销量)返回的值为每日的最大值销量;当用户横轴为维度字段'月'时,MAX_AGG(销量)返回的值为每月的最大值销量。",name:"MAX_AGG",type:"AGG"},{def:"MEDIAN_AGG(array): 根据当前分析维度,动态返回指标字段的中位数,生成结果为一动态数据列,行数与当前分析维度行数一致。\n \"array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n \"示例:用户横轴为维度字段'日'时,纵轴的计算字段MEDIAN_AGG(销量)返回的值为每日的中位数销量;当用户横轴为维度字段'月'时,MEDIAN_AGG(销量)返回的值为每月的中位数销量。",name:"MEDIAN_AGG",type:"AGG"},{def:'MID(text,start_num,num_chars): 返回文本串中从指定位置开始的一定数目的字符,该数目由用户指定。Text:包含要提取字符的文本串。Start_num:文本中需要提取字符的起始位置。文本中第一个字符的start_num为1,依此类推。Num_chars:返回字符的长度。备注: 如果start_num大于文本长度,MID函数返回“”(空文本)。 如果start_num小于文本长度,并且start_num加上num_chars大于文本长度,MID函数将从start_num指定的起始字符直至文本末的所有字符。 如果start_num小于1,MID函数返回错误信息*VALUE!。 如果num_chars是负数,MID函数返回错误信息*VALUE!。示例:MID("Finemore software",10,8)返回“software”。MID("Finemore software",30,5)返回“”(空文本)。MID("Finemore software",0,8)返回*VALUE!。MID("Finemore software",5,-1)返回*VALUE!。',name:"MID",type:"TEXT"},{def:"MIN(number1,number2,…): 返回参数列表中的最小值。Number1,number2,…:1到30个需要找出最小值的参数。备注: 若参数中没有数字,函数MIN将返回0。 参数应为数字、空白单元格、逻辑值或是表示数值的文本串。如果参数是错误值时,MIN将返回错误信息。 如果数组或引用参数中包含可解析文本值,逻辑值,零值或空白单元格,这些值都将参与计算,而不可解析的文本值忽略不计。示例:如果B1:B4包含3,6,9,12,则:MIN(B1:B4)等于3。MIN(B1:B4,0)等于0。",name:"MIN",type:"MATH"},{def:'MINUTE(serial_number):返回某一指定时间的分钟数,其值是介于0与59之间的一个整数。serial_number:包含所求分钟数的时间。示例:MINUTE("15:36:25")等于36。MINUTE("15:36:25", "HH:mm:ss")等于36。',name:"MINUTE",type:"DATETIME"},{def:"MIN_AGG(array): 根据当前分析维度,动态返回指标字段的最小值,生成结果为一动态数据列,行数与当前分析维度行数一致。\n \"array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n \"示例:用户横轴为维度字段'日'时,纵轴的计算字段MIN_AGG(销量)返回的值为每日的最小值销量;当用户横轴为维度字段'月'时,MIN_AGG(销量)返回的值为每月的最小值销量。",name:"MIN_AGG",type:"AGG"},{def:"MOD(number,divisor):返回两数相除的余数。结果的正负号与除数相同。number:为被除数。divisor:为除数。示例:MOD(3, 2) 等于 1MOD(-3, 2) 等于 1MOD(3, -2) 等于 -1MOD(-3, -2) 等于 -1",name:"MOD",type:"MATH"},{def:'MONTH:(serial_number)返回日期中的月。月是介于1和12之间的一个数。Serial_number:含有所求的月的日期.备注:FineReport将日期保存为系列数,一个系列数代表一个与之匹配的日期,以方便用户对日期进行数值式计算。在1900年日期系统中,FineReport电子表格将1900年1月1日保存为系列数2,将1900年1月2日保存为系列数3,将1900年1月3日保存为系列数4……依此类推。如在1900年日期系统,1998年1月1日存为系列数35796。示例:MONTH("2000/1/1")等于1。MONTH("2006/05/05")等于5。MONTH("1997/04/20")等于4。MONTH("2000-1-1", "yyyy-MM-dd")等于1。MONTH("2006-05-05", "yyyy-MM-dd")等于5。MONTH("1997-04-20", "yyyy-MM-dd")等于4。MONTH(35796)等于1。',name:"MONTH",type:"DATETIME"},{def:'MONTHDELTA(date,delta):返回指定日期date后delta个月的日期。示例:MONTHDELTA("2008-08-08", 4)等于2008-12-08。',name:"MONTHDELTA",type:"DATETIME"},{def:"NOW():获取当前时间。示例:如果系统时间是2012年5月12日 15点18分38秒则NOW()等于2012-05-12 15:18:36。",name:"NOW",type:"DATETIME"},{def:"NUMTO(number,bool)或NUMTO(number):返回number的中文表示。其中bool用于选择中文表示的方式,当没有bool时采用默认方式显示。示例:NUMTO(2345,true)等于二三四五。示例:NUMTO(2345,false)等于二千三百四十五。示例:NUMTO(2345)等于二千三百四十五。",name:"NUMTO",type:"TEXT"},{def:"NVL(value1,value2,value3,...):在所有参数中返回第一个不是null的值value1:可以为任意数,也可以为null。value2:可以为任意数,也可以为null。当字符串长度为0时, 返回也为null示例:NVL(12,20)等于12。NVL(null,12)等于12。NVL(null,null)等于null。NVL(20,null)等于20。NVL(null,null,10)等于10。",name:"NVL",type:"OTHER"},{def:"OR(logical1,logical2,…): 当所有参数的值为假时,返回FALSE;当任意参数的值为真时,返回TRUE。Logical1,logical2,…:指1到30个需要检验TRUE或FALSE的条件值。备注: 参数必须是逻辑值,或是含有逻辑值的数组或引用。 如果数组或引用中含有文本或空的单元格,则忽略其值。 如果在指定的单元格区域中没有逻辑值,AND函数将返回错误信息*NAME?。示例:OR(1+7=9,5+7=11)等于FALSE。OR(1+7=8,5+7=11)等于TRUE。",name:"OR",type:"LOGIC"},{def:'period_anls(x_agg(array),datepart)根据横纵轴或行列维度添加的日期字段进行上期末的计算。第一个参数为用于计算的指标,该指标必须为聚合函数或聚合指标;第二个参数用于配置计算的上期末为上年期末或者上月期末。横纵轴拖拽的字段不满足函数的计算要求时,该指标会标红。示例:period_anls(sum_agg(amount),"Y") 用户横纵轴拖拽销售日期(年月日分组),则该指标计算结果为,根据年月日对销量进行分组汇总,然后计算出该日数据上年年末的销量;如果参数2为“M”,则计算结果为该日销量上月月末的销量。',name:"PERIOD_ANLS",type:"TABLE_CAL"},{def:"PI(number): 是一个数学常量函数,当number为空时,函数返回精确到15位的数值3.141592653589793;当参数不为空时,number表示PI的倍数。示例:SIN(PI()/2)等于1。计算圆的面积的公式: S=PI()*(r^2),其中S为圆的面积,R为圆的半径。PI(3)等于9.42477796076938。",name:"PI",type:"MATH"},{def:"POWER(number,power): 返回指定数字的乘幂。Number:底数,可以为任意实数。Power:指数。参数number按照该指数次幂乘方。备注: 可以使用符号“^”代替POWER,如: POWER(5,2)等于5^2。示例:POWER(6,2)等于36。POWER(14,5)等于537824。POWER(4,2/3)等于2.519842100。POWER(3,-2.3)等于0.079913677。",name:"POWER",type:"MATH"},{def:"previous_period(x_agg(array))根据横纵轴或行列维度添加的日期字段进行环期值的计算。参数为用于计算的指标,该指标必须为聚合函数或聚合指标。横纵轴拖拽的字段不满足函数的计算要求时,该指标会标红。示例:previous_period(sum_agg(amount)) 用户横纵轴拖拽销售日期(年月日分组),则该指标计算结果为,根据年月日对销量进行分组汇总,然后计算出该日数据上一日的销量。",name:"PREVIOUS_PERIOD",type:"TABLE_CAL"},{def:"PROMOTION(value1,value2):返回value2在value1上提升的比例。示例:PROMOTION(12, 14)等于0.166666666,即提升了16.6666666%.PROMOTION(-12, 14)等于2.166666666,即提升了216.6666666%.",name:"PROMOTION",type:"MATH"},{def:'PROPER(text): 将文本中的第一个字母和所有非字母字符后的第一个字母转化成大写,其他字母变为小写。Text:需要转化为文本的公式、由双引号引用的文本串或是单元格引用。示例:PROPER("Finemore Integrated Office")等于“Finemore Integrated Office”。PROPER("100 percent")等于“100 Percent”。PROPER("SpreaDSheEt")等于“Spreadsheet”。',name:"PROPER",type:"TEXT"},{def:"RADIANS(angle): 将角度转换成弧度。Angle:需要转换为弧度的角度。示例:RADIANS(90)等于1.570796327。",name:"RADIANS",type:"MATH"},{def:"RAND(): 返回均匀分布的随机数。每计算一次工作表,函数都会返回一个新的随机数值。备注: 要生成一个位于a和b之间的随机数,可以使用以下的公式: C=RAND()*(b-a)+a。 如果要使一个随机产生的数值不随单元格的重计算而改变,可以在编辑框中输入=RAND()并保持编辑状态,然后按F9,将公式永久性地改为随机数。示例:假如需要生成一个大于等于0,小于60的随机数,使用公式: =RAND()*60。假如需要生成一个大于等于0,小于19的随机数,使用公式: =RAND()*19。假如需要生成一个大于等于0,小于50的随机数,使用公式: =RAND()*50。",name:"RAND",type:"MATH"},{def:"RANDBETWEEN(value1,value2):返回value1和value2之间的一个随机整数。示例:RANDBETWEEN(12.333, 13.233)只会返回13。RANDBETWEEN(11.2, 13.3)有可能返回12或者13。",name:"RANDBETWEEN",type:"MATH"},{def:'rank_anls(x_agg(array),range,order)根据横纵轴或行列维度添加的字段对指标进行跨行排名的计算。第一个参数为用户计算的指标,该指标必须为聚合函数或聚合指标;第二个参数range为用户设置计算的范围,0为对所有行进行排名,1为对组内所有行进行排名;第三个参数order为排名的计算规则,"asc"为升序排名,"desc"为降序排名。示例:rank_anls(sum_agg(amount),0,"asc")用户横轴轴拖拽省份,则该指标计算结果为,根据省份对销量进行分组汇总,然后计算每个省份的销量在所有省份中的升序排名情况。',name:"RANK_ANLS",type:"TABLE_CAL"},{def:'REGEXP(str, pattern):字符串str是否与正则表达式pattern相匹配。示例:REGEXP("aaaaac","a*c")等于true。REGEXP("abc","a*c")等于false。REGEXP(str, pattern, intNumber):字符串str是否与具有给定模式 intNumber的正则表达式pattern相匹配。示例:CASE_INSENSITIVE = 0 启用不区分大小写的匹配。 默认情况下,不区分大小写的匹配假定仅匹配 US-ASCII 字符集中的字符。可以通过指 定 UNICODE_CASE 标志连同此标志来启用 Unicode 感知的、不区分大小写的匹配。 MULTILINE = 1 启用多行模式。DOTALL = 2 启用 dotall 模式。在 dotall 模式中,表达式 . 可以匹配任何字符,包括行结束符。默认情况下,此表达式不匹配行 结束符。UNICODE_CASE = 3 启用 Unicode 感知的大小写折叠。指定此标志后,由 CASE_INSENSITIVE 标志启用时,不区分大小写的匹配将以 符合 Unicode Standard 的方式完成。CANON_EQ = 4 启用规范等价。 指定此标志后,当且仅当其完整规范分解匹配时,两个字符才可视为匹配。UNIX_LINES = 5 启用 Unix 行模式。 在此模式中,.、^ 和 $ 的行为中仅识别 \'\n\' 行结束符。LITERAL = 6 启用模式的字面值解析。 指定此标志后,指定模式的输入字符串就会作为字面值字符序列来对待。输入序列中的 元字符或转义序列不具有任何特殊意义。 标志 CASE_INSENSITIVE 和 UNICODE_CASE 在与此标志一起使用时将 对匹配产生影响。其他标志都变得多余了。COMMENTS = 7 模式中允许空白和注释。 此模式将忽略空白和在结束行之前以 # 开头的嵌入式注释。 REGEXP("Aaaaabbbbc","a*b*c", 3)等于true。REGEXP("Aaaaabbbbc","a*b*c", 1)等于false。',name:"REGEXP",type:"TEXT"},{def:'REPEAT(text,number_times): 根据指定的次数重复显示文本。REPEAT函数可用来显示同一字符串,并对单元格进行填充。Text:需要重复显示的文本或包含文本的单元格引用。Number_times:指定文本重复的次数,且为正数。如果number_times为0,REPEAT函数将返回“”(空文本)。如果number_times不是整数,将被取整。REPEAT函数的最终结果通常不大于32767个字符。备注: 该函数可被用于在工作表中创建简单的直方图。示例:REPEAT("$",4)等于“$$$$”。如果单元格B10的内容为“你好”,REPEAT(B10,3)等于“你好你好你好”。',name:"REPEAT",type:"TEXT"},{def:'REPLACE(text, texttoreplace, replacetext):根据指定字符串,用其他文本来代替原始文本中的内容。text:需要被替换部分字符的文本或单元格引用。texttoreplace:指定的字符串。replacetext:需要替换部分旧文本的文本。示例:REPLACE("abcd", "a", "re")等于"rebcd"。REPLACE("a**d", "**d", "rose")等于"arose"。REPLACE(old_text,start_num,num_chars,new_text): 根据指定的字符数,用其他文本串来替换某个文本串中的部分内容。Old_text:需要被替换部分字符的文本或单元格引用。Start_num:需要用new_text来替换old_text中字符的起始位置。Num_chars:需要用new_text来替换old_text中字符的个数。New_text:需要替换部分旧文本的文本。示例:REPLACE("0123456789",5,4,"*")等于“0123*89”。REPLACE("1980",3,2,"99")等于“1999”。',name:"REPLACE",type:"TEXT"},{def:'RIGHT(text,num_chars): 根据指定的字符数从右开始返回文本串中的最后一个或几个字符。Text:包含需要提取字符的文本串或单元格引用。Num_chars:指定RIGHT函数从文本串中提取的字符数。Num_chars不能小于0。如果num_chars大于文本串长度,RIGHT函数将返回整个文本。如果不指定num_chars,则默认值为1。示例:RIGHT("It is interesting",6)等于“esting”。RIGHT("Share Holder")等于“r”。RIGHT("Huge sale",4)等于“sale”。',name:"RIGHT",type:"TEXT"},{def:"ROUND(number,num_digits):返回某个数字按指定位数舍入后的数字。number:需要进行舍入的数字。num_digits:指定的位数,按此位数进行舍入。如果 num_digits 大于 0,则舍入到指定的小数位。如果 num_digits 等于 0,则舍入到最接近的整数。如果 num_digits 小于 0,则在小数点左侧进行舍入。示例:ROUND(2.15, 1) 等于 2.2ROUND(2.149, 1) 等于 2.1ROUND(-1.475, 2) 等于 -1.48ROUND(21.5, -1) 等于 20因浮点数存在精度计算丢失问题, 导致计算结果里可能带上9999, 0000这些, 因此加入第三个参数来控制是否需要去除9999. true表示需要过滤9999, 0000这些数据.",name:"ROUND",type:"MATH"},{def:"ROUND(number,num_digits):返回某个数字按指定位数舍入后的数字。number:需要进行舍入的数字。num_digits:指定的位数,按此位数进行舍入。如果 num_digits 大于 0,则舍入到指定的小数位。如果 num_digits 等于 0,则舍入到最接近的整数。如果 num_digits 小于 0,则在小数点左侧进行舍入。示例:ROUND(2.15, 1) 等于 2.2ROUND(2.149, 1) 等于 2.1ROUND(-1.475, 2) 等于 -1.48ROUND(21.5, -1) 等于 20因浮点数存在精度计算丢失问题, 导致计算结果里可能带上9999, 0000这些, 因此加入第三个参数来控制是否需要去除9999. true表示需要过滤9999, 0000这些数据.",name:"ROUND",type:"COMMON"},{def:'same_period(x_agg(array),datepart)根据横纵轴或行列维度添加的日期字段进行同期值的计算。第一个参数为用于计算的指标,该指标必须为聚合函数或聚合指标;第二个参数用于配置计算同期时计算某日的年同期或者某日的月同期。横纵轴拖拽的字段不满足函数的计算要求时,该指标会标红。示例:same_period(sum_agg(amount),"Y") 用户横纵轴拖拽销售日期(年月日分组),则该指标计算结果为,根据年月日对销量进行分组汇总,然后计算出该日数据上年同日的销量;如果参数2为“M”,则计算结果为该日销量上月同日的销量。',name:"SAME_PERIOD",type:"TABLE_CAL"},{def:'SECOND(serial_number):返回某一指定时间的秒数,其值是介于0与59之间的一个整数。Serial_number:包含所求秒数的时间。示例:SECOND("15:36:25")等于25。SECOND("15:36:25", "HH:mm:ss")等于25。',name:"SECOND",type:"DATETIME"},{def:"SIGN(number):返回数字的符号。当数字为正数时返回 1,为零时返回 0,为负数时返回 -1。Number:为任意实数。示例:SIGN(10) 等于 1SIGN(4-4) 等于 0SIGN(-0.00001) 等于 -1",name:"SIGN",type:"MATH"},{def:"SIN(number): 计算给定角度的正弦值。Number:待求正弦值的以弧度表示的角度。备注: 如果参数的单位是度,将其乘以PI()/180即可转换成弧度。示例:SIN(10)等于-0.5440211108893698。SIN(45*PI()/180)等于0.707106781。",name:"SIN",type:"MATH"},{def:'SPLIT(String1,String2):返回由String2分割String1组成的字符串数组。String1:以双引号表示的字符串。String2:以双引号表示的分隔符。例如逗号","示例:SPLIT("hello,world,yes",",") = ["hello","world","yes"]。SPLIT("this is very good"," ") = ["this","is","very","good"]。备注:如果只有一个参数,则返回一个错误。如果有多个参数,则只有前两个起作用。',name:"SPLIT",type:"TEXT"},{def:"SQRT(number): 返回一个正数的平方根。Number:要求其平方根的任一正数。备注:Number必须是一个正数,否则函数返回错误信息*NUM!。示例:SQRT(64)等于8。SQRT(-64)返回*NUM!。",name:"SQRT",type:"MATH"},{def:'STARTWITH(str1,str2):判断字符串str1是否以str2开始。备注: str1和str2都是大小写敏感的。示例:STARTWITH("FineReport","Fine")等于true。STARTWITH("FineReport","Report")等于false。STARTWITH("FineReport","fine")等于false。',name:"STARTWITH",type:"TEXT"},{def:"STDEV_AGG(array): 根据当前分析维度,动态返回指标字段的标准差,生成结果为一动态数据列,行数与当前分析维度行数一致。\n \"array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n \"示例:用户横轴为维度字段'日'时,纵轴的计算字段STDEV_AGG(销量)返回的值为每日的销量标准差;当用户横轴为维度字段'月'时,STDEV_AGG(销量)返回的值为每月的销量标准差。",name:"STDEV_AGG",type:"AGG"},{def:'SUBSTITUTE(text,old_text,new_text,instance_num): 用new_text替换文本串中的old_text。Text:需要被替换字符的文本,或含有文本的单元格引用。Old_text:需要被替换的部分文本。New_text:用于替换old_text的文本。Instance_num:指定用new_text来替换第几次出现的old_text。如果指定了instance_num,则只有指定位置上的old_text被替换,否则文字串中出现的所有old_text都被new_text替换。备注: 如果需要替换文本串中的指定文本,则使用SUBSTITUTE函数;如果需要替换文本串中指定位置上的任意文本,则使用REPLACE函数。示例:SUBSTITUTE("data base","base","model")等于“data model”。SUBSTITUTE("July 28, 2000","2","1",1)等于“July 18, 2000”。SUBSTITUTE("July 28, 2000","2","1")等于“July 18, 1000”。SUBSTITUTE("July 28, 2000","2","1",2)等于“July 28, 1000”。 ',name:"SUBSTITUTE",type:"TEXT"},{def:"SUM_AGG(array):根据当前分析维度,动态返回指标字段的汇总求和值,生成结果为一动态数据列,行数与当前分析维度行数一致。\n array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n 示例:用户横轴为维度字段'日'时,纵轴的计算字段SUM_AGG(销量)返回的值为每日的汇总销量;当用户横轴为维度字段'月'时,SUM_AGG(销量)返回的值为每月的汇总销量。",name:"SUM_AGG",type:"AGG"},{def:"switch(表达式, 值1, 结果1, 值2, 结果2, ...)如果表达式的结果是值1,整个函数返回结果1如果表达式的结果是值2,整个函数返回结果2如果表达式的结果是值3,整个函数返回结果3等等",name:"SWITCH",type:"LOGIC"},{def:"TAN(number): 返回指定角度的正切值。Number:待求正切值的角度,以弧度表示。如果参数是以度为单位的,乘以Pi()/180后转换为弧度。示例:TAN(0.8)等于1.029638557。TAN(45*Pi()/180)等于1。",name:"TAN",type:"MATH"},{def:"TIME(hour,minute,second): 返回代表指定时间的小数。介于0:00:00(12:00:00 A.M.)与23:59:59(11:59:59 P.M.)之间的时间可返回0到0.99999999之间的对应数值。Hour:介于0到23之间的数。Minute:介于0到59之间的数。Second:介于0到59之间的数。示例:TIME(14,40,0)等于2:40 PM。TIME(19,43,24)等于7:43 PM。",name:"TIME",type:"DATETIME"},{def:'TODATE()函数可以将各种日期形式的参数转换为日期类型。它有三种参数的形式:1 参数是一个日期型的参数,那么直接将这个参数返回。示例:TODATE(DATE(2007,12,12))返回2007年12月12日组成的日期。2 参数是以从1970年1月1日0时0分0秒开始的毫秒数,返回对应的时间。示例:TODATE(1023542354746)返回2002年6月8日。3 参数是日期格式的文本,那么返回这个文本对应的日期。示例:TODATE("2007/10/15")返回2007年10月5日组成的日期。TODATE("2007-6-8")返回2007年6月8日组成的日期。4 有两个参数,第一个参数是一个日期格式的文本,第二个参数是用来解析日期的格式。示例:TODATE("1/15/07","mm/dd/yy")返回07年1月15日组成的日期。特别的,"yyyyMMdd"是用来解析形如“20081230”之类的日期格式的。比如TODATE("20110830","yyyyMMdd")返回11年08月30日组成的日期5 有三个参数,第一个参数是一个日期格式的文本,第二个参数是用来解析日期的格式,第三个参数为解析日期的语言,如:zh(中文),en(英文)。示例:TODATE("星期三 1/15/07","EEE mm/dd/yy", "zh")返回07年1月15日组成的日期,使用“zh(中文)”才能够正常解析“星期三”这个字符串。',name:"TODATE",type:"DATETIME"},{def:"TODAY():获取当前日期。示例:如果系统日期是2005年9月10日则TODAY()等于2005-9-10。",name:"TODAY",type:"DATETIME"},{def:'TODOUBLE(text): 将文本转换成Double对象。Text:需要转换的文本。示例:TODOUBLE("123.21")等于 new Double(123.21)。',name:"TODOUBLE",type:"TEXT"},{def:'TOINTEGER(text): 将文本转换成Integer对象。Text:需要转换的文本。示例:TOINTEGER("123")等于 new Integer(123)。',name:"TOINTEGER",type:"TEXT"},{def:'total(x_agg(array),range,agg)根据横纵轴或行列维度添加的字段对指标进行跨行汇总的计算。第一个参数为用户计算的指标,该指标必须为聚合函数或聚合指标;第二个参数range为用户设置计算的范围,0为对所有行进行汇总,1为对组内所有行进行汇总;第三个参数agg为汇总的计算规则,"sum"为求和;"avg"为求平均,"max"为求最大值,"min"为求最小值示例:total(sum_agg(array),0,"avg")用户横纵轴拖拽省份,则该指标计算结果为,根据省份对销量进行分组汇总,然后计算平均每个省份的销量',name:"TOTAL",type:"TABLE_CAL"},{def:'TRIM(text): 清除文本中所有空格,单词间的单个空格除外,也可用于带有不规则空格的文本。Text:需要清除空格的文本。示例:TRIM(" Monthly Report")等于Monthly Report。',name:"TRIM",type:"TEXT"},{def:"TRUNC(number,num_digits):将数字的小数部分截去,返回整数。number:需要截尾取整的数字。num_digits:用于指定取整精度的数字。示例:TRUNC(8.9) 等于 8TRUNC(-8.9) 等于 -8TRUNC(PI()) 等于 3",name:"TRUNC",type:"MATH"},{def:'UPPER(text): 将文本中所有的字符转化为大写。Text:需要转化为大写字符的文本,或是包含文本的单元格引用。示例:UPPER("notes")等于“NOTES”。如果单元格E5的值为“Examples”,则UPPER(E5)等于“EXAMPLES”。',name:"UPPER",type:"TEXT"},{def:"VAR_AGG(array): 根据当前分析维度,动态返回指标字段的方差,生成结果为一动态数据列,行数与当前分析维度行数一致。\n \"array必须为非聚合函数公式返回的结果,可以是某指标字段、维度或指标字段与普通公式的计算结果。\n \"示例:用户横轴为维度字段'日'时,纵轴的计算字段VAR_AGG(销量)返回的值为每日的销量方差;当用户横轴为维度字段'月'时,VAR_AGG(销量)返回的值为每月的销量方差。",name:"VAR_AGG",type:"AGG"},{def:'WEEK(serial_num):返回一个代表一年中的第几周的数字。Serial_num:表示输入的日期。备注:FineReport将日期保存为系列数,一个系列数代表一个与之匹配的日期,以方便用户对日期进行数值式计算。在1900年日期系统中,FineReport电子表格将1900年1月1日保存为系列数2,将1900年1月2日保存为系列数3,将1900年1月3日保存为系列数4……依此类推。如在1900年日期系统,1998年1月1日存为系列数35796。示例:WEEK("2010/1/1")等于52。WEEK("2010/1/6")等于1。WEEK(35796)等于1。',name:"WEEK",type:"DATETIME"},{def:"weekdate(year,month,weekOfMonth,dayOfWeek): 返回指定年月的指定周的周几的具体日期。示例:weekdate(2009,10,2,1)返回的是2009年的10月的第二个周的第一天即星期天的日期,返回的是2009-10-04最后一个参数dayOfWeek为-1时,表示这个周的最后一天示例:weekdate(2009,12,1,-1)返回的是2009年的12月的第一个周的最后一天即星期六的日期,返回的是2009-12-05",name:"WEEKDATE",type:"DATETIME"},{def:'WEEKDAY(Serial_number):获取日期并返回星期数。返回值为介于0到6之间的某一整数,分别代表星期中的某一天(从星期日到星期六)。Serial_number:输入的日期备注:FineReport将日期保存为系列数,一个系列数代表一个与之匹配的日期,以方便用户对日期进行数值式计算。在1900年日期系统中,FineReport电子表格将1900年1月1日保存为系列数2,将1900年1月2日保存为系列数3,将1900年1月3日保存为系列数4……依此类推。如在1900年日期系统,1998年1月1日存为系列数35796。举例:WEEKDAY("2005/9/10")等于6(星期六)。WEEKDAY("2005/9/11")等于0(星期日)。WEEKDAY(35796)等于4(星期四)。',name:"WEEKDAY",type:"DATETIME"},{def:'YEAR:(serial_number)返回日期中的年。Year是介于1900和9999之间的一个数。Serial_number:含有所求的年的日期.备注:FineReport将日期保存为系列数,一个系列数代表一个与之匹配的日期,以方便用户对日期进行数值式计算。在1900年日期系统中,FineReport电子表格将1900年1月1日保存为系列数2,将1900年1月2日保存为系列数3,将1900年1月3日保存为系列数4……依此类推。如在1900年日期系统,1998年1月1日存为系列数35796。示例:YEAR("2000/1/1")等于2000。YEAR("2006/05/05")等于2006。YEAR("1997/04/20")等于1997。YEAR("2000-1-1", "yyyy-MM-dd")等于2000。YEAR("2006-05-05", "yyyy-MM-dd")等于2006。YEAR("1997-04-20", "yyyy-MM-dd")等于1997。YEAR(35796)等于1998。',name:"YEAR",type:"DATETIME"},{def:'YEARDELTA(date, delta):返回指定日期后delta年的日期。示例:YEARDELTA("2008-10-10",10)等于2018-10-10。',name:"YEARDELTA",type:"DATETIME"}]};function Mt(){return new Promise(function(e){e(Bt)})}function Lt(e){return(Lt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function Ut(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"",orderValue:arguments.length>2?arguments[2]:void 0})}(n.model.selectedConnection,n.model.search,n.model.orderValue).then(function(e){n.model.tables=e||[]}):n.model.tables=[]},setSearch:function(e,t){this.model.search=e,this.model.orderValue=t},setSelectedConnection:function(e){this.model.selectedConnection=e}}),n}var n,r,o;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&Vt(e,t)}(t,v),n=t,(r=[{key:"state",value:function(){return{connections:[],tables:[],search:"",orderValue:"",selectedConnection:""}}}])&&Ut(n.prototype,r),o&&Ut(n,o),t}(),kt(Ct,"xtype","dec.model.dcm.connection.plugin.redis.table_list"),Nt=jt))||Nt;function qt(e){return(qt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function Kt(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:BI.RegularFormulaInserter.xtype;return new Promise(function(n,r){var o,i=BI.UUID();BI.Popovers.create(i,{type:_,width:900,height:600,header:BI.i18nText("Plugin-JSON_Function_Definition"),body:{type:BI.FormulaOpeartingPanel.xtype,configLoader:Mt,ref:function(e){o=e},inserterType:t,value:e},listeners:[{eventName:BI.Popover.EVENT_CANCEL,action:function(){r(),BI.Popovers.remove(i)}},{eventName:BI.Popover.EVENT_CONFIRM,action:function(){n(o.getValue()),BI.Popovers.remove(i)}}]}).open(i)})}({formula:0===this.model.inputValue?"":this.model.inputValue},BI.ComplexFormulaInserter.xtype).then(function(e){t.store.setInpueValue(e.formula),t.formulaPane.setValue(e.formula)})}},{key:"getValue",value:function(){return"int"===this.model.inputType?parseInt("".concat(this.model.inputValue),10):this.model.inputValue}}])&&on(n.prototype,r),o&&on(n,o),t}(),sn(en,"xtype","plugin.report.redis.components.database_index"),Zt=tn))||Zt)||Zt;function dn(e){return(dn="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function mn(e,t){for(var n=0;n0?n.model.connections[0]:"";n.connectionTextValue.setValue(e),n.store.setSelectedConnection(e)},"selectedConnection || search || orderValue":function(){n.store.initTableList()},tables:function(e){n.buttonGroup.populate(n.renderTableList())}}),n}var n,r,o;return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&gn(e,t)}(t,BI.Widget),n=t,(r=[{key:"render",value:function(){var e=this,t=(this.options.value.datasetData||{}).orderValue,n=void 0===t?0:t,r="string"==typeof n?"formula":"int";return{type:"bi.vtape",hgap:10,bgap:5,items:[{el:{type:"bi.htape",items:[{type:"bi.text_value_combo",ref:function(t){e.connectionTextValue=t},items:[],listeners:[{eventName:BI.TextValueCombo.EVENT_CHANGE,action:function(){var t=e.connectionTextValue.getValue()[0];e.store.setSelectedConnection(t)}}]},{el:{type:"bi.icon_button",cls:"redis-site-font",title:BI.i18nText("Plugin-Redis_Data_Connection"),handler:function(){window.location.href="".concat(Tt,"#management/connection")}},width:25},{el:{type:"bi.icon_button",cls:"redis-refresh-font",title:BI.i18nText("Plugin-Redis_Refresh"),handler:function(){e.store.initData()}},width:25}]},height:25},{el:{type:"bi.htape",items:[{el:{type:T,text:BI.i18nText("Plugin-Redis_Index"),textAlign:"left"},width:24},{type:yn.xtype,value:n,inputType:r,ref:function(t){e.databaseIndex=t},width:24,height:22},{type:"bi.text_editor",height:24,watermark:BI.i18nText("Plugin-Redis_Keys_Pattern"),ref:function(t){e.searchText=t}},{el:{type:"bi.button",minWidth:50,text:BI.i18nText("Plugin-Redis_Keys_Pattern_Search"),handler:function(){e.store.setSearch(e.searchText.getValue(),e.databaseIndex.getValue())}},width:50}]},height:25},{type:"bi.vtape",items:[{type:"bi.button_group",chooseType:BI.Selection.None,layouts:[{type:"bi.vertical"}],items:[],ref:function(t){e.buttonGroup=t}}]}]}}},{key:"renderConnectionList",value:function(){return this.model.connections.map(function(e){return{text:e,value:e}})}},{key:"renderTableList",value:function(){return this.model.tables.map(function(e){return{type:ht.xtype,text:e,value:e}})}},{key:"mounted",value:function(){this.store.initData()}},{key:"getSelectedDatabase",value:function(){return this.model.selectedConnection}}])&&mn(n.prototype,r),o&&mn(n,o),t}(),vn(fn,"xtype","dec.dcm.connection.plugin.redis.table_list"),ln=pn))||ln)||ln,xn=(n(8),[{text:BI.i18nText("Plugin-Redis_Set_Parameter_Name")},{text:BI.i18nText("Plugin-Redis_Set_Parameter_Type")},{text:BI.i18nText("Plugin-Redis_Set_Parameter_Value")}]),An=[{text:BI.i18nText("Dec-Basic_String"),value:DecCst.Schedule.Parameter.Type.STRING,iconCls:"string-field-font"},{text:BI.i18nText("Dec-Basic_Integer"),value:DecCst.Schedule.Parameter.Type.INTEGER,iconCls:"number-field-font"},{text:BI.i18nText("Dec-Basic_Double"),value:DecCst.Schedule.Parameter.Type.DOUBLE,iconCls:"number-field-font"},{text:BI.i18nText("Dec-Basic_Date"),value:DecCst.Schedule.Parameter.Type.DATE,iconCls:"date-field-font"},{text:BI.i18nText("Dec-Basic_Boolean"),value:DecCst.Schedule.Parameter.Type.BOOLEAN,iconCls:"string-field-font"},{text:BI.i18nText("Dec-Basic_Formula"),value:DecCst.Schedule.Parameter.Type.FORMULA,iconCls:"string-field-font"}];function wn(e){return(wn="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function Pn(e,t){for(var n=0;n @@ -27,7 +27,6 @@
- - + diff --git a/src/web/package.json b/src/web/package.json index 439f620..e0512a3 100644 --- a/src/web/package.json +++ b/src/web/package.json @@ -7,9 +7,11 @@ "author": "alan", "license": "MIT", "dependencies": { + "@fui/materials": "^10.0.0", "@types/jss": "9.5.8", "autoprefixer": "^9.6.1", "es6-promise": "4.2.6", + "fineui": "^2.0.20200628140334", "fork-ts-checker-webpack-plugin": "^1.5.1", "jss": "9.8.7", "jss-plugin-global": "10.0.0-alpha.7", @@ -58,10 +60,6 @@ "webpack-dev-server": "3.7.2", "webpack-merge": "4.2.1" }, - "optionalDependencies": { - "fineui": "git+ssh://git@cloud.finedevelop.com:7999/visual/fineui.git", - "fineui-materials": "git+ssh://git@cloud.finedevelop.com:7999/fui/fineui-materials.git#release/10.0" - }, "scripts": { "dev": "cross-env NODE_ENV=mock webpack-dev-server -p --progress --config=webpack/webpack.dev.js --mode development --open", "build": "webpack -p --progress --config=webpack/webpack.prod.js --mode production", diff --git a/src/web/private/i18n.ts b/src/web/private/i18n.ts index f29deca..c47cf86 100644 --- a/src/web/private/i18n.ts +++ b/src/web/private/i18n.ts @@ -9,7 +9,12 @@ export const i18n = { 'Plugin-Redis_Help': '帮助文档', 'Plugin-Redis_Keys_Pattern': '键值的正则表达式', 'Plugin-Redis_Keys_Pattern_Search': '搜索', + 'Plugin-Redis_Set_Parameter': '参数', + 'Plugin-Redis_Set_Parameter_Name': '参数名', + 'Plugin-Redis_Set_Parameter_Type': '参数类型', + 'Plugin-Redis_Set_Parameter_Value': '参数值', 'Plugin-Redis_DB_Index': '数据库编号', + 'Plugin-Redis_Index': '编号', 'Plugin-Redis_Preview': '预览', 'Plugin-Redis_Refresh': '刷新', 'Plugin-Redis_Formula': '公式', @@ -44,9 +49,193 @@ export const i18n = { 'Plugin-Redis_Check_Integer': '请输入不小于0的整数', 'Plugin-Redis_View': '视图', 'Plugin-Redis_Table': '表', - 'Plugin-Redis_Data_Connection': '数据连接', - 'Plugin-Redis_Set_Parameter': '参数设置', - 'Plugin-Redis_Set_Parameter_Name': '参数名', - 'Plugin-Redis_Set_Parameter_Type': '参数类型', - 'Plugin-Redis_Set_Parameter_Value': '默认值', + 'BI-Multi_Date_Quarter_End': '季度末', + 'BI-Multi_Date_Month_Begin': '月初', + 'BI-Multi_Date_YMD': '年月日', + 'BI-Custom_Color': '自定义颜色', + 'BI-Numerical_Interval_Input_Data': '请输入数值', + 'BI-Please_Input_Natural_Number': '请输入非负整数', + 'BI-No_More_Data': '无更多数据', + 'BI-Basic_Altogether': '共', + 'BI-Basic_Sunday': '星期日', + 'BI-Widget_Background_Colour': '组件背景', + 'BI-Color_Picker_Error_Text': '请输入0~255的正整数', + 'BI-Multi_Date_Month': '月', + 'BI-No_Selected_Item': '没有可选项', + 'BI-Multi_Date_Year_Begin': '年初', + 'BI-Quarter_1': '第1季度', + 'BI-Quarter_2': '第2季度', + 'BI-Quarter_3': '第3季度', + 'BI-Quarter_4': '第4季度', + 'BI-Multi_Date_Year_Next': '年后', + 'BI-Multi_Date_Month_Prev': '个月前', + 'BI-Month_Trigger_Error_Text': '请输入1~12的正整数', + 'BI-Less_And_Equal': '小于等于', + 'BI-Year_Trigger_Invalid_Text': '请输入有效时间', + 'BI-Multi_Date_Week_Next': '周后', + 'BI-Font_Size': '字号', + 'BI-Basic_Total': '共', + 'BI-Already_Selected': '已选择', + 'BI-Formula_Insert': '插入', + 'BI-Select_All': '全选', + 'BI-Basic_Tuesday': '星期二', + 'BI-Multi_Date_Month_End': '月末', + 'BI-Load_More': '点击加载更多数据', + 'BI-Basic_September': '九月', + 'BI-Current_Is_Last_Page': '当前已是最后一页', + 'BI-Basic_Auto': '自动', + 'BI-Basic_Count': '个', + 'BI-Basic_Value': '值', + 'BI-Basic_Unrestricted': '无限制', + 'BI-Quarter_Trigger_Error_Text': '请输入1~4的正整数', + 'BI-Basic_More': '更多', + 'BI-Basic_Wednesday': '星期三', + 'BI-Basic_Bold': '加粗', + 'BI-Basic_Simple_Saturday': '六', + 'BI-Multi_Date_Month_Next': '个月后', + 'BI-Basic_March': '三月', + 'BI-Current_Is_First_Page': '当前已是第一页', + 'BI-Basic_Thursday': '星期四', + 'BI-Basic_Prompt': '提示', + 'BI-Multi_Date_Today': '今天', + 'BI-Multi_Date_Quarter_Prev': '个季度前', + 'BI-Row_Header': '行表头', + 'BI-Date_Trigger_Error_Text': '日期格式示例:2015-3-11', + 'BI-Basic_Cancel': '取消', + 'BI-Basic_January': '一月', + 'BI-Basic_June': '六月', + 'BI-Basic_July': '七月', + 'BI-Basic_April': '四月', + 'BI-Multi_Date_Quarter_Begin': '季度初', + 'BI-Multi_Date_Week': '周', + 'BI-Click_Blank_To_Select': '点击\\空格键\\选中完全匹配项', + 'BI-Basic_August': '八月', + 'BI-Word_Align_Left': '文字居左', + 'BI-Basic_November': '十一月', + 'BI-Font_Colour': '字体颜色', + 'BI-Multi_Date_Day_Prev': '天前', + 'BI-Select_Part': '部分选择', + 'BI-Multi_Date_Day_Next': '天后', + 'BI-Less_Than': '小于', + 'BI-Basic_February': '二月', + 'BI-Multi_Date_Year': '年', + 'BI-Number_Index': '序号', + 'BI-Multi_Date_Week_Prev': '周前', + 'BI-Next_Page': '下一页', + 'BI-Right_Page': '向右翻页', + 'BI-Numerical_Interval_Signal_Value': '前后值相等,请将操作符改为“≤”', + 'BI-Basic_December': '十二月', + 'BI-Basic_Saturday': '星期六', + 'BI-Basic_Simple_Wednesday': '三', + 'BI-Multi_Date_Quarter_Next': '个季度后', + 'BI-Basic_October': '十月', + 'BI-Basic_Simple_Friday': '五', + 'BI-Basic_Save': '保存', + 'BI-Numerical_Interval_Number_Value': '请保证前面的数值小于/等于后面的数值', + 'BI-Previous_Page': '上一页', + 'BI-No_Select': '搜索结果为空', + 'BI-Basic_Clears': '清空', + 'BI-Created_By_Me': '我创建的', + 'BI-Basic_Simple_Tuesday': '二', + 'BI-Word_Align_Right': '文字居右', + 'BI-Summary_Values': '汇总', + 'BI-Basic_Clear': '清除', + 'BI-Upload_File_Size_Error': '文件大小不支持', + 'BI-Up_Page': '向上翻页', + 'BI-Basic_Simple_Sunday': '日', + 'BI-Multi_Date_Relative_Current_Time': '相对当前时间', + 'BI-Selected_Data': '已选数据:', + 'BI-Multi_Date_Quarter': '季度', + 'BI-Check_Selected': '查看已选', + 'BI-Basic_Search': '搜索', + 'BI-Basic_May': '五月', + 'BI-Continue_Select': '继续选择', + 'BI-Please_Input_Positive_Integer': '请输入正整数', + 'BI-Upload_File_Type_Error': '文件类型不支持', + 'BI-Upload_File_Error': '文件上传失败', + 'BI-Basic_Friday': '星期五', + 'BI-Down_Page': '向下翻页', + 'BI-Basic_Monday': '星期一', + 'BI-Left_Page': '向左翻页', + 'BI-Transparent_Color': '透明', + 'BI-Basic_Simple_Monday': '一', + 'BI-Multi_Date_Year_End': '年末', + 'BI-Time_Interval_Error_Text': '请保证开始时间早于/等于结束时间', + 'BI-Basic_Time': '时间', + 'BI-Basic_OK': '确定', + 'BI-Basic_Sure': '确定', + 'BI-Basic_Simple_Thursday': '四', + 'BI-Multi_Date_Year_Prev': '年前', + 'BI-Tiao_Data': '条数据', + 'BI-Basic_Italic': '斜体', + 'BI-Basic_Dynamic_Title': '动态时间', + 'BI-Basic_Year': '年', + 'BI-Basic_Single_Quarter': '季', + 'BI-Basic_Month': '月', + 'BI-Basic_Week': '周', + 'BI-Basic_Day': '天', + 'BI-Basic_Work_Day': '工作日', + 'BI-Basic_Front': '前', + 'BI-Basic_Behind': '后', + 'BI-Basic_Empty': '空', + 'BI-Basic_Month_End': '月末', + 'BI-Basic_Month_Begin': '月初', + 'BI-Basic_Year_End': '年末', + 'BI-Basic_Year_Begin': '年初', + 'BI-Basic_Quarter_End': '季末', + 'BI-Basic_Quarter_Begin': '季初', + 'BI-Basic_Week_End': '周末', + 'BI-Basic_Week_Begin': '周初', + 'BI-Basic_Current_Day': '当天', + 'BI-Basic_Begin_Start': '初', + 'BI-Basic_End_Stop': '末', + 'BI-Basic_Current_Year': '今年', + 'BI-Basic_Year_Fen': '年份', + 'BI-Basic_Current_Month': '本月', + 'BI-Basic_Current_Quarter': '本季度', + 'BI-Basic_Year_Month': '年月', + 'BI-Basic_Year_Quarter': '年季度', + 'BI-Basic_Input_Can_Not_Null': '输入框不能为空', + 'BI-Basic_Date_Time_Error_Text': '日期格式示例:2015-3-11 00:00:00', + 'BI-Basic_Input_From_To_Number': '请输入{R1}的数值', + 'BI-Basic_Or': '或', + 'BI-Basic_And': '且', + 'BI-Conf_Add_Formula': '添加公式', + 'BI-Conf_Add_Condition': '添加条件', + 'BI-Conf_Formula_And': '且公式条件', + 'BI-Conf_Formula_Or': '或公式条件', + 'BI-Conf_Condition_And': '且条件', + 'BI-Conf_Condition_Or': '或条件', + 'BI-Microsoft_YaHei': '微软雅黑', + 'BI-Apple_Light': '苹方-light', + 'BI-Font_Family': '字体', + 'BI-Basic_Please_Input_Content': '请输入内容', + 'BI-Word_Align_Center': '文字居中', + 'BI-Basic_Please_Enter_Number_Between': '请输入{R1}-{R2}的值', + 'BI-More_Than': '大于', + 'BI-More_And_Equal': '大于等于', + 'BI-Please_Enter_SQL': '请输入SQL', + 'BI-Basic_Click_To_Add_Text': '+点击新增\\{R1}\\', + 'BI-Basic_Please_Select': '请选择', + 'BI-Basic_Font_Color': '文字颜色', + 'BI-Basic_Background_Color': '背景色', + 'BI-Basic_Underline': '下划线', + 'BI-Basic_Param_Month': '{R1}月', + 'BI-Basic_Param_Day': '{R1}日', + 'BI-Basic_Param_Quarter': '{R1}季度', + 'BI-Basic_Param_Week_Count': '第{R1}周', + 'BI-Basic_Param_Hour': '{R1}时', + 'BI-Basic_Param_Minute': '{R1}分', + 'BI-Basic_Param_Second': '{R1}秒', + 'BI-Basic_Param_Year': '{R1}年', + 'BI-Basic_Date_Day': '日', + 'BI-Basic_Hour_Sin': '时', + 'BI-Basic_Seconds': '秒', + 'BI-Basic_Minute': '分', + 'BI-Basic_Wan': '万', + 'BI-Basic_Million': '百万', + 'BI-Basic_Billion': '亿', + 'BI-Basic_Quarter': '季度', + 'BI-Basic_No_Select': '不选', + 'BI-Basic_Now': '此刻', }; diff --git a/src/web/src/index.edit.ts b/src/web/src/index.edit.ts index 0f8a090..a57adf0 100644 --- a/src/web/src/index.edit.ts +++ b/src/web/src/index.edit.ts @@ -1,6 +1,6 @@ -import { RedisEdit } from './modules/app.edit'; +import { TableList } from './modules/table_list/table_list'; BI.createWidget({ - type: RedisEdit.xtype, + type: TableList.xtype, element: '#wrapper', }); diff --git a/src/web/src/modules/crud/crud.request.ts b/src/web/src/modules/crud/crud.request.ts index cfa4471..6860d2a 100644 --- a/src/web/src/modules/crud/crud.request.ts +++ b/src/web/src/modules/crud/crud.request.ts @@ -4,10 +4,11 @@ export function getConnectionlist(): Promise<{data?: Connection[]}> { return requestGet('/v10/config/connection/list'); } -export function getTableList(database: string, pattern = ''): Promise { +export function getTableList(database: string, pattern = '', orderValue: string | number): Promise { return requestGet('plugin/private/com.fr.solution.plugin.db.redis.v10/redis/keys', { database, pattern, + orderValue, }); } diff --git a/src/web/src/modules/table_list/table_list.model.ts b/src/web/src/modules/table_list/table_list.model.ts index d69a462..963d360 100644 --- a/src/web/src/modules/table_list/table_list.model.ts +++ b/src/web/src/modules/table_list/table_list.model.ts @@ -9,6 +9,7 @@ export class TableModelModel extends Model { connections: [] as string[], tables: [] as string[], search: '', + orderValue: '', selectedConnection: '', }; } @@ -21,15 +22,16 @@ export class TableModelModel extends Model { }, initTableList: () => { if (this.model.selectedConnection) { - getTableList(this.model.selectedConnection, this.model.search).then(re => { + getTableList(this.model.selectedConnection, this.model.search, this.model.orderValue).then(re => { this.model.tables = re ? re : []; }); } else { this.model.tables = []; } }, - setSearch(value: string) { + setSearch(value: string, orderValue: string | number) { this.model.search = value; + this.model.orderValue = orderValue; }, setSelectedConnection(name: string) { this.model.selectedConnection = name; diff --git a/src/web/src/modules/table_list/table_list.ts b/src/web/src/modules/table_list/table_list.ts index af4b383..5d8bcc0 100644 --- a/src/web/src/modules/table_list/table_list.ts +++ b/src/web/src/modules/table_list/table_list.ts @@ -1,8 +1,9 @@ import { shortcut, store } from '@core/core'; -import { VtapeXtype, HtapeXtype, IconButtonXtype, TextValueComboXtype, ButtonXtype, TextEditorXtype, ButtonGroupXtype, VerticalXtype } from 'ui'; +import { VtapeXtype, HtapeXtype, LabelXtype, IconButtonXtype, TextValueComboXtype, ButtonXtype, TextEditorXtype, ButtonGroupXtype, VerticalXtype } from 'ui'; import { ListItem } from './list_item'; import { TableModelModel } from './table_list.model'; import { fineServletURL } from '@constants/env'; +import { DatabaseIndex } from '../components/database_index/database_index'; @shortcut() @store(TableModelModel) @@ -12,12 +13,18 @@ export class TableList extends BI.Widget { store: TableModelModel['store'] model: TableModelModel['model'] + databaseIndex: DatabaseIndex; buttonGroup: any; connectionTextValue: any; searchText: any; props = { database: '', + value: { + datasetData: { + orderValue: 0, + }, + }, } watch = { @@ -27,7 +34,7 @@ export class TableList extends BI.Widget { this.connectionTextValue.setValue(name); this.store.setSelectedConnection(name); }, - 'selectedConnection || search': () => { + 'selectedConnection || search || orderValue': () => { this.store.initTableList(); }, tables: (tables: string[]) => { @@ -36,6 +43,9 @@ export class TableList extends BI.Widget { } render() { + const { orderValue = 0 } = this.options.value.datasetData || {}; + const inputType = typeof orderValue === 'string' ? 'formula' : 'int'; + return { type: VtapeXtype, hgap: 10, @@ -83,6 +93,22 @@ export class TableList extends BI.Widget { el: { type: HtapeXtype, items: [{ + el: { + type: LabelXtype, + text: BI.i18nText('Plugin-Redis_Index'), + textAlign: 'left', + }, + width: 24, + }, { + type: DatabaseIndex.xtype, + value: orderValue, + inputType, + ref: (_ref: any) => { + this.databaseIndex = _ref; + }, + width: 24, + height: 22, + }, { type: TextEditorXtype, height: 24, watermark: BI.i18nText('Plugin-Redis_Keys_Pattern'), @@ -95,7 +121,7 @@ export class TableList extends BI.Widget { minWidth: 50, text: BI.i18nText('Plugin-Redis_Keys_Pattern_Search'), handler: () => { - this.store.setSearch(this.searchText.getValue()); + this.store.setSearch(this.searchText.getValue(), this.databaseIndex.getValue()); }, }, width: 50, diff --git a/src/web/yarn.lock b/src/web/yarn.lock index e5fdcbf..7c3f2c3 100644 --- a/src/web/yarn.lock +++ b/src/web/yarn.lock @@ -723,10 +723,18 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@jest/console@^24.7.1", "@jest/console@^24.9.0": - version "24.9.0" - resolved "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" - integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ== +"@fui/materials@^10.0.0": + version "10.0.0" + resolved "https://npm.fineres.com/@fui%2fmaterials/-/materials-10.0.0.tgz#816187a3c287f59e4f7e404f3b9f7f041aa424a4" + integrity sha512-yQvAR8yfnnnFPu9UEdlfx15bO/GVtrppOvbp/kJPPFW+MnW8fQ60WYAnIPjzLLu0LxNRsucvsKDAiYAUFWVwIA== + dependencies: + "@types/codemirror" "0.0.77" + codemirror "5.42.2" + +"@jest/console@^24.7.1": + version "24.7.1" + resolved "https://registry.npmjs.org/@jest/console/-/console-24.7.1.tgz#32a9e42535a97aedfe037e725bd67e954b459545" + integrity sha512-iNhtIy2M8bXlAOULWVTUxmnelTLFneTNEkHCgPmgd+zNwy9zVddJ6oS5rZ9iwoscNdT5mMwUd0C51v/fSlzItg== dependencies: "@jest/source-map" "^24.9.0" chalk "^2.0.1" @@ -906,15 +914,15 @@ "@types/codemirror@0.0.77": version "0.0.77" - resolved "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.77.tgz#6785a0183b4aea147de650530259ebf2a511bde9" - integrity sha512-nfjRJpAXgkT075jztMp92Ol2b7w7JrDvpfBU70GfVhpfdpWiZi6NqVIO3STGNzWl77/iJkTu2ZSg6hQobrEadg== + resolved "https://registry.npm.taobao.org/@types/codemirror/download/@types/codemirror-0.0.77.tgz#6785a0183b4aea147de650530259ebf2a511bde9" + integrity sha1-Z4WgGDtK6hR95lBTAlnr8qURvek= dependencies: "@types/tern" "*" "@types/estree@*": - version "0.0.39" - resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" - integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + version "0.0.45" + resolved "https://registry.npm.taobao.org/@types/estree/download/@types/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884" + integrity sha1-6Th1cpmOXs2sIhlQ2rPow7Fq+IQ= "@types/events@*": version "3.0.0" @@ -992,22 +1000,15 @@ "@types/tern@*": version "0.23.3" - resolved "https://registry.npmjs.org/@types/tern/-/tern-0.23.3.tgz#4b54538f04a88c9ff79de1f6f94f575a7f339460" - integrity sha512-imDtS4TAoTcXk0g7u4kkWqedB3E4qpjXzCpD2LU5M5NAXHzCDsypyvXSaG7mM8DKYkCRa7tFp4tS/lp/Wo7Q3w== + resolved "https://registry.npm.taobao.org/@types/tern/download/@types/tern-0.23.3.tgz#4b54538f04a88c9ff79de1f6f94f575a7f339460" + integrity sha1-S1RTjwSojJ/3neH2+U9XWn8zlGA= dependencies: "@types/estree" "*" -"@types/yargs-parser@*": - version "13.1.0" - resolved "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-13.1.0.tgz#c563aa192f39350a1d18da36c5a8da382bbd8228" - integrity sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg== - -"@types/yargs@^13.0.0": - version "13.0.3" - resolved "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.3.tgz#76482af3981d4412d65371a318f992d33464a380" - integrity sha512-K8/LfZq2duW33XW/tFwEAfnZlqIfVsoyRB3kfXdPXYhl0nfM8mmh7GS0jg7WrX2Dgq/0Ha/pR1PaR+BvmWwjiQ== - dependencies: - "@types/yargs-parser" "*" +"@types/yargs@^12.0.2", "@types/yargs@^12.0.9": + version "12.0.12" + resolved "https://registry.npmjs.org/@types/yargs/-/yargs-12.0.12.tgz#45dd1d0638e8c8f153e87d296907659296873916" + integrity sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw== "@typescript-eslint/eslint-plugin@1.7.0": version "1.7.0" @@ -2088,10 +2089,10 @@ code-point-at@^1.0.0: resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -codemirror@5.49.0: - version "5.49.0" - resolved "https://registry.npmjs.org/codemirror/-/codemirror-5.49.0.tgz#adedbffcc81091e4a0334bcb96b1ae3b7ada5e3f" - integrity sha512-Hyzr0HToBdZpLBN9dYFO/KlJAsKH37/cXVHPAqa+imml0R92tb9AkmsvjnXL+SluEvjjdfkDgRjc65NG5jnMYA== +codemirror@5.42.2: + version "5.42.2" + resolved "https://registry.npm.taobao.org/codemirror/download/codemirror-5.42.2.tgz?cache=0&sync_timestamp=1592745428423&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcodemirror%2Fdownload%2Fcodemirror-5.42.2.tgz#801ab715a7a7e1c7ed4162b78e9d8138b98de8f0" + integrity sha1-gBq3Faen4cftQWK3jp2BOLmN6PA= collection-visit@^1.0.0: version "1.0.0" @@ -3432,16 +3433,10 @@ findup-sync@3.0.0: micromatch "^3.0.4" resolve-dir "^1.0.1" -"fineui-materials@git+ssh://git@cloud.finedevelop.com:7999/fui/fineui-materials.git#release/10.0": - version "1.0.0" - resolved "git+ssh://git@cloud.finedevelop.com:7999/fui/fineui-materials.git#df3fd3821680cd28edbc5e03b6182d8d7021fc45" - dependencies: - "@types/codemirror" "0.0.77" - codemirror "5.49.0" - -"fineui@git+ssh://git@cloud.finedevelop.com:7999/visual/fineui.git": - version "1.1.2" - resolved "git+ssh://git@cloud.finedevelop.com:7999/visual/fineui.git#9463c7fbf77e9636945a4b08eff8c30cf8664425" +fineui@^2.0.20200628140334: + version "2.0.20200628140334" + resolved "https://registry.npm.taobao.org/fineui/download/fineui-2.0.20200628140334.tgz#9280889789402c8f731792279eeb6e43d95e6bdb" + integrity sha1-koCIl4lALI9zF5InnutuQ9lea9s= flat-cache@^2.0.1: version "2.0.1"