图形端数据函数

应用场景 #

在图形开发中,我们可能需要使用 JS 对传递过来的数据进行处理。
所有函数均可直接在图形的 JS 代码区中调用。

数据约定:本文所有示例均以如下标准二维数组为基础,第一行为表头,后续行为数据行:

dataset = [['category', 'C1', 'C2'],
           ['R1',        12,   18],
           ['R2',        10,   17]]

数据集转化 #

ds_transform(dataset) #

行列转置:将二维数组的行与列互换,等同于矩阵转置。常用于坐标轴翻转展示。

result = ds_transform(dataset)
// 结果:
// [['category', 'R1', 'R2'],
//  ['C1',        12,   10],
//  ['C2',        18,   17]]

ds_createMap(dataset) #

生成 key → [] 字典:将二维数组转换为以第一列值为 key、其余列组成数组为 value 的字典对象。常用于 ECharts 中按名称取系列数据。

result = ds_createMap(dataset)
// 结果:
// {
//   "category": ["C1", "C2"],
//   "R1": [12, 18],
//   "R2": [10, 17]
// }

// 典型用法:取某一行的数值
let r1Data = result['R1']  // [12, 18]

ds_createMap_all(dataset) #

生成对象数组:将二维数组转换为 [{列名1: 值, 列名2: 值, ...}, ...] 格式的对象数组(跳过第一行表头)。常用于饼图 data、ECharts dataset source,以及需要按字段名取值的场景。

result = ds_createMap_all(dataset)
// 结果:
// [
//   {"category": "R1", "C1": 12, "C2": 18},
//   {"category": "R2", "C1": 10, "C2": 17}
// ]

// 典型用法:饼图 data
let pieData = ds_createMap_all(dataset).map(item => ({name: item.category, value: item.C1}))

ds_mapToList(dataset) #

对象数组还原为二维数组:将 ds_createMap_all 生成的对象数组还原回标准二维数组格式(表头 + 数据行)。常用于处理 MongoDB、Elasticsearch 等 NoSQL 数据源返回的数据。

let objList = [
  {"category": "R1", "C1": 12, "C2": 18},
  {"category": "R2", "C1": 10, "C2": 17}
]
result = ds_mapToList(objList)
// 结果:
// [['category', 'C1', 'C2'],
//  ['R1',        12,   18],
//  ['R2',        10,   17]]

ds_pivot(dataset, indexs=null, column=null, value=null) #

数据透视(行转列):将"维度 … + 透视列 + 值"格式的明细数据透视为宽表。默认取最后两列作为透视列和值列,其余列作为行索引。

参数 说明 默认值
dataset 原始二维数组(含表头)
indexs 行索引列的序号数组 [0, 1, ..., n-3]
column 透视列的序号 倒数第二列
value 值列的序号 最后一列
// 基本用法:两列(维度 + 值)自动透视
dataset3 = [['城市', '户型', '数量'],
            ['长沙', 'A', 35],
            ['上海', 'B', 19]]

result = ds_pivot(dataset3)
// 结果:
// [["城市", "A", "B"],
//  ["长沙",  35,   0],
//  ["上海",   0,  19]]

// 多维行索引透视
dataset4 = [['省份', '城市', '户型', '数量'],
            ['湖南', '长沙', 'A', 35],
            ['上海', '上海', 'B', 19]]

result = ds_pivot(dataset4)
// 结果:
// [["省份", "城市", "A", "B"],
//  ["湖南", "长沙",  35,   0],
//  ["上海", "上海",   0,  19]]

// 自定义索引列、透视列、值列
result = ds_pivot(dataset4, indexs=[1, 0], column=2, value=3)
// 结果:
// [["城市", "省份", "A", "B"],
//  ["长沙", "湖南",  35,   0],
//  ["上海", "上海",   0,  19]]

ds_tree(dataset, label='label', children='children') #

生成树形结构:将"父节点、子节点"格式的二维数组转换为 ECharts tree/treemap 组件所需的嵌套树结构。支持通过 fatherName/childName 字段将编码与显示名称分离。

// 基础用法(直接用显示名称)
dataset = [["father", "child"],
           ["湖南", "长沙"],
           ["湖南", "郴州"],
           ["郴州", "安仁"],
           ["广东", "佛山"],
           ["广东", "广州"]]

result = ds_tree(dataset)
// 结果(简化):
// [
//   {id:"湖南", label:"湖南", children:[
//     {id:"长沙", label:"长沙"},
//     {id:"郴州", label:"郴州", children:[
//       {id:"安仁", label:"安仁"}
//     ]}
//   ]},
//   {id:"广东", label:"广东", children:[...]}
// ]

// 进阶用法:避免同名歧义,SELECT father, child, fatherName, childName
dataset = [["father", "child", "fatherName", "childName"],
           ["A",  "A1",  "湖南", "长沙"],
           ["A",  "A2",  "湖南", "郴州"],
           ["A2", "A2A", "郴州", "安仁"],
           ["B",  "B1",  "广东", "佛山"],
           ["B",  "B2",  "广东", "广州"]]

result = ds_tree(dataset)
// 节点 id 为编码,label 为显示名称,不会因重名引起混淆

ds_distinct(a, b=[]) #

数组去重:对单个或两个数组合并后去重,返回无重复值的新数组。

// 单数组去重
result = ds_distinct(['A', 'B', 'A', 'C'])
// 结果:['A', 'B', 'C']

// 合并两个数组并去重
result = ds_distinct(['A', 'B'], ['B', 'C', 'D'])
// 结果:['A', 'B', 'C', 'D']

// 典型用法:获取某列的不重复值列表
let categories = ds_distinct(dataset.slice(1).map(row => row[0]))

ds_filter(dataset, fun) #

数据集过滤:使用函数 fun 对数据行进行筛选,自动保留表头行。fun 接收每行数据,返回 true 保留,返回 false 过滤掉。

// 过滤第一列等于 'R1' 的行
result = ds_filter(dataset, item => item[0] === 'R1')
// 结果:
// [['category', 'C1', 'C2'],
//  ['R1',        12,   18]]

// 过滤第二列大于 10 的行
result = ds_filter(dataset, item => item[1] > 10)
// 结果:
// [['category', 'C1', 'C2'],
//  ['R1',        12,   18]]

// 多条件过滤
result = ds_filter(dataset, item => item[1] > 10 && item[2] < 20)

ds_sort(dataset, index=0, asc=true) #

数据集排序:按指定列索引对数据行排序(保留表头),支持升序/降序,也支持传入自定义比较函数。

参数 说明 默认值
index 排序列的序号,或自定义比较函数 0
asc true 升序,false 降序 true
// 按第二列(序号1)升序排序
result = ds_sort(dataset, 1)
// 结果:
// [['category', 'C1', 'C2'],
//  ['R2',        10,   17],
//  ['R1',        12,   18]]

// 按第二列降序排序
result = ds_sort(dataset, 1, false)
// 结果:
// [['category', 'C1', 'C2'],
//  ['R1',        12,   18],
//  ['R2',        10,   17]]

// 使用自定义比较函数(按第三列降序)
result = ds_sort(dataset, (a, b) => b[2] - a[2])

ds_remove_column(dataset, remove_list=[0]) #

移除指定列:删除二维数组中指定序号的列,支持一次移除多列。

// 移除第一列(序号 0,即 category 列)
result = ds_remove_column(dataset, [0])
// 结果:
// [['C1', 'C2'],
//  [ 12,   18],
//  [ 10,   17]]

// 移除第一列和第三列
result = ds_remove_column(dataset, [0, 2])
// 结果:
// [['C1'],
//  [ 12],
//  [ 10]]

ds_split(data, sep=',', head_add=[]) #

拆分第一列:将第一列的字符串按分隔符拆分成多个字段,合并到数据集。如果传入 head_add 则使用指定表头,否则用 SQL 字段名(第一列表头)按分隔符拆分作为新表头。

// SQL 返回数据,第一列是逗号拼接的多字段
data = [['province,city', 'sales'],
        ['湖南,长沙',       100],
        ['广东,广州',       200]]

// 传入自定义表头
result = ds_split(data, ',', ['省份', '城市'])
// 结果:
// [['省份', '城市', 'sales'],
//  ['湖南', '长沙',  100],
//  ['广东', '广州',  200]]

// 不传表头,自动从第一列列名"province,city"拆分
result = ds_split(data, ',')
// 结果:
// [['province', 'city', 'sales'],
//  ['湖南',     '长沙',  100],
//  ['广东',     '广州',  200]]

ds_sumColumn(dataset, column) #

列求和:对指定列(从第 1 行开始,跳过表头)所有数值求和,返回合计值。

// 对第二列(序号 1)求和
total = ds_sumColumn(dataset, 1)
// 结果:22  (12 + 10)

// 对第三列(序号 2)求和
total = ds_sumColumn(dataset, 2)
// 结果:35  (18 + 17)

ds_percentAcc(dataset, row) #

累计占比行:对指定行(按行序号,从 0 开始含表头行)计算累计百分比,并在数据集末尾追加一行。常用于柏拉图(Pareto Chart)。

// 原始数据(先按数量降序排好)
dataset5 = [['品类',  '数量'],
            ['A',     50],
            ['B',     30],
            ['C',     20]]

// 对第 1 行(数量行,序号 1)做累计占比
result = ds_percentAcc(dataset5, 1)
// 结果(在末尾追加累计占比行):
// [['品类',    '数量'],
//  ['A',         50],
//  ['B',         30],
//  ['C',         20],
//  ['数量_acc',  0.5, 0.8, 1.0]]

数据集关联 #

ds_leftjoin(a, b, withhead=true, type=1) #

左关联:按照两个数据集的第一列进行左连接,a 中所有行都保留,b 中无匹配的列填 0

dataset2 = [['category', 'C3'],
            ['R1',        38],
            ['R6',        13]]

result = ds_leftjoin(dataset, dataset2)
// 结果:
// [['category', 'C1', 'C2', 'C3'],
//  ['R1',        12,   18,   38],
//  ['R2',        10,   17,    0]]   // R2 在 b 中无匹配,C3 填 0
// 注意:R6 仅存在于 b 中,左连接不保留

ds_crossjoin(a, b, withhead=true) #

交叉关联(内连接):只保留两个数据集第一列匹配的行,等同于 SQL 的 INNER JOIN

result = ds_crossjoin(dataset, dataset2)
// 结果:
// [['category', 'C1', 'C2', 'C3'],
//  ['R1',        12,   18,   38]]   // 仅 R1 匹配

ds_fulljoin(a, b, withhead=true) #

全外连接:保留两个数据集中所有行,无匹配处补 0,等同于 SQL 的 FULL OUTER JOIN

result = ds_fulljoin(dataset, dataset2)
// 结果:
// [['category', 'C1', 'C2', 'C3'],
//  ['R1',        12,   18,   38],
//  ['R2',        10,   17,    0],   // b 中无 R2,C3 补 0
//  ['R6',         0,    0,   13]]   // a 中无 R6,C1/C2 补 0

ds_union(a, b, withhead=true) #

纵向合并(UNION ALL):将两个数据集纵向拼接,取第一个数据集的表头,去掉第二个数据集的表头行。

dataset_extra = [['category', 'C1', 'C2'],
                 ['R3',        5,   9]]

result = ds_union(dataset, dataset_extra)
// 结果:
// [['category', 'C1', 'C2'],
//  ['R1',        12,   18],
//  ['R2',        10,   17],
//  ['R3',         5,    9]]

数据集刷新 #

ds_param(name) #

获取传入参数:在图形点击联动或 URL 参数传递后,通过参数名获取全局参数字典 filter_param 中对应的值。

// 假设点击图形后传入了 city='长沙'
let city = ds_param('city')
// 结果:'长沙'

// 在 SQL 中使用参数过滤(需配合后端参数语法)
// WHERE city = '${city}'

ds_setParam('参数名', 参数值) #

设定全局参数:向全局参数字典 filter_param 写入参数,用于控制其他图形刷新时的过滤条件。当参数值为空/null/undefined 时,自动删除该参数,恢复到未传参的初始状态。

// 设置参数
ds_setParam('city', '长沙')
// filter_param 变为:{city: '长沙'}

// 清除参数(传空值)
ds_setParam('city', '')
// filter_param 变为:{}

// 典型联动场景:点击图形时传参并刷新其他图形
myChart.on('click', function(params) {
    ds_setParam('city', params.name)
    ds_refresh(2)   // 刷新序号为 2 的图形
    ds_refresh(3)   // 刷新序号为 3 的图形
})

ds_refresh(序号, param=filter_param, r=null) #

刷新图形/获取数据:触发指定序号的图形重新请求数据并渲染。可以传入自定义参数,也可以指定返回值格式用于获取数据。

参数 说明 默认值
序号 图形序号(对应后台配置的 id)
param 参数字典,默认使用全局参数 filter_param
r null 同步刷新渲染;0 触发异步刷新但不等待;'list' 同步返回二维数组;'map' 同步返回对象数组 null
// 使用全局参数刷新序号为 2 的图形
ds_refresh(2)

// 使用指定参数刷新
ds_refresh(2, {city: '长沙', year: '2024'})

// 同步获取数据(返回二维数组格式)
let data = ds_refresh(2, filter_param, 'list')
// data = [['city','sales'],['长沙',100],['广州',200]]

// 同步获取数据(返回对象数组格式)
let data = ds_refresh(2, filter_param, 'map')
// data = [{city:'长沙', sales:100}, {city:'广州', sales:200}]

// 触发异步刷新,不等待返回值
ds_refresh(2, filter_param, 0)

数据处理 #

ds_rowname(dataset, start_row=1, column=0) #

获取指定列数据:从指定起始行开始,提取指定列的所有值,返回一维数组。常用于获取图形的维度列表(X 轴分类)。

// 获取第一列(序号 0)从第 1 行起的所有值(默认)
result = ds_rowname(dataset)
// 结果:['R1', 'R2']

// 获取第二列(序号 1)从第 1 行起的数据
result = ds_rowname(dataset, 1, 1)
// 结果:[12, 10]

// 从第 2 行开始(跳过第 1 行)
result = ds_rowname(dataset, 2, 0)
// 结果:['R2']

ds_toThousands(num) #

数字转千分位格式:将数字转换为逗号分隔的千分位字符串,支持负数和小数。

ds_toThousands(1234567)
// 结果:'1,234,567'

ds_toThousands(1234567.89)
// 结果:'1,234,567.89'

ds_toThousands(-9876543)
// 结果:'-9,876,543'

// 典型用法:ECharts tooltip/label 格式化
formatter: function(params) {
    return ds_toThousands(params.value)
}

ds_round(num, qty=2) #

小数位格式化:对数字保留指定位数的小数,默认保留两位,返回字符串。

ds_round(3.14159)
// 结果:'3.14'

ds_round(3.14159, 4)
// 结果:'3.1416'

ds_round(100, 0)
// 结果:'100'

// 典型用法:百分比显示
let pct = ds_round(0.3567 * 100, 1) + '%'
// 结果:'35.7%'

ds_generateLastDay(n=15, joinChat='-') #

生成近 N 天日期数组:生成最近 N 天的日期列表(含表头行 ['zymd']),可用于与其他数据集 join 补全缺失日期。

// 生成最近 5 天
result = ds_generateLastDay(5)
// 结果(假设今天是 2024-01-15):
// [['zymd'],
//  ['2024-01-11'],
//  ['2024-01-12'],
//  ['2024-01-13'],
//  ['2024-01-14'],
//  ['2024-01-15']]

// 使用斜杠分隔
result = ds_generateLastDay(3, '/')
// 结果:
// [['zymd'],
//  ['2024/01/13'],
//  ['2024/01/14'],
//  ['2024/01/15']]

// 典型用法:与销售数据 fulljoin,补全没有数据的日期
result = ds_fulljoin(ds_generateLastDay(15), salesDataset)

ds_generateUUID() #

生成 UUID:生成一个随机的 UUID v4 字符串,可用于唯一标识数据行或前端组件 id。

let id = ds_generateUUID()
// 结果示例:'550e8400-e29b-41d4-a716-446655440000'

// 典型用法:为新增数据行生成唯一 id
let newRow = {id: ds_generateUUID(), name: '新数据', value: 100}

new Date().format('yyyy-MM-dd hh:mm:ss') #

日期格式化:Date 原型扩展方法,将日期对象按指定格式转换为字符串。

占位符 含义
yyyy 四位年份
MM 两位月份
dd 两位日期
hh 两位小时(24h)
mm 两位分钟
ss 两位秒
q 季度
S 毫秒
new Date().format('yyyy-MM-dd')
// 结果示例:'2024-01-15'

new Date().format('yyyy-MM-dd hh:mm:ss')
// 结果示例:'2024-01-15 09:30:00'

new Date().format('yyyy年MM月dd日')
// 结果示例:'2024年01月15日'

// 典型用法:作为默认参数值
ds_setParam('start_date', new Date().format('yyyy-MM-dd'))

组件渲染 #

ds_formatArray(dataset, formatStr) #

格式化数组为字符串:遍历数据集(跳过表头),用每行数据替换格式串中的 $字段名 占位符,多行结果用换行符拼接。

dataset6 = [['name',  'score', 'grade'],
            ['Alice',    95,     'A'],
            ['Bob',      82,     'B']]

result = ds_formatArray(dataset6, '$name 的成绩是 $score 分,等级 $grade')
// 结果:
// 'Alice 的成绩是 95 分,等级 A
// Bob 的成绩是 82 分,等级 B'

// 典型用法:生成 ECharts tooltip 内容或 HTML 字符串
let htmlStr = ds_formatArray(dataset6, '<li>$name:$score ($grade)</li>')
document.getElementById('list').innerHTML = '<ul>' + htmlStr + '</ul>'

ds_vue(eid, dataset, param=null, ds_list=null) #

动态渲染 Vue 组件:异步加载 Vue + ElementUI,并在指定 DOM 元素上创建 Vue 实例,支持联动刷新其他图形。

参数 说明
eid DOM 选择器,如 '#container_1'
dataset 绑定到 ds 的数据(二维数组或对象)
param 绑定到 param 的参数对象
ds_list 调用 refresh() 时要刷新的图形序号数组
// 基础渲染
await ds_vue('#container_1', dataset)

// 带参数联动(点击按钮时刷新序号 2、3 的图形)
let vm = await ds_vue('#container_1', dataset, {city: '长沙'}, [2, 3])
// Vue 模板中可调用 refresh() 触发联动
// <el-button @click="refresh()">刷新</el-button>

ds_chart(dataset, index=999, chartType=null) #

异步动态渲染图形:根据数据集自动判断并渲染 ECharts 图形(饼图或柱状/折线图),支持点击切换图形类型。dataset 也可直接传入 ECharts option 对象或 HTML 字符串。

参数 说明 默认值
dataset 二维数组、ECharts option 对象或 HTML 字符串
index 渲染到哪个容器序号(container_序号 999
chartType 强制指定图形类型:'bar'(柱图)、'pie'(饼图) null(自动)
// 自动判断类型渲染(≤6 行且只有 2 列时用饼图,否则用柱图)
await ds_chart(dataset, 1)

// 强制渲染饼图
await ds_chart(dataset, 1, 'pie')

// 强制渲染柱状图
await ds_chart(dataset, 1, 'bar')

// 直接传入 ECharts option
await ds_chart({
    xAxis: {type: 'category', data: ['R1', 'R2']},
    yAxis: {type: 'value'},
    series: [{type: 'bar', data: [12, 10]}]
}, 1)

// 渲染 HTML 内容
await ds_chart('<div style="color:red">暂无数据</div>', 1)

ds_loadcss(css, id=null) #

动态加载样式:向页面 <head> 中动态注入 CSS,支持内置 CSS 名称(加载 /static/smartchart/opt/ 目录下对应的 .css 文件)、完整 URL 路径,或直接传入 CSS 字符串(配合 id 参数)。重复加载同一样式会自动跳过。

// 加载内置样式(如 swiper 组件样式)
ds_loadcss('smt_swiper')
// 实际加载:/static/smartchart/opt/smt_swiper.css

// 加载外部样式
ds_loadcss('https://cdn.example.com/style.css')

// 直接注入 CSS 字符串(id 用于防重复)
ds_loadcss('.my-box { color: red; font-size: 14px; }', 'my-custom-style')

Excel 数据集 #

ds_excel_refresh(dataset) #

刷新复杂报表:向 LuckySheet 表格中批量写入数据,通过在单元格中预先设置 #df数字.字段名 占位符来指定填充位置。dataset 格式为 {df0: 二维数组, df1: 二维数组, ...}

// dataset 格式
let dataset = {
    df0: [['name',  'sales'],
          ['长沙',    100],
          ['广州',    200]],
    df1: [['total'],
          [300]]
}
// 表格中单元格预设占位符:#df0.name、#df0.sales、#df1.total
// 调用后会自动向对应单元格填入数据
ds_excel_refresh(dataset)

ds_excel_value(fillCells, clear=false) #

获取单元格值:从 LuckySheet 表格中按列行坐标(如 'A1')批量读取单元格的值,返回值数组。常用于数据填报场景。

// 读取 A1、B2、C3 单元格的值
let values = ds_excel_value(['A1', 'B2', 'C3'])
// 结果示例:['张三', 100, '2024-01-15']

// 读取后同时清空这些单元格
let values = ds_excel_value(['A1', 'B2'], true)

// 典型填报场景
let [name, amount, date] = ds_excel_value(['B2', 'C2', 'D2'])
ds_save(1, [[name, amount, date]])

数据上传下载 #

ds_save(序号, contents, update=0, id=null) #

保存/更新数据:将数据写入 SmartChart 的数据集存储。update=0 为新增,update=1 为更新(以第一列为主键匹配更新)。

// 新增一条数据
ds_save(1, [['name', 'sales'], ['长沙', 100]])

// 更新数据(按第一列 name 匹配更新)
ds_save(1, [['name', 'sales'], ['长沙', 150]], 1)

// 返回值:{status: 200, msg: 'success'}
let result = ds_save(1, contents)
if(result.status === 200) { alert('保存成功') }

更多用法参见: 数据填报 | 数据更新


ds_download(文件名, dataset, xls=0) #

下载数据:将数据集下载到本地。默认下载为 CSV 文件;传入 xls=1 则下载为 Excel(.xlsx)文件。

// 下载为 CSV
ds_download('销售数据', dataset)
// 下载文件名:销售数据(浏览器自动加扩展名)

// 下载为 Excel
ds_download('销售数据', dataset, 1)
// 下载文件名:销售数据.xlsx

// 下载纯文本字符串
ds_download('report.txt', '这是一段文本内容')

更多用法参见: 数据下载


ds_uploadfile(blob, filename, name=null, callback=null) #

上传文件:将文件(Blob 对象)上传到服务端,上传成功后执行回调函数。常与文件选择 input 配合使用。

参数 说明
blob 文件 Blob 对象
filename 文件名(含扩展名)
name 存储分类名,默认使用 dashid
callback 上传成功回调,接收服务端返回的数据
// 配合文件 input 使用
document.getElementById('fileInput').addEventListener('change', function(e) {
    let file = e.target.files[0]
    ds_uploadfile(file, file.name, 'my_category', function(data) {
        console.log('上传成功,文件路径:', data.url)
    })
})

// 上传 Canvas 截图
let canvas = document.getElementById('myCanvas')
canvas.toBlob(function(blob) {
    ds_uploadfile(blob, 'screenshot.png', null, function(data) {
        alert('截图已上传:' + data.url)
    })
})

常用 JS 原生函数 #

// 在末尾追加一行/元素
dataset.push(['R3', 5, 9])

// 在开头插入一行/元素(注意:unshift 拼写)
dataset.unshift(['header', 'C1', 'C2'])

// 切片
dataset = dataset.slice(1)       // 去掉表头,从第 1 行开始
dataset = dataset.slice(5, 10)   // 取第 5 到第 9 行(不含第 10 行)
dataset = dataset.slice(-3)      // 取最后 3 行

// for 循环(性能最好,SmartChart 推荐)
for (let i = 0; i < dataset.length; i++) {
    let row = dataset[i]
}

// forEach(可读性好,无法 break)
dataset.forEach(function(row, index) {
    console.log(index, row)
})

// map(生成新数组)
let values = dataset.slice(1).map(row => row[1])   // 取第二列值列表

// find(找第一个匹配元素)
let row = dataset.slice(1).find(row => row[0] === 'R1')

// concat(合并数组)
let merged = dataset.concat(dataset_extra.slice(1))

原始数据格式参考 #

假设 SQL = SELECT 维度1, 维度2, 数据 FROM xxxx,生成的标准二维数组格式如下:

dataset = [['category', 'C1', 'C2'],  // 第 0 行:表头
           ['R1',        12,   18],    // 第 1 行起:数据
           ['R2',        10,   17]]
  • 第 0 行:表头,对应 SQL 查询的字段名
  • 第 1 行起:数据行,第一列通常为维度(分类),后续列为数值
  • 所有转化函数均以此格式为输入,输出格式也保持一致(除 ds_createMapds_createMap_all 等转换函数外)