提交 37f198e7 编写于 作者: L lang

Layout properties x => left, y => top, x2 => right, y2 => bottom

上级 7946c1ab
......@@ -39,8 +39,6 @@ define(function (require) {
defaultOption: {
center: ['50%', '50%'],
radius: ['65%', '75%'],
// x2: null,
// y2: null
//
// layout: 'circular',
......
......@@ -45,12 +45,12 @@ define(function(require) {
z: 2, // 二级层叠
clickable: true,
legendHoverLink: true,
x: 80,
y: 60,
x2: 80,
y2: 60,
// width: {totalWidth} - x - x2,
// height: {totalHeight} - y - y2,
left: 80,
top: 60,
right: 80,
bottom: 60,
// width: {totalWidth} - left - right,
// height: {totalHeight} - top - bottom,
// 默认取数据最小最大值
// min: 0,
......
......@@ -6,17 +6,12 @@ define(function (require) {
var parsePercent = number.parsePercent;
function getViewRect(seriesModel, api) {
return layout.parsePositionInfo({
x: seriesModel.get('x'),
y: seriesModel.get('y'),
x2: seriesModel.get('x2'),
y2: seriesModel.get('y2'),
width: seriesModel.get('width'),
height: seriesModel.get('height')
}, {
width: api.getWidth(),
height: api.getHeight()
});
return layout.getLayoutRect(
seriesModel.getBoxLayoutOption(), {
width: api.getWidth(),
height: api.getHeight()
}
);
}
function getSortedIndices(data, sort) {
......
......@@ -119,10 +119,10 @@ define(function (require) {
layoutAnimation: true
},
x: 'center',
y: 'center',
x2: null,
y2: null,
left: 'center',
top: 'center',
// right: null,
// bottom: null,
// width: '80%',
// height: '80%',
......
......@@ -5,15 +5,9 @@ define(function (require) {
var bbox = require('zrender/core/bbox');
function getViewRect(seriesModel, api, aspect) {
return layout.parsePositionInfo({
x: seriesModel.get('x'),
y: seriesModel.get('y'),
x2: seriesModel.get('x2'),
y2: seriesModel.get('y2'),
width: seriesModel.get('width'),
height: seriesModel.get('height'),
aspect: aspect
}, {
var option = seriesModel.getBoxLayoutOption();
option.aspect = aspect;
return layout.getLayoutRect(option, {
width: api.getWidth(),
height: api.getHeight()
});
......
......@@ -138,12 +138,12 @@ define(function (require) {
map: 'china',
// 'center' | 'left' | 'right' | 'x%' | {number}
x: 'center',
left: 'center',
// 'center' | 'top' | 'bottom' | 'x%' | {number}
y: 'center',
// x2
// y2
// width: '60%'
top: 'center',
// right
// bottom
// width:
// height // 自适应
// 数值合并方式,默认加和,可选为:
......
......@@ -43,10 +43,10 @@ define(function (require) {
layout : null,
// the position of the whole view
x: '5%',
y: '5%',
x2: '20%',
y2: '5%',
left: '5%',
top: '5%',
right: '20%',
bottom: '5%',
// the dx of the node
nodeWidth: 20,
......
......@@ -40,17 +40,12 @@ define(function (require) {
* get the layout position of the whole view.
*/
function getViewRect(seriesModel, api) {
return layout.parsePositionInfo({
x: seriesModel.get('x'),
y: seriesModel.get('y'),
x2: seriesModel.get('x2'),
y2: seriesModel.get('y2'),
width: seriesModel.get('width'),
height: seriesModel.get('height')
},{
width: api.getWidth(),
height: api.getHeight()
});
return layout.getLayoutRect(
seriesModel.getBoxLayoutOption(), {
width: api.getWidth(),
height: api.getHeight()
}
);
}
function layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations) {
......
......@@ -20,10 +20,10 @@ define(function(require) {
clickable: true,
// center: ['50%', '50%'], // not supported in ec3.
// size: ['80%', '80%'], // deprecated, compatible with ec2.
x: 'center',
y: 'middle',
x2: null,
y2: null,
left: 'center',
top: 'middle',
right: null,
bottom: null,
width: '80%',
height: '80%',
sort: true, // Can be null or false or true
......
......@@ -32,15 +32,8 @@ define(function (require) {
ecHeight
);
var layoutInfo = layout.parsePositionInfo(
{
x: seriesModel.get('x'),
y: seriesModel.get('y'),
x2: seriesModel.get('x2'),
y2: seriesModel.get('y2'),
width: containerWidth,
height: containerHeight
},
var layoutInfo = layout.getLayoutRect(
seriesModel.getBoxLayoutOption(),
{
width: api.getWidth(),
height: api.getHeight()
......
......@@ -13,9 +13,9 @@ define(function(require) {
* @protected
*/
defaultOption: {
// x: {number}, // 水平安放位置,默认为根据grid参数适配,可选为:
// left: {number}, // 水平安放位置,默认为根据grid参数适配,可选为:
// {number}(x坐标,单位px)
// y: {number}, // 垂直安放位置,默认为根据grid参数适配,可选为:
// top: {number}, // 垂直安放位置,默认为根据grid参数适配,可选为:
// {number}(y坐标,单位px)
// width: {number}, // 指定宽度,横向布局时默认为根据grid参数适配
// height: {number}, // 指定高度,纵向布局时默认为根据grid参数适配
......
......@@ -145,8 +145,8 @@ define(function (require) {
var ecWidth = api.getWidth();
var ecHeight = api.getHeight();
var x = dataZoomModel.get('x');
var y = dataZoomModel.get('y');
var x = dataZoomModel.get('left');
var y = dataZoomModel.get('top');
var width = dataZoomModel.get('width');
var height = dataZoomModel.get('height');
......
......@@ -222,7 +222,7 @@ define(function (require) {
}
}
function shouldShowCover(p1, p2) {
function shouldShowCover() {
var track = this._track;
if (!track.length) {
......
......@@ -5,24 +5,8 @@ define(function (require) {
var graphic = require('../../util/graphic');
function positionGroup(group, model, api) {
var x = model.get('x');
var y = model.get('y');
var x2 = model.get('x2');
var y2 = model.get('y2');
if (!x && !x2) {
x = 'center';
}
if (!y && !y2) {
y = 'top';
}
layout.positionGroup(
group, {
x: x,
y: y,
x2: x2,
y2: y2
},
group, model.getBoxLayoutOption(),
{
width: api.getWidth(),
height: api.getHeight()
......@@ -74,5 +58,5 @@ define(function (require) {
group.add(rect);
}
}
};
});
\ No newline at end of file
......@@ -128,15 +128,11 @@ define(function(require) {
// 'horizontal' | 'vertical'
orient: 'horizontal',
// x, x2 为水平安放位置,默认为全图居中,可选为:
// 'center' | 'left' | 'right' | {number}(x坐标,单位px)
// x: 'center',
// x2: 'center',
// y, y2 为垂直安放位置,默认为全图顶端,可选为:
// 'top' | 'bottom' | 'center' | {number}(y坐标,单位px)
// y: 'top',
// y2: 'top'
left: 'center',
// right: 'center',
top: 'top',
// bottom: 'top',
// 水平对齐
// 'auto' | 'left' | 'right'
......
......@@ -73,7 +73,7 @@ define(function (require) {
this.group.removeAll();
var mainGroup = new graphic.Group();
// var mainGroup = new graphic.Group();
var layoutInfo = this._layout(timelineModel, api);
......@@ -623,15 +623,8 @@ define(function (require) {
});
function getViewRect(model, api) {
return layout.parsePositionInfo(
{
x: model.get('x'),
y: model.get('y'),
x2: model.get('x2'),
y2: model.get('y2'),
width: model.get('width'),
height: model.get('height')
},
return layout.getLayoutRect(
model.getBoxLayoutOption(),
{
width: api.getWidth(),
height: api.getHeight()
......
......@@ -25,10 +25,10 @@ define(function(require) {
realtime: true,
x: '20%',
y: null,
x2: '20%',
y2: 0,
left: '20%',
top: null,
right: '20%',
bottom: 0,
width: null,
height: 40,
padding: 5,
......
......@@ -3,8 +3,8 @@
*/
define(function (require) {
var zrUtil = require('zrender/core/util');
var graphic = require('../../util/graphic');
// var zrUtil = require('zrender/core/util');
// var graphic = require('../../util/graphic');
var ComponentView = require('../../view/Component');
// Constants
......
......@@ -30,14 +30,12 @@ define(function(require) {
// 仅支持self | blank
// subtarget: null,
// 水平安放位置,默认为左对齐,可选为:
// 'center' ¦ 'left' ¦ 'right'
// ¦ {number}(x坐标,单位px)
x: 'left',
// 垂直安放位置,默认为全图顶端,可选为:
left: 'left',
// 'top' ¦ 'bottom' ¦ 'center'
// ¦ {number}(y坐标,单位px)
y: 'top',
top: 'top',
// 水平对齐
// 'auto' | 'left' | 'right'
......@@ -134,49 +132,45 @@ define(function(require) {
// If no subText, but add subTextEl, there will be an empty line.
var groupRect = group.getBoundingRect();
var positionInfo = layout.parsePositionInfo(
{
x: titleModel.get('x'),
y: titleModel.get('y'),
x2: titleModel.get('x2'),
y2: titleModel.get('y2'),
width: groupRect.width,
height: groupRect.height
}, {
var layoutOption = titleModel.getBoxLayoutOption();
layoutOption.width = groupRect.width;
layoutOption.height = groupRect.height;
var layoutRect = layout.getLayoutRect(
layoutOption, {
width: api.getWidth(),
height: api.getHeight()
}, titleModel.get('padding')
);
// Adjust text align based on position
if (!textAlign) {
var p = positionInfo.x / api.getWidth();
var p2 = (positionInfo.x + positionInfo.width) / api.getWidth();
var p = layoutRect.x / api.getWidth();
var p2 = (layoutRect.x + layoutRect.width) / api.getWidth();
if (p < 0.2) {
textAlign = 'left';
}
else if (p2 > 0.8) {
positionInfo.x += positionInfo.width;
layoutRect.x += layoutRect.width;
textAlign = 'right';
}
else {
positionInfo.x += positionInfo.width / 2;
layoutRect.x += layoutRect.width / 2;
textAlign = 'center';
}
}
group.position = [positionInfo.x, positionInfo.y];
group.position = [layoutRect.x, layoutRect.y];
textEl.style.textAlign = subTextEl.style.textAlign = textAlign;
textEl.dirty();
subTextEl.dirty();
// Render background
var padding = positionInfo.margin;
var padding = layoutRect.margin;
var rect = new graphic.Rect({
shape: {
x: -padding[3],
y: -padding[0],
width: positionInfo.width + padding[1] + padding[3],
height: positionInfo.height + padding[0] + padding[2]
width: layoutRect.width + padding[1] + padding[3],
height: layoutRect.height + padding[0] + padding[2]
},
style: {
stroke: titleModel.get('borderColor'),
......
......@@ -26,12 +26,12 @@ define(function (require) {
orient: 'horizontal',
x: 'right',
left: 'right',
y: 'top',
top: 'top',
// x2
// y2
// right
// bottom
backgroundColor: 'transparent',
......
......@@ -58,12 +58,14 @@ define(function(require) {
orient: 'vertical', // 布局方式,默认为垂直布局,可选为:
// 'horizontal' ¦ 'vertical'
x: 'left', // 水平安放位置,默认为全图左对齐,可选为:
left: 'left', // 水平安放位置,默认为全图左对齐,可选为:
// 'center' ¦ 'left' ¦ 'right'
// ¦ {number}(x坐标,单位px)
y: 'bottom', // 垂直安放位置,默认为全图底部,可选为:
top: 'bottom', // 垂直安放位置,默认为全图底部,可选为:
// 'top' ¦ 'bottom' ¦ 'center'
// ¦ {number}(y坐标,单位px)
// right
// bottom
inverse: false,
seriesIndex: null, // 所控制的series indices,默认所有有value的series.
......
......@@ -167,22 +167,11 @@ define(function (require) {
*/
positionGroup: function (group) {
var model = this.visualMapModel;
var x = model.get('x');
var y = model.get('y');
var x2 = model.get('x2');
var y2 = model.get('y2');
var api = this.api;
if (!x && !x2) {
x = 'center';
}
if (!y && !y2) {
y = 'bottom';
}
layout.positionGroup(
group,
{x: x, y: y, x2: x2, y2: y2},
model.getBoxLayoutOption(),
{width: api.getWidth(), height: api.getHeight()}
);
},
......
......@@ -86,17 +86,11 @@ define(function(require, factory) {
*/
gridProto.resize = function (gridModel, api) {
var gridRect = layout.parsePositionInfo({
x: gridModel.get('x'),
y: gridModel.get('y'),
x2: gridModel.get('x2'),
y2: gridModel.get('y2'),
width: gridModel.get('width'),
height: gridModel.get('height')
}, {
width: api.getWidth(),
height: api.getHeight()
});
var gridRect = layout.getLayoutRect(
gridModel.getBoxLayoutOption(), {
width: api.getWidth(),
height: api.getHeight()
});
this._rect = gridRect;
......
......@@ -14,15 +14,15 @@ define(function(require) {
dependencies: ['xAxis', 'yAxis'],
mergeDefaultAndTheme: function (option, ecModel) {
// Not specify layout with x2, width, y2, height
// Not specify layout with right, width, bottom, height
// FIXME 通用?
if (option.x2 == null || option.width == null || option.x != null) {
option.x = option.x != null ? option.x : '10%';
option.x2 = option.x2 != null ? option.x2 : '10%';
if (option.right == null || option.width == null || option.left != null) {
option.left = option.left != null ? option.left : '10%';
option.right = option.right != null ? option.right : '10%';
}
if (option.y2 == null || option.height == null || option.y != null) {
option.y = option.y != null ? option.y : 60;
option.y2 = option.y2 != null ? option.y2 : 60;
if (option.bottom == null || option.height == null || option.top != null) {
option.top = option.top != null ? option.top : 60;
option.bottom = option.bottom != null ? option.bottom : 60;
}
ComponentModel.prototype.mergeDefaultAndTheme.call(
this, option, ecModel
......@@ -36,16 +36,16 @@ define(function(require) {
defaultOption: {
show: false,
zlevel: 0, // 一级层叠
z: 0, // 二级层叠
// x: '10%',
// y: 60,
// x2: '10%',
// y2: 60,
zlevel: 0,
z: 0,
// left: '10%',
// top: 60,
// right: '10%',
// bottom: 60,
// If grid size contain label
containLabel: false,
// width: {totalWidth} - x - x2,
// height: {totalHeight} - y - y2,
// width: {totalWidth} - left - right,
// height: {totalHeight} - top - bottom,
backgroundColor: 'rgba(0,0,0,0)',
borderWidth: 1,
borderColor: '#ccc'
......
......@@ -30,15 +30,15 @@ define(function (require) {
show: true,
x: 'center',
left: 'center',
y: 'center',
top: 'center',
// 自适应
// width:,
// height:,
// x2
// y2
// right
// bottom
// Map type
map: '',
......
......@@ -17,29 +17,16 @@ define(function (require) {
function resizeGeo (geoModel, api) {
var rect = this.getBoundingRect();
var width = geoModel.get('width');
var height = geoModel.get('height');
var viewRect = layout.parsePositionInfo({
x: geoModel.get('x'),
y: geoModel.get('y'),
x2: geoModel.get('x2'),
y2: geoModel.get('y2'),
width: width,
height: height,
// 0.75 rate
aspect: rect.width / rect.height * 0.75
}, {
var boxLayoutOption = geoModel.getBoxLayoutOption();
// 0.75 rate
boxLayoutOption.aspect = rect.width / rect.height * 0.75;
var viewRect = layout.getLayoutRect(boxLayoutOption, {
width: api.getWidth(),
height: api.getHeight()
});
var width = viewRect.width;
var height = viewRect.height;
var x = viewRect.x + (width - viewRect.width) / 2;
var y = viewRect.y + (height - viewRect.height) / 2;
this.setViewRect(x, y, width, height);
this.setViewRect(viewRect.x, viewRect.y, viewRect.width, viewRect.height);
var roamDetailModel = geoModel.getModel('roamDetail');
......
......@@ -116,15 +116,8 @@ define(function(require) {
* @param {module:echarts/ExtensionAPI} api
*/
resize: function (parallelModel, api) {
this._rect = layout.parsePositionInfo(
{
x: parallelModel.get('x'),
y: parallelModel.get('y'),
x2: parallelModel.get('x2'),
y2: parallelModel.get('y2'),
width: parallelModel.get('width'),
height: parallelModel.get('height')
},
this._rect = layout.getLayoutRect(
parallelModel.getBoxLayoutOption(),
{
width: api.getWidth(),
height: api.getHeight()
......
......@@ -35,12 +35,12 @@ define(function(require) {
zlevel: 0, // 一级层叠
z: 0, // 二级层叠
x: 80,
y: 60,
x2: 80,
y2: 60,
// width: {totalWidth} - x - x2,
// height: {totalHeight} - y - y2,
left: 80,
top: 60,
right: 80,
bottom: 60,
// width: {totalWidth} - left - right,
// height: {totalHeight} - top - bottom,
layout: 'horizontal', // 'horizontal' or 'vertical'
......
......@@ -144,5 +144,7 @@ define(function(require) {
});
}
zrUtil.mixin(ComponentModel, require('./mixin/boxLayout'));
return ComponentModel;
});
\ No newline at end of file
define(function (require) {
return {
getBoxLayoutOption: function () {
return {
left: this.get('left'),
top: this.get('top'),
right: this.get('right'),
bottom: this.get('bottom'),
width: this.get('width'),
height: this.get('height')
};
}
};
});
\ No newline at end of file
......@@ -32,8 +32,32 @@ define(function (require) {
}
}
function compatLayoutProperties(option) {
each(LAYOUT_PROPERTIES, function (prop) {
if (prop[0] in option && !(prop[1] in option)) {
option[prop[1]] = option[prop[0]];
}
});
}
var LAYOUT_PROPERTIES = [
['x', 'left'], ['y', 'top'], ['x2', 'right'], ['y2', 'bottom']
];
var COMPATITABLE_COMPONENTS = [
'grid', 'geo', 'parallel', 'legend', 'toolbox', 'title', 'visualMap', 'dataZoom'
];
var COMPATITABLE_SERIES = [
'bar', 'boxplot', 'candlestick', 'chord', 'effectScatter',
'funnel', 'gauge', 'geoLine', 'graph', 'heatmap', 'line', 'map', 'parallel',
'pie', 'radar', 'sankey', 'scatter', 'treemap'
];
var each = zrUtil.each;
return function (option) {
zrUtil.each(option.series, function (seriesOpt) {
each(option.series, function (seriesOpt) {
if (!zrUtil.isObject(seriesOpt)) {
return;
}
......@@ -52,11 +76,30 @@ define(function (require) {
pointerColor != null
&& set(seriesOpt, 'itemStyle.normal.color', pointerColor);
}
for (var i = 0; i < COMPATITABLE_SERIES.length; i++) {
if (COMPATITABLE_SERIES[i] === seriesOpt.type) {
compatLayoutProperties(seriesOpt);
break;
}
}
});
// dataRange has changed to visualMap
if (option.dataRange) {
option.visualMap = option.dataRange;
}
each(COMPATITABLE_COMPONENTS, function (componentName) {
var options = option[componentName];
if (options) {
if (!zrUtil.isArray(options)) {
options = [options];
}
each(options, function (option) {
compatLayoutProperties(option);
});
}
});
};
});
\ No newline at end of file
......@@ -132,15 +132,12 @@ define(function(require) {
/**
* Parse position info.
* position info is specified by either
* {x, y}, {x2, y2}
* If all properties exists, x2 and y2 will be igonred.
*
* @param {Object} positionInfo
* @param {number|string} [positionInfo.x]
* @param {number|string} [positionInfo.y]
* @param {number|string} [positionInfo.x2]
* @param {number|string} [positionInfo.y2]
* @param {number|string} [positionInfo.left]
* @param {number|string} [positionInfo.top]
* @param {number|string} [positionInfo.right]
* @param {number|string} [positionInfo.bottom]
* @param {number|string} [positionInfo.width]
* @param {number|string} [positionInfo.height]
* @param {number|string} [positionInfo.aspect] Aspect is width / height
......@@ -149,7 +146,7 @@ define(function(require) {
*
* @return {module:zrender/core/BoundingRect}
*/
layout.parsePositionInfo = function (
layout.getLayoutRect = function (
positionInfo, containerRect, margin
) {
margin = formatUtil.normalizeCssArray(margin || 0);
......@@ -157,10 +154,10 @@ define(function(require) {
var containerWidth = containerRect.width;
var containerHeight = containerRect.height;
var x = parsePercent(positionInfo.x, containerWidth);
var y = parsePercent(positionInfo.y, containerHeight);
var x2 = parsePercent(positionInfo.x2, containerWidth);
var y2 = parsePercent(positionInfo.y2, containerHeight);
var left = parsePercent(positionInfo.left, containerWidth);
var top = parsePercent(positionInfo.top, containerHeight);
var right = parsePercent(positionInfo.right, containerWidth);
var bottom = parsePercent(positionInfo.bottom, containerHeight);
var width = parsePercent(positionInfo.width, containerWidth);
var height = parsePercent(positionInfo.height, containerHeight);
......@@ -168,14 +165,18 @@ define(function(require) {
var horizontalMargin = margin[1] + margin[3];
var aspect = positionInfo.aspect;
// If width is not specified, calculate width from x and x2
// If width is not specified, calculate width from left and right
if (isNaN(width)) {
width = containerWidth - x2 - horizontalMargin - x;
width = containerWidth - right - horizontalMargin - left;
}
if (isNaN(height)) {
height = containerHeight - y2 - verticalMargin - y;
height = containerHeight - bottom - verticalMargin - top;
}
// If width and height are not given
// 1. Graph should not exceeds the container
// 2. Aspect must be keeped
// 3. Graph should take the space as more as possible
if (isNaN(width) && isNaN(height)) {
if (aspect > containerWidth / containerHeight) {
width = containerWidth * 0.8;
......@@ -195,34 +196,34 @@ define(function(require) {
}
}
// If x is not specified, calculate x from x2 and width
if (isNaN(x)) {
x = containerWidth - x2 - width - horizontalMargin;
// If left is not specified, calculate left from right and width
if (isNaN(left)) {
left = containerWidth - right - width - horizontalMargin;
}
if (isNaN(y)) {
y = containerHeight - y2 - height - verticalMargin;
if (isNaN(top)) {
top = containerHeight - bottom - height - verticalMargin;
}
// Align x and y
switch (positionInfo.x || positionInfo.x2) {
// Align left and top
switch (positionInfo.left || positionInfo.right) {
case 'center':
x = containerWidth / 2 - width / 2 - margin[3];
left = containerWidth / 2 - width / 2 - margin[3];
break;
case 'right':
x = containerWidth - width - horizontalMargin;
left = containerWidth - width - horizontalMargin;
break;
}
switch (positionInfo.y || positionInfo.y2) {
switch (positionInfo.top || positionInfo.bottom) {
case 'middle':
case 'center':
y = containerHeight / 2 - height / 2 - margin[0];
top = containerHeight / 2 - height / 2 - margin[0];
break;
case 'bottom':
y = containerHeight - height - verticalMargin;
top = containerHeight - height - verticalMargin;
break;
}
var rect = new BoundingRect(x + margin[3], y + margin[0], width, height);
var rect = new BoundingRect(left + margin[3], top + margin[0], width, height);
rect.margin = margin;
return rect;
};
......@@ -230,15 +231,15 @@ define(function(require) {
/**
* Position group of component in viewport
* Group position is specified by either
* {x, y}, {x2, y2}
* If all properties exists, x2 and y2 will be igonred.
* {left, top}, {right, bottom}
* If all properties exists, right and bottom will be igonred.
*
* @param {module:zrender/container/Group} group
* @param {Object} positionInfo
* @param {number|string} [positionInfo.x]
* @param {number|string} [positionInfo.y]
* @param {number|string} [positionInfo.x2]
* @param {number|string} [positionInfo.y2]
* @param {number|string} [positionInfo.left]
* @param {number|string} [positionInfo.top]
* @param {number|string} [positionInfo.right]
* @param {number|string} [positionInfo.bottom]
* @param {Object} containerRect
* @param {string|number} margin
*/
......@@ -247,12 +248,12 @@ define(function(require) {
) {
var groupRect = group.getBoundingRect();
positionInfo = zrUtil.extend({
positionInfo = zrUtil.extend(zrUtil.clone(positionInfo), {
width: groupRect.width,
height: groupRect.height
}, positionInfo);
});
positionInfo = layout.parsePositionInfo(
positionInfo = layout.getLayoutRect(
positionInfo, containerRect, margin
);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册