“模块:DPLlua”与“星云轨道交通都会线”:页面之间的差异

来自NebulaeWiki
(页面间差异)
(创建页面,内容为“-- <nowiki> local dpl = {} local libraryUtil = require( 'libraryUtil' ) local hasContent = require( 'Module:Paramtest' ).has_content local checkType = libraryUtil.checkType local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg dpl.pipe = '¦' local dataContentMarker = '`#@@#`' local allIncludedParamNames = {} -- Custom function for splitting a string because mw.text.split() is waaay too slow local function split( str, pattern, plain ) local res = {}…”)
 
无编辑摘要
 
第1行: 第1行:
-- <nowiki>
{{Infobox Metro
local dpl = {}
|Picture = MetroMetropolitan.png
local libraryUtil = require( 'libraryUtil' )
|Description = 未安装站台安全门的星天地站
local hasContent = require( 'Module:Paramtest' ).has_content
|Logo = NebulaeCraft.png
local checkType = libraryUtil.checkType
|Name = 星云轨道交通都会线
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg
|Location = 星云市
|Type = 地铁
|System = 星云轨道交通
|Situation = 建设中
|Start = 北堡公园
|End = 闵北商务区
|English = Metropolitan Line
|Code = M4线
|Structure = 地下、高架
|Length = 12.14km (7.54mi)
|Speed = 80千米/小时
|Lines = 2条
|Stations = 19个
|Gauge = 1,435毫米(准轨)
|Electrification = DC 1,500V 接触网供电
|Blocking = CBTC移动自动闭塞
|Signal = 泰雷兹 TSTCBTC 2.0 (DTO有人值守全自动驾驶/GoA3)
|Depot = 闵北车辆段
|Model = MPC01
|Formation = 6/7节C型列车
|Opening =
|Extending =
|Owner = 星云轨道交通集团有限公司
|Operator = 江闵交运集团
}}'''星云轨道交通都会线'''是[[NebulaeCraft]]的一条地铁线路。是星云第二批开工的轨道交通线路之一。


dpl.pipe = '¦'
== 概览 ==
local dataContentMarker = '`#@@#`'
都会线起于北[[浦汇区|浦汇]],经[[星天地]],最终进入[[星川区]],是[[星云轨道交通]]中极其重要的线路之一。
local allIncludedParamNames = {}


-- Custom function for splitting a string because mw.text.split() is waaay too slow
都会线的线路标识色为#F8A5C3(R=248 G=165 B=195 C=2 M=48 Y=6 K=0)。
local function split( str, pattern, plain )
local res = {}
local continue = true
local startIndex = 1


while continue do
==== 线路数据 ====
local i, j = string.find( str, pattern, startIndex, plain )
if i then
table.insert( res, string.sub( str, startIndex, i-1 ) )
startIndex = j + 1
else
table.insert( res, string.sub( str, startIndex ) )
continue = false
end
end


return res
* 运营里程:
end
* 站数:19
* 轨距:1435mm
* 动力来源:1500V接触网供电
* 最高速度:80km/h
* 地下区间:北堡公园—紫薇路北
* 高架区间:生产路南—闵北商务区


-- Also custom function for speed
== 车站 ==
local function trim( str )
return (string.gsub( str, '^%s+', '' ):gsub( '%s+$', '' ))
end


local function mergeItem( tbl, key, item )
==== 换乘站点 ====
if type( tbl[key] ) == 'table' and type( item ) == 'table' then
for k in pairs( tbl[key] ) do
mergeItem( tbl[key], k, item[k] )
end
elseif type( tbl[key] ) == 'table' then
table.insert( tbl[key], item )
else
tbl[key] = { tbl[key], item }
end
end


local escapeChars = {
* 北堡公园 — 换乘[[星云轨道交通下关线|下关线]],天地换乘
['{'] = '&#123;',
* 枫泽湖 — 换乘[[星云轨道交通星川线|星川线]],节点换乘
['}'] = '&#125;',
* 北京路 — 换乘[[星云轨道交通环线|环线]],通道换乘
['['] = '&#91;',
* 大世界 — 换乘[[星云轨道交通空港线|空港线]],“L”字换乘
[']'] = '&#93;',
* 星天地 — 换乘[[星云轨道交通中央线|中央线]]、[[星云轨道交通星岛线|星岛线]],站厅换乘
['|'] = '&#124;',
* 昆山路 — 换乘[[星云轨道交通港湾线|港湾线]],“T”字换乘
['-'] = '&#8208;'
* 星汇路 — 换乘[[星云轨道交通区域线|区域线]],同站台换乘
}
* 云台路 — 换乘[[星云轨道交通空港线|空港线]],“T”字换乘
local function escape( str )
* 江浦大桥 — 换乘[[星云轨道交通环线|环线]],长通道换乘
return (string.gsub( str, '[{}%[%]|%-]', escapeChars ))
* 红沙坪 — 换乘[[星云轨道交通江北线|江北线]],同站台换乘
end
* 江闵 — 换乘[[星云轨道交通区域线|区域线]],同站台换乘


local unEscapeChars = {
==== 车站列表 ====
['&#123;'] = '{',
{| class="wikitable" style="text-align: center;"
['&#125;'] = '}',
!style="text-align: center; border-bottom: 2px solid #F8A5C3;"|阶段
['&#91;'] = '[',
!style="text-align: center; border-bottom: 2px solid #F8A5C3;"|站名
['&#93;'] = ']',
!style="text-align: center; border-bottom: 2px solid #F8A5C3;"|换乘线路
['&#124;'] = '|',
!style="text-align: center; border-bottom: 2px solid #F8A5C3;"|站台类型
['&#8208;'] = '-'
!style="text-align: center; border-bottom: 2px solid #F8A5C3;"|所在地
}
|-
local function unEscape( str )
| rowspan="5" |二期
return (string.gsub( str, '&#%d+;', unEscapeChars ))
西延
end
|北堡公园
 
|<font color="D80169">█</font> [[星云轨道交通下关线|下关线]]
local function fixCurlyBrackets( str )
|岛式
-- the \226\157\180\181 are used to match ❴ (U+2774) and ❵ (U+2775) wich are 3 bytes long (UTF-8) so
| rowspan="4" |[[下关区]]
-- we can't use them directly inside [] patterns. Ustring would fix this but it's way too slow.
|-
return (string.gsub( str, '\226\157[\180\181]', { ['❴'] = '{', ['❵'] = '}' } ))
|礼泉路
end
|
 
|岛式
local function removeFormattingSettings( query )
|-
local toRemove = {
|浦珠北路
'mode',
|
'table',
|岛式
'tablerow',
|-
'tablesortcol',
|枫泽湖
'headingmode',
|<font color="004A9F"></font> [[星云轨道交通星川线|星川线]]
'headingcount',
|岛式
'listattr',
|-
'itemattr',
|丽岛路
'hlistattr',
|
'hitemattr',
|岛式
'userdateformat',
| rowspan="2" |[[星川区]]
'shownamespace',
|-
'escapelinks',
| rowspan="8" |一期
'titlemaxlength',
|北京路
'replaceintitle',
|<font color="E7CC08"></font> [[星云轨道交通环线|环线]]
'columns',
|岛式
'rows',
|-
'rowsize',
|大世界
'rowcolformat',
|<font color="F79F1F"></font> [[星云轨道交通空港线|空港线]]
'resultsheader',
|岛式
'resultsfooter',
| rowspan="3" |[[星轨区]]
'oneresultheader',
|-
'oneresultfooter',
|星天地
'noresultsheader',
|<font color="45AAF2">█</font> [[星云轨道交通中央线|中央线]] <font color="17C123">█</font> [[星云轨道交通星岛线|星岛线]]
'suppresserrors',
|岛式
'noresultsfooter',
|-
'format',
|昆山路
'groupMultiTemplateResults'
|<font color="E73828">█</font> [[星云轨道交通港湾线|港湾线]]
}
|岛式
 
|-
for _, k in ipairs( toRemove ) do
|星汇路
query[k] = nil
|<font color="9B59B6">█</font> [[星云轨道交通区域线|区域线]]
end
|双岛式
end
| rowspan="4" |[[浦汇区]]
 
|-
local function formatInclude( query )
|云台路
checkTypeForNamedArg( 'Module:DPLlua.ask', 'include', query, 'string' )
|<font color="F79F1F">█</font> [[星云轨道交通空港线|空港线]]
query = split( query, ',', true )
|侧式
local includedParamNames = {}
|-
local sectionAttributes = {}
|江浦大桥
 
|<font color="E7CC08">█</font> [[星云轨道交通环线|环线]]
for i = 1, #query do
|侧式
if query[i]:match( '%b{}' ) then -- Check if we are including a template
|-
local templateName, extra = query[i]:match( '{(.-)[¦|}](.*)' )
|柏景湾
if hasContent( extra ) then
|
local phantomTemplateName = extra:match( '^(.-)}' ) or extra:match( '^[./].+' )
|侧式
local phantomTemplatePrefix = extra:match( '^(.-)}' ) and '' or templateName
|-
local params = extra:gsub( '^.-}', '' ):gsub( '^[./].+', '' ):gsub( ':%-', '' )
| rowspan="6" |二期
local sur = hasContent( phantomTemplateName ) and ('¦' .. phantomTemplatePrefix .. phantomTemplateName) or ''
东延
query[i] = string.format( '{%s%s}%s', templateName, sur, params )
|红沙坪
 
|<font color="5758BB">█</font> [[星云轨道交通江北线|江北线]]
if hasContent( phantomTemplateName ) then
|岛式
table.insert( includedParamNames, { name=phantomTemplatePrefix..phantomTemplateName, isTemplate=true, hasPhantomTemplate=true } )
| rowspan="6" |[[江闵区]]
table.insert( sectionAttributes, { hasPhantomTemplate=true } )
|-
else
|沙东
for param in params:gmatch( ':([^:]*)' ) do
|
param = trim( param )
|岛式
table.insert( includedParamNames, { name=templateName, isTemplate=true, param=param } )
|-
end
|江闵
table.insert( sectionAttributes, { hasPhantomTemplate=false } )
|<font color="9B59B6">█</font> [[星云轨道交通区域线|区域线]]
end
|双岛式
else
|-
query[i] = string.format( '{%s¦DPLlua helper}', templateName ) -- Use a helper template to get all the parameters of our included template
|紫薇路
table.insert( includedParamNames, { name=templateName, isTemplate=true, includeAll=true } )
|
table.insert( sectionAttributes, { hasPhantomTemplate=false } )
|岛式
end
|-
else
|生产路
table.insert( includedParamNames, { name=trim( query[i] ) } )
|
table.insert( sectionAttributes, { hasPhantomTemplate=false } )
|岛式
end
|-
end
|闵北商务区
 
|
return table.concat( query, ',' ), includedParamNames, sectionAttributes
|岛式
end
|}
 
local function formatDpl( query )
local queries = {}
local count = query.count or 500
local offset = query.offset or 0
local usesInclude = false
local includedParamNames = {}
local sectionAttributes
query.count = nil
query.offset = nil
 
-- Use table format so we can place dataContentMarkers around each included parameter. The secseparator
-- is needed to add dataContentMarkers when a phantom template is used
local dplStringInclude =
[=[
{{#dpl:
|noresultsheader=@@
|count=%s
|offset=%s
|%s
|table=,
|listseparators=,\n¦-\n¦[[%%PAGE%%¦]],,
|tablerow=%s
|secseparators=%s
}}]=]
 
-- Table format requires an include statement so we use format instead.
-- This is also a lot faster than adding an empty include statement
local dplStringNoInclude =
[=[
{{#dpl:
|noresultsheader=@@
|count=%s
|offset=%s
|%s
|format=,¦-¦[[%%PAGE%%¦]],,
}}]=]
 
-- Auto generate more than one dpl if count > 500
-- The results of these are later combined
for i = 1, math.ceil( count / 500 ) do
local params = {}
 
for k, v in pairs( query ) do
if k == 'include' then
v, includedParamNames, sectionAttributes = formatInclude( v )
usesInclude =  true
end
 
if type( v ) == 'table' then
for _, x in ipairs( v ) do
table.insert( params, k .. '=' .. tostring( x ):gsub( '|', '¦' ) )
end
else
table.insert( params, k .. '=' .. tostring( v ):gsub( '|', '¦' ) )
end
end
 
if usesInclude then
local secseparators = ''
for _, v in ipairs( sectionAttributes ) do
if v.hasPhantomTemplate then
-- Phantom templates need this because they ignore tablerow formatting
secseparators = secseparators .. '¶¦' .. dataContentMarker .. ',' .. dataContentMarker .. ','
else
secseparators = secseparators .. '¶¦,,'
end
end
 
table.insert( queries, string.format(
dplStringInclude,
count > 500 and 500 or count,
offset,
table.concat( params, '\n|' ),
string.rep( dataContentMarker..'%%'..dataContentMarker..',', #includedParamNames ),
secseparators
) )
else
table.insert( queries, string.format(
dplStringNoInclude,
count > 500 and 500 or count,
offset,
table.concat( params, '\n|' )
) )
end
 
count = count - 500
offset = offset + 500
end
 
table.insert( allIncludedParamNames, includedParamNames )
return table.concat( queries )
end
 
local function toTable( query, groupMultiTemplateResults )
local includedParamNames = table.remove( allIncludedParamNames, 1 )
local usesInclude = #includedParamNames > 0
local res = {}
 
query = query:gsub( '<p>Extension:DynamicPageList .-</p>', function(item) res.error = item; return '' end )
 
if query:find( '^@@' ) then -- @@ is used when no result is found
return res
end
 
if usesInclude then
query = query:gsub( dataContentMarker..'(.-)'..dataContentMarker, escape )
end
 
query = trim( query )
query = split( query, '|-', true ) -- Results of the returned pages are separated by |-
 
for _, v in ipairs( query ) do
if hasContent( v ) and not v:find( '^@@' ) then
v = trim( v )
local title = v:match( '^|%[%[(.-)|' )
local rawDataList = v:match( '^|.-|.-|(.*)' ) -- This is everything after the title
 
if not usesInclude then
if title and title ~= '' then
table.insert( res, title )
end
else
-- When multiple includes are used (e.g. include={Template1},{Template2} or include={Template}:1:2) their results are separated by a pipe
rawDataList = split( rawDataList, '|', true )
local cleanedDataList = {}
 
for _incIndex, dataItem in ipairs( rawDataList ) do
local incIndex = ((_incIndex - 1) % #includedParamNames) + 1 -- Needed in case the same template appears multiple times on the same page
dataItem = unEscape( dataItem )
dataItem = trim( dataItem )
 
if includedParamNames[ incIndex ].isTemplate and includedParamNames[ incIndex ].includeAll then -- Check if we included a full template
-- When we include an entire template we use the %ARGS% parameter supplied by dpl.
-- However all | characters are repaced with §, e.g.:
-- §namelessParam
-- §param = text [[wowee§link text]]
-- §param2 = text {{something§something else}}
dataItem = dataItem:gsub( '\127\'"`UNIQ%-%-nowiki%-%x+%-QINU`"\'\127', function(item) return '<nowiki>' .. item .. '</nowiki>' end )
dataItem = mw.text.unstripNoWiki( dataItem ) -- Unstrip nowiki so we can clean their content
dataItem = fixCurlyBrackets( dataItem ) -- When using the %ARGS% dpl parameter, curly brackets are replaced with ❴ (U+2774) and ❵ (U+2775)
dataItem = dataItem:gsub( '%b{}', function(x) return x:gsub( '§', '|' ) end ) -- Restore pipe characters inside links and templates
dataItem = dataItem:gsub( '%b[]', function(x) return x:gsub( '§', '|' ) end )
dataItem = dataItem:gsub( '<nowiki>(.-)</nowiki>', function(x) return mw.getCurrentFrame():extensionTag( 'nowiki', x ) end ) -- Restrip nowiki
local _dataItem = {}
 
if dataItem ~= '' then
dataItem = split( dataItem:sub( 3 ), '§' ) -- The sub(3) removes the first § at the start. § is 2 bytes wide so start at index 3
 
for i, item in ipairs( dataItem ) do
if item:find( '=' ) then -- Check if the parameter is named or unnamed
local param, value = item:match( '^%s*(.-)%s*=%s*(.-)%s*$' )
_dataItem[ param ] = value
else
table.insert( _dataItem, trim( item ) )
end
end
end
 
dataItem = _dataItem
end
 
local dataListIndex = groupMultiTemplateResults and 1 or math.ceil( _incIndex / #includedParamNames )
if
includedParamNames[ incIndex ].isTemplate and
not includedParamNames[ incIndex ].includeAll and
not includedParamNames[ incIndex ].hasPhantomTemplate
then -- This means there was an include in the form 'include = {template}:param'
local templateName = includedParamNames[ incIndex ].name
local paramName = includedParamNames[ incIndex ].param
paramName = tonumber( paramName ) or paramName -- Keep as string if tonumber fails
cleanedDataList[ dataListIndex ] = cleanedDataList[ dataListIndex ] or {}
cleanedDataList[ dataListIndex ][ templateName ] = cleanedDataList[ dataListIndex ][ templateName ] or {}
if groupMultiTemplateResults and _incIndex > #includedParamNames then
mergeItem( cleanedDataList[ dataListIndex ][ templateName ], paramName, dataItem )
else
cleanedDataList[ dataListIndex ][ templateName ][ paramName ] = dataItem
end
else
local templateName = includedParamNames[ incIndex ].name
cleanedDataList[ dataListIndex ] = cleanedDataList[ dataListIndex ] or {}
if groupMultiTemplateResults and _incIndex > #includedParamNames then
mergeItem( cleanedDataList[ dataListIndex ], templateName, dataItem )
else
cleanedDataList[ dataListIndex ][ templateName ] = dataItem
end
end
end
 
if title and title ~= '' then
for _, v in ipairs( cleanedDataList ) do
table.insert( res, { title=title, include=v } )
end
end
end
end
end
 
return res
end
 
-- Accepts a series of tables each containig the settings for a dpl query.
-- Combinig multiple dpl queries yields better performance than doing them sequentially
function dpl.ask( ... )
local formatTime = os.clock()
local queries = { ... }
local wantsGrouping = {}
 
for i = 1, #queries do
checkType( 'Module:DPLlua.ask', i, queries[i], 'table' )
table.insert( wantsGrouping, queries[i].groupMultiTemplateResults or false )
removeFormattingSettings( queries[i] )
queries[i] = formatDpl( queries[i] )
end
formatTime = os.clock() - formatTime
 
local DPLtime = os.clock()
queries = table.concat( queries, '$@µ@$' )
queries = mw.getCurrentFrame():preprocess( queries )
queries = split( queries, '$@µ@$', true )
DPLtime = os.clock() - DPLtime
 
for i = 1, #queries do
local parseTime = os.clock()
queries[i] = toTable( queries[i], wantsGrouping[i] )
parseTime = os.clock() - parseTime
queries[i]['DPL time'] = DPLtime
queries[i]['Parse time'] = math.floor( (formatTime + parseTime) * 1e5 ) / 1e5 -- os.clock() has a resolution of 10µs
end
 
return unpack( queries )
end
 
-- function dpl.test()
-- local time = os.clock()
 
-- local a, b = dpl.ask({
--    namespace = 'Module',
--    linksto = 'Module:Chart data',
--    distinct = 'strict',
--    ordermethod = 'title',
--    nottitlematch = '%/doc¦%sandbox%¦Exchange/%¦Exchange historical/%¦Chart data',
-- ignorecase = 'true',
-- allowcachedresults = false
-- },{
--    namespace = 'Module',
--    linksto = 'Module:Enum',
--    distinct = 'strict',
--    ordermethod = 'title',
-- nottitlematch = '%/doc¦%sandbox%¦Exchange/%¦Exchange historical/%¦Enum',
--    ignorecase = 'true',
-- allowcachedresults = false
-- })
-- mw.logObject(a)
-- mw.logObject(b)
 
-- local a, b = dpl.ask({
--    namespace = 'Module',
--    linksto = 'Module:Chart data',
--    distinct = 'strict',
--    ordermethod = 'title',
--    nottitlematch = '%/doc¦%sandbox%¦Exchange/%¦Exchange historical/%¦Chart data',
--    ignorecase = 'true',
-- allowcachedresults = false
-- },{
-- namespace = '',
-- ignorecase = 'true',
-- uses = 'Template:Infobox Recipe',
-- count = 50,
-- include = '{Infobox Recipe},{Infobox Item}',
-- allowcachedresults = false
-- })
-- mw.logObject(a)
-- mw.logObject(b)
 
-- local a = dpl.ask{
-- namespace = '',
-- uses = 'Template:Infobox Recipe',
-- include = '{Infobox Recipe}:skill:name,{Infobox Item}:update,{Infobox Item|test}',
-- count = 50,
-- ordermethod = 'title',
-- }
-- mw.logObject(a)
 
-- local q = dpl.ask{
-- uses = "Template:Collections table",
-- category = "Archaeology collections",
-- -- include = "{Infobox collection}:reward,{Collections table}:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15",
-- include = "{Infobox collection}:reward,{Collections table}",
-- count = 100
-- }
-- mw.logObject(q)
-- local q = dpl.ask{
-- namespace = "",
-- uses = "Template:Infobox spell",
-- notcategory = {"Removed content", "Removed spells"},
-- nottitlematch = {"Enchant Crossbow Bolt", "Storm of Armadyl"},
-- include = "{Infobox spell}",
-- }
-- mw.logObject(q)
 
-- local list = dpl.ask{
-- namespace = 'Template',
-- uses = 'Template:Navbox',
-- ordermethod = 'title',
-- include = '{Navbox}:gtitle1:gtitle2',
-- count = 1,
-- offset = 3
-- }
-- mw.logObject(list)
 
-- local list = dpl.ask{
-- namespace = 'User',
-- titlematch = 'CephHunter/Sandbox/test1',
-- include = '{User:CephHunter/Sandbox/test2|User:CephHunter/Sandbox/test3},{User:CephHunter/Sandbox/test3}:1',
-- }
-- mw.logObject(list)
 
-- mw.logObject(dpl.ask{
-- namespace = 'User',
-- ignorecase = 'true',
-- titlematch = 'CephHunter/Sandbox/test1',
-- include = '{User:CephHunter/Sandbox/test2}'
-- })
 
-- mw.logObject(dpl.ask{
-- namespace = 'Module',
-- uses = 'Template:Helper module',
-- titlematch = '%/doc',
-- nottitlematch = 'Exchange/%|Exchange historical/%|Sandbox/%',
-- ordermethod = 'title',
-- include = '{Helper module}, {Helper module}:example',
-- count = 1,
-- offset = 13
-- })
 
-- mw.logObject(dpl.ask{
--        namespace = 'Module',
--        titlematch = 'Chart data|Absorbative calculator',
--        nottitlematch = 'Exchange/%|Exchange historical/%|Sandbox/%|%/doc|DPLlua%',
--        ordermethod = 'title',
--        include = '%0'
-- })
 
-- mw.logObject(dpl.ask{
--        uses = 'Template:Collections table',
--        include = '{Collections table}',
--        count = 5
-- })
 
-- mw.log(os.clock()-time)
-- end
 
return dpl
-- </nowiki>

2024年2月11日 (日) 12:35的版本

MetroMetropolitan.png

未安装站台安全门的星天地站

NebulaeCraft.png星云轨道交通都会线

运营地点 星云市
服务类型 地铁
所属系统 星云轨道交通
目前状况 建设中
起点站 北堡公园
终点站 闵北商务区
英文代号 Metropolitan Line
系统代号 M4线

线路结构 地下、高架
线路长度 12.14km (7.54mi)
最高速度 80千米/小时
正线数目 2条
车站数目 19个
轨距 1,435毫米(准轨)
电气化方式 DC 1,500V 接触网供电
闭塞方式 CBTC移动自动闭塞
信号系统 泰雷兹 TSTCBTC 2.0 (DTO有人值守全自动驾驶/GoA3)
车辆基地 闵北车辆段
使用车型 MPC01
列车编组 6/7节C型列车

开通运营 暂未开通
拥有者 星云轨道交通集团有限公司
运营者 江闵交运集团

星云轨道交通都会线NebulaeCraft的一条地铁线路。是星云第二批开工的轨道交通线路之一。

概览

都会线起于北浦汇,经星天地,最终进入星川区,是星云轨道交通中极其重要的线路之一。

都会线的线路标识色为#F8A5C3(R=248 G=165 B=195 C=2 M=48 Y=6 K=0)。

线路数据

  • 运营里程:
  • 站数:19
  • 轨距:1435mm
  • 动力来源:1500V接触网供电
  • 最高速度:80km/h
  • 地下区间:北堡公园—紫薇路北
  • 高架区间:生产路南—闵北商务区

车站

换乘站点

  • 北堡公园 — 换乘下关线,天地换乘
  • 枫泽湖 — 换乘星川线,节点换乘
  • 北京路 — 换乘环线,通道换乘
  • 大世界 — 换乘空港线,“L”字换乘
  • 星天地 — 换乘中央线星岛线,站厅换乘
  • 昆山路 — 换乘港湾线,“T”字换乘
  • 星汇路 — 换乘区域线,同站台换乘
  • 云台路 — 换乘空港线,“T”字换乘
  • 江浦大桥 — 换乘环线,长通道换乘
  • 红沙坪 — 换乘江北线,同站台换乘
  • 江闵 — 换乘区域线,同站台换乘

车站列表

阶段 站名 换乘线路 站台类型 所在地
二期

西延

北堡公园 下关线 岛式 下关区
礼泉路 岛式
浦珠北路 岛式
枫泽湖 星川线 岛式
丽岛路 岛式 星川区
一期 北京路 环线 岛式
大世界 空港线 岛式 星轨区
星天地 中央线 星岛线 岛式
昆山路 港湾线 岛式
星汇路 区域线 双岛式 浦汇区
云台路 空港线 侧式
江浦大桥 环线 侧式
柏景湾 侧式
二期

东延

红沙坪 江北线 岛式 江闵区
沙东 岛式
江闵 区域线 双岛式
紫薇路 岛式
生产路 岛式
闵北商务区 岛式