mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 03:48:13 +08:00
commit
413d4a55d0
@ -428,7 +428,22 @@ test('evalute:array:func', () => {
|
|||||||
id: 1.1,
|
id: 1.1,
|
||||||
name: 1.3
|
name: 1.3
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
obj1: {
|
||||||
|
p1: 'name',
|
||||||
|
p2: 'age',
|
||||||
|
p3: 'obj',
|
||||||
|
p4: [
|
||||||
|
{
|
||||||
|
p41: 'Tom',
|
||||||
|
p42: 'Jerry'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
p41: 'baidu',
|
||||||
|
p42: 'amis'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(evaluate('${COMPACT(arr1)}', data)).toMatchObject([1, 2, 3]);
|
expect(evaluate('${COMPACT(arr1)}', data)).toMatchObject([1, 2, 3]);
|
||||||
@ -466,6 +481,33 @@ test('evalute:array:func', () => {
|
|||||||
expect(
|
expect(
|
||||||
evaluate('${ARRAYFILTER(arr1, item => item && item >=2)}', data)
|
evaluate('${ARRAYFILTER(arr1, item => item && item >=2)}', data)
|
||||||
).toMatchObject([2, 3]);
|
).toMatchObject([2, 3]);
|
||||||
|
|
||||||
|
expect(evaluate('${ARRAYFINDINDEX(arr3, item => item === 2)}', data)).toBe(1);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
evaluate('${ARRAYFIND(arr5, item => item.name === 1.3)}', data)
|
||||||
|
).toMatchObject({
|
||||||
|
id: 1.1,
|
||||||
|
name: 1.3
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(evaluate('${ARRAYSOME(arr5, item => item.name === 1.3)}', data)).toBe(
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(evaluate('${ARRAYEVERY(arr5, item => item.name === 1.3)}', data)).toBe(
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(evaluate('${ARRAYINCLUDES(arr1, false)}', data)).toBe(true);
|
||||||
|
|
||||||
|
expect(evaluate('${GET(arr1, 2)}', data)).toBe(false);
|
||||||
|
expect(evaluate('${GET(arr1, 6, "not-found")}', data)).toBe('not-found');
|
||||||
|
expect(evaluate('${GET(arr5, "[2].name")}', data)).toBe(1.3);
|
||||||
|
expect(evaluate('${GET(arr5, "2.name")}', data)).toBe(1.3);
|
||||||
|
expect(evaluate('${GET(obj1, "p2")}', data)).toBe('age');
|
||||||
|
expect(evaluate('${GET(obj1, "p4.1.p42")}', data)).toBe('amis');
|
||||||
|
expect(evaluate('${GET(obj1, "p4[1].p42")}', data)).toBe('amis');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('evalute:ISTYPE', () => {
|
test('evalute:ISTYPE', () => {
|
||||||
|
@ -863,6 +863,85 @@ DATEMODIFY(A, -2, 'month')
|
|||||||
数据做数据过滤,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
|
数据做数据过滤,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
|
||||||
将第二个箭头函数返回为 false 的成员过滤掉。
|
将第二个箭头函数返回为 false 的成员过滤掉。
|
||||||
|
|
||||||
|
### ARRAYFINDINDEX
|
||||||
|
|
||||||
|
用法:`ARRAYFINDINDEX(arr, item => item === 2)`
|
||||||
|
|
||||||
|
* `arr:Array<any>` 数组
|
||||||
|
* `iterator:Array<any>` 箭头函数
|
||||||
|
|
||||||
|
返回:`number` 结果
|
||||||
|
|
||||||
|
数据做数据查找,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
|
||||||
|
找出第二个箭头函数返回为 true 的成员的索引。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
ARRAYFINDINDEX([0, 2, false], item => item === 2) 得到 1
|
||||||
|
|
||||||
|
### ARRAYFIND
|
||||||
|
|
||||||
|
用法:`ARRAYFIND(arr, item => item === 2)`
|
||||||
|
|
||||||
|
* `arr:Array<any>` 数组
|
||||||
|
* `iterator:Array<any>` 箭头函数
|
||||||
|
|
||||||
|
返回:`any` 结果
|
||||||
|
|
||||||
|
数据做数据查找,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
|
||||||
|
找出第二个箭头函数返回为 true 的成员。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
ARRAYFIND([0, 2, false], item => item === 2) 得到 2
|
||||||
|
|
||||||
|
### ARRAYSOME
|
||||||
|
|
||||||
|
用法:`ARRAYSOME(arr, item => item === 2)`
|
||||||
|
|
||||||
|
* `arr:Array<any>` 数组
|
||||||
|
* `iterator:Array<any>` 箭头函数
|
||||||
|
|
||||||
|
返回:`boolean` 结果
|
||||||
|
|
||||||
|
数据做数据遍历判断,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
|
||||||
|
判断第二个箭头函数是否存在返回为 true 的成员。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
ARRAYSOME([0, 2, false], item => item === 2) 得到 true
|
||||||
|
|
||||||
|
### ARRAYEVERY
|
||||||
|
|
||||||
|
用法:`ARRAYEVERY(arr, item => item === 2)`
|
||||||
|
|
||||||
|
* `arr:Array<any>` 数组
|
||||||
|
* `iterator:Array<any>` 箭头函数
|
||||||
|
|
||||||
|
返回:`boolean` 结果
|
||||||
|
|
||||||
|
数据做数据遍历判断,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
|
||||||
|
判断第二个箭头函数返回是否都为 true。
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
ARRAYEVERY([0, 2, false], item => item === 2) 得到 false
|
||||||
|
|
||||||
|
### ARRAYINCLUDES
|
||||||
|
|
||||||
|
用法:`ARRAYINCLUDES(arr, 2)`
|
||||||
|
|
||||||
|
* `arr:Array<any>` 数组
|
||||||
|
* `item:any` 元素
|
||||||
|
|
||||||
|
返回:`any` 结果
|
||||||
|
|
||||||
|
判断数据中是否存在指定元素
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
ARRAYINCLUDES([0, 2, false], 2) 得到 true
|
||||||
|
|
||||||
### COMPACT
|
### COMPACT
|
||||||
|
|
||||||
用法:`COMPACT(arr)`
|
用法:`COMPACT(arr)`
|
||||||
@ -923,6 +1002,26 @@ UNIQ([{a: '1'}, {b: '2'}, {a: '1'}], 'id')
|
|||||||
|
|
||||||
## 其他
|
## 其他
|
||||||
|
|
||||||
|
### GET
|
||||||
|
|
||||||
|
用法:`GET(arr, 2)`
|
||||||
|
|
||||||
|
* `obj:any` 对象或数组
|
||||||
|
* `path:string` 路径
|
||||||
|
* `defaultValue:any` 如果解析不到则返回该值
|
||||||
|
|
||||||
|
返回:`any` 结果
|
||||||
|
|
||||||
|
根据对象或者数组的path路径获取值。 如果解析 value 是 undefined 会以 defaultValue 取代
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
GET([0, 2, {name: 'amis', age: 18}], 1) 得到 2
|
||||||
|
GET([0, 2, {name: 'amis', age: 18}], '2.name') 得到 'amis'
|
||||||
|
GET({arr: [{name: 'amis', age: 18}]}, 'arr[0].name') 得到 'amis'
|
||||||
|
GET({arr: [{name: 'amis', age: 18}]}, 'arr.0.name') 得到 'amis'
|
||||||
|
GET({arr: [{name: 'amis', age: 18}]}, 'arr.1.name', 'not-found') 得到 'not-found'
|
||||||
|
|
||||||
### ISTYPE
|
### ISTYPE
|
||||||
|
|
||||||
用法:`ISTYPE([{a: '1'}, {b: '2'}, {a: '1'}], 'array')`
|
用法:`ISTYPE([{a: '1'}, {b: '2'}, {a: '1'}], 'array')`
|
||||||
|
@ -1503,6 +1503,143 @@ export const doc: {
|
|||||||
},
|
},
|
||||||
namespace: "数组"
|
namespace: "数组"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ARRAYFINDINDEX",
|
||||||
|
description: "数据做数据查找,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。\n找出第二个箭头函数返回为 true 的成员的索引。\n\n示例:\n\nARRAYFINDINDEX([0, 2, false], item => item === 2) 得到 1",
|
||||||
|
example: "ARRAYFINDINDEX(arr, item => item === 2)",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
type: "Array<any>",
|
||||||
|
name: "arr",
|
||||||
|
description: "数组"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "Array<any>",
|
||||||
|
name: "iterator",
|
||||||
|
description: "箭头函数"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: "number",
|
||||||
|
description: "结果"
|
||||||
|
},
|
||||||
|
namespace: "数组"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ARRAYFIND",
|
||||||
|
description: "数据做数据查找,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。\n找出第二个箭头函数返回为 true 的成员。\n\n示例:\n\nARRAYFIND([0, 2, false], item => item === 2) 得到 2",
|
||||||
|
example: "ARRAYFIND(arr, item => item === 2)",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
type: "Array<any>",
|
||||||
|
name: "arr",
|
||||||
|
description: "数组"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "Array<any>",
|
||||||
|
name: "iterator",
|
||||||
|
description: "箭头函数"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: "any",
|
||||||
|
description: "结果"
|
||||||
|
},
|
||||||
|
namespace: "数组"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ARRAYSOME",
|
||||||
|
description: "数据做数据遍历判断,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。\n判断第二个箭头函数是否存在返回为 true 的成员。\n\n示例:\n\nARRAYSOME([0, 2, false], item => item === 2) 得到 true",
|
||||||
|
example: "ARRAYSOME(arr, item => item === 2)",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
type: "Array<any>",
|
||||||
|
name: "arr",
|
||||||
|
description: "数组"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "Array<any>",
|
||||||
|
name: "iterator",
|
||||||
|
description: "箭头函数"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: "boolean",
|
||||||
|
description: "结果"
|
||||||
|
},
|
||||||
|
namespace: "数组"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ARRAYEVERY",
|
||||||
|
description: "数据做数据遍历判断,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。\n判断第二个箭头函数返回是否都为 true。\n\n示例:\n\nARRAYEVERY([0, 2, false], item => item === 2) 得到 false",
|
||||||
|
example: "ARRAYEVERY(arr, item => item === 2)",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
type: "Array<any>",
|
||||||
|
name: "arr",
|
||||||
|
description: "数组"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "Array<any>",
|
||||||
|
name: "iterator",
|
||||||
|
description: "箭头函数"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: "boolean",
|
||||||
|
description: "结果"
|
||||||
|
},
|
||||||
|
namespace: "数组"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "ARRAYINCLUDES",
|
||||||
|
description: "判断数据中是否存在指定元素\n\n示例:\n\nARRAYINCLUDES([0, 2, false], 2) 得到 true",
|
||||||
|
example: "ARRAYINCLUDES(arr, 2)",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
type: "Array<any>",
|
||||||
|
name: "arr",
|
||||||
|
description: "数组"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "any",
|
||||||
|
name: "item",
|
||||||
|
description: "元素"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: "any",
|
||||||
|
description: "结果"
|
||||||
|
},
|
||||||
|
namespace: "数组"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "GET",
|
||||||
|
description: "根据对象或者数组的path路径获取值。 如果解析 value 是 undefined 会以 defaultValue 取代\n\n示例:\n\nGET([0, 2, {name: 'amis', age: 18}], 1) 得到 2\nGET([0, 2, {name: 'amis', age: 18}], '2.name') 得到 'amis'\nGET({arr: [{name: 'amis', age: 18}]}, 'arr[0].name') 得到 'amis'\nGET({arr: [{name: 'amis', age: 18}]}, 'arr.0.name') 得到 'amis'\nGET({arr: [{name: 'amis', age: 18}]}, 'arr.1.name', 'not-found') 得到 'not-found'",
|
||||||
|
example: "GET(arr, 2)",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
type: "any",
|
||||||
|
name: "obj",
|
||||||
|
description: "对象或数组"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "string",
|
||||||
|
name: "path",
|
||||||
|
description: "路径"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "any",
|
||||||
|
name: "defaultValue",
|
||||||
|
description: "如果解析不到则返回该值"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: "any",
|
||||||
|
description: "结果"
|
||||||
|
},
|
||||||
|
namespace: "其他"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "COMPACT",
|
name: "COMPACT",
|
||||||
description: "数组过滤掉 false、null、0 和 \"\"\n\n示例:\n\nCOMPACT([0, 1, false, 2, '', 3]) 得到 [1, 2, 3]",
|
description: "数组过滤掉 false、null、0 和 \"\"\n\n示例:\n\nCOMPACT([0, 1, false, 2, '', 3]) 得到 [1, 2, 3]",
|
||||||
|
@ -12,6 +12,7 @@ import uniqWith from 'lodash/uniqWith';
|
|||||||
import uniqBy from 'lodash/uniqBy';
|
import uniqBy from 'lodash/uniqBy';
|
||||||
import isEqual from 'lodash/isEqual';
|
import isEqual from 'lodash/isEqual';
|
||||||
import isPlainObject from 'lodash/isPlainObject';
|
import isPlainObject from 'lodash/isPlainObject';
|
||||||
|
import get from 'lodash/get';
|
||||||
import {EvaluatorOptions, FilterContext, FilterMap, FunctionMap} from './types';
|
import {EvaluatorOptions, FilterContext, FilterMap, FunctionMap} from './types';
|
||||||
|
|
||||||
export class Evaluator {
|
export class Evaluator {
|
||||||
@ -1841,6 +1842,141 @@ export class Evaluator {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据做数据查找,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
|
||||||
|
* 找出第二个箭头函数返回为 true 的成员的索引。
|
||||||
|
*
|
||||||
|
* 示例:
|
||||||
|
*
|
||||||
|
* ARRAYFINDINDEX([0, 2, false], item => item === 2) 得到 1
|
||||||
|
*
|
||||||
|
* @param {Array<any>} arr 数组
|
||||||
|
* @param {Function<any>} iterator 箭头函数
|
||||||
|
* @namespace 数组
|
||||||
|
* @example ARRAYFINDINDEX(arr, item => item === 2)
|
||||||
|
* @returns {number} 结果
|
||||||
|
*/
|
||||||
|
fnARRAYFINDINDEX(arr: any[], iterator: any) {
|
||||||
|
if (!iterator || iterator.type !== 'anonymous_function') {
|
||||||
|
throw new Error('expected an anonymous function get ' + iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Array.isArray(arr) ? arr : []).findIndex((item, index, arr) =>
|
||||||
|
this.callAnonymousFunction(iterator, [item, index, arr])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据做数据查找,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
|
||||||
|
* 找出第二个箭头函数返回为 true 的成员。
|
||||||
|
*
|
||||||
|
* 示例:
|
||||||
|
*
|
||||||
|
* ARRAYFIND([0, 2, false], item => item === 2) 得到 2
|
||||||
|
*
|
||||||
|
* @param {Array<any>} arr 数组
|
||||||
|
* @param {Function<any>} iterator 箭头函数
|
||||||
|
* @namespace 数组
|
||||||
|
* @example ARRAYFIND(arr, item => item === 2)
|
||||||
|
* @returns {any} 结果
|
||||||
|
*/
|
||||||
|
fnARRAYFIND(arr: any[], iterator: any) {
|
||||||
|
if (!iterator || iterator.type !== 'anonymous_function') {
|
||||||
|
throw new Error('expected an anonymous function get ' + iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Array.isArray(arr) ? arr : []).find((item, index, arr) =>
|
||||||
|
this.callAnonymousFunction(iterator, [item, index, arr])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据做数据遍历判断,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
|
||||||
|
* 判断第二个箭头函数是否存在返回为 true 的成员。
|
||||||
|
*
|
||||||
|
* 示例:
|
||||||
|
*
|
||||||
|
* ARRAYSOME([0, 2, false], item => item === 2) 得到 true
|
||||||
|
*
|
||||||
|
* @param {Array<any>} arr 数组
|
||||||
|
* @param {Function<any>} iterator 箭头函数
|
||||||
|
* @namespace 数组
|
||||||
|
* @example ARRAYSOME(arr, item => item === 2)
|
||||||
|
* @returns {boolean} 结果
|
||||||
|
*/
|
||||||
|
fnARRAYSOME(arr: any[], iterator: any) {
|
||||||
|
if (!iterator || iterator.type !== 'anonymous_function') {
|
||||||
|
throw new Error('expected an anonymous function get ' + iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Array.isArray(arr) ? arr : []).some((item, index, arr) =>
|
||||||
|
this.callAnonymousFunction(iterator, [item, index, arr])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据做数据遍历判断,需要搭配箭头函数一起使用,注意箭头函数只支持单表达式用法。
|
||||||
|
* 判断第二个箭头函数返回是否都为 true。
|
||||||
|
*
|
||||||
|
* 示例:
|
||||||
|
*
|
||||||
|
* ARRAYEVERY([0, 2, false], item => item === 2) 得到 false
|
||||||
|
*
|
||||||
|
* @param {Array<any>} arr 数组
|
||||||
|
* @param {Function<any>} iterator 箭头函数
|
||||||
|
* @namespace 数组
|
||||||
|
* @example ARRAYEVERY(arr, item => item === 2)
|
||||||
|
* @returns {boolean} 结果
|
||||||
|
*/
|
||||||
|
fnARRAYEVERY(arr: any[], iterator: any) {
|
||||||
|
if (!iterator || iterator.type !== 'anonymous_function') {
|
||||||
|
throw new Error('expected an anonymous function get ' + iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Array.isArray(arr) ? arr : []).every((item, index, arr) =>
|
||||||
|
this.callAnonymousFunction(iterator, [item, index, arr])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断数据中是否存在指定元素
|
||||||
|
*
|
||||||
|
* 示例:
|
||||||
|
*
|
||||||
|
* ARRAYINCLUDES([0, 2, false], 2) 得到 true
|
||||||
|
*
|
||||||
|
* @param {Array<any>} arr 数组
|
||||||
|
* @param {any} item 元素
|
||||||
|
* @namespace 数组
|
||||||
|
* @example ARRAYINCLUDES(arr, 2)
|
||||||
|
* @returns {any} 结果
|
||||||
|
*/
|
||||||
|
fnARRAYINCLUDES(arr: any[], item: any) {
|
||||||
|
return (Array.isArray(arr) ? arr : []).includes(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据对象或者数组的path路径获取值。 如果解析 value 是 undefined 会以 defaultValue 取代
|
||||||
|
*
|
||||||
|
* 示例:
|
||||||
|
*
|
||||||
|
* GET([0, 2, {name: 'amis', age: 18}], 1) 得到 2
|
||||||
|
* GET([0, 2, {name: 'amis', age: 18}], '2.name') 得到 'amis'
|
||||||
|
* GET({arr: [{name: 'amis', age: 18}]}, 'arr[0].name') 得到 'amis'
|
||||||
|
* GET({arr: [{name: 'amis', age: 18}]}, 'arr.0.name') 得到 'amis'
|
||||||
|
* GET({arr: [{name: 'amis', age: 18}]}, 'arr.1.name', 'not-found') 得到 'not-found'
|
||||||
|
*
|
||||||
|
* @param {any} obj 对象或数组
|
||||||
|
* @param {string} path 路径
|
||||||
|
* @param {any} defaultValue 如果解析不到则返回该值
|
||||||
|
* @namespace 其他
|
||||||
|
* @example GET(arr, 2)
|
||||||
|
* @returns {any} 结果
|
||||||
|
*/
|
||||||
|
fnGET(obj: any, path: string, defaultValue?: any) {
|
||||||
|
return get(obj, path, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数组过滤掉 false、null、0 和 ""
|
* 数组过滤掉 false、null、0 和 ""
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user