Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
陈庄旺
uni-app
提交
7cc0bc56
U
uni-app
项目概览
陈庄旺
/
uni-app
与 Fork 源项目一致
Fork自
DCloud / uni-app
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-app
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
7cc0bc56
编写于
8月 02, 2021
作者:
fxy060608
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
wip(app): nvue
上级
e20aa854
变更
17
隐藏空白更改
内联
并排
Showing
17 changed file
with
171 addition
and
55 deletion
+171
-55
packages/shims-uni-app.d.ts
packages/shims-uni-app.d.ts
+1
-0
packages/uni-app-plus/build.json
packages/uni-app-plus/build.json
+5
-2
packages/uni-app-plus/dist/uni-app-service.es.js
packages/uni-app-plus/dist/uni-app-service.es.js
+50
-8
packages/uni-app-plus/src/service/api/index.ts
packages/uni-app-plus/src/service/api/index.ts
+1
-0
packages/uni-app-plus/src/service/api/plugin/restoreGlobal.ts
...ages/uni-app-plus/src/service/api/plugin/restoreGlobal.ts
+43
-0
packages/uni-app-plus/src/service/framework/page/register.ts
packages/uni-app-plus/src/service/framework/page/register.ts
+2
-0
packages/uni-app-plus/src/service/framework/webview/init/index.ts
.../uni-app-plus/src/service/framework/webview/init/index.ts
+2
-1
packages/uni-app-plus/src/service/framework/webview/style/index.ts
...uni-app-plus/src/service/framework/webview/style/index.ts
+0
-1
packages/uni-cli-shared/src/json/app/manifest/index.ts
packages/uni-cli-shared/src/json/app/manifest/index.ts
+6
-3
packages/uni-cli-shared/src/json/app/manifest/launchwebview.ts
...ges/uni-cli-shared/src/json/app/manifest/launchwebview.ts
+1
-3
packages/uni-cli-shared/src/json/app/manifest/tabBar.ts
packages/uni-cli-shared/src/json/app/manifest/tabBar.ts
+2
-3
packages/uni-cli-shared/src/json/app/pages/code.ts
packages/uni-cli-shared/src/json/app/pages/code.ts
+2
-1
packages/uni-core/src/helpers/hook.ts
packages/uni-core/src/helpers/hook.ts
+6
-5
packages/vite-plugin-uni/src/cli/action.ts
packages/vite-plugin-uni/src/cli/action.ts
+2
-1
packages/vite-plugin-uni/src/cli/build.ts
packages/vite-plugin-uni/src/cli/build.ts
+19
-19
packages/vite-plugin-uni/src/cli/utils.ts
packages/vite-plugin-uni/src/cli/utils.ts
+8
-8
rollup.config.js
rollup.config.js
+21
-0
未找到文件。
packages/shims-uni-app.d.ts
浏览文件 @
7cc0bc56
...
...
@@ -68,6 +68,7 @@ declare namespace UniApp {
autoclose
:
boolean
}
onReady
:
(
fn
:
Function
)
=>
void
serviceReady
:
boolean
}
interface
UniRoute
{
...
...
packages/uni-app-plus/build.json
浏览文件 @
7cc0bc56
...
...
@@ -6,7 +6,7 @@
"output"
:
{
"name"
:
"serviceContext"
,
"format"
:
"iife"
,
"banner"
:
"export function createServiceContext(
Vue,weex, plus,instanceContext){
\n
const setTimeout = instanceContext.setTimeout;
\n
const clearTimeout = instanceContext.clearTimeout;
\n
const setInterval = instanceContext.setInterval;
\n
cons
t clearInterval = instanceContext.clearInterval;
\n
const __uniConfig = instanceContext.__uniConfig;
\n
const __uniRoutes = instanceContext.__uniRoutes;
\n
"
,
"banner"
:
"export function createServiceContext(
weex, plus, instanceContext){
\n
const Vue = instanceContext.Vue;
\n
let setTimeout = instanceContext.setTimeout;
\n
let clearTimeout = instanceContext.clearTimeout;
\n
let setInterval = instanceContext.setInterval;
\n
le
t clearInterval = instanceContext.clearInterval;
\n
const __uniConfig = instanceContext.__uniConfig;
\n
const __uniRoutes = instanceContext.__uniRoutes;
\n
"
,
"footer"
:
"const uni = serviceContext.uni;
\n
const getApp = serviceContext.getApp;
\n
const getCurrentPages = serviceContext.getCurrentPages;
\n
const UniServiceJSBridge = serviceContext.UniServiceJSBridge;
\n
return serviceContext;
\n
}"
,
"globals"
:
{
"vue"
:
"Vue"
...
...
@@ -26,7 +26,10 @@
"__UNI_FEATURE_I18N_ZH_HANS__"
:
"true"
,
"__UNI_FEATURE_I18N_ZH_HANT__"
:
"true"
},
"external"
:
[
"vue"
]
"external"
:
[
"vue"
],
"replaceAfterBundled"
:
{
"__VUE__"
:
"vue"
}
},
{
"input"
:
{
...
...
packages/uni-app-plus/dist/uni-app-service.es.js
浏览文件 @
7cc0bc56
export function createServiceContext(Vue,weex, plus,instanceContext){
const setTimeout = instanceContext.setTimeout;
const clearTimeout = instanceContext.clearTimeout;
const setInterval = instanceContext.setInterval;
const clearInterval = instanceContext.clearInterval;
export function createServiceContext(weex, plus, instanceContext){
const Vue = instanceContext.Vue;
let setTimeout = instanceContext.setTimeout;
let clearTimeout = instanceContext.clearTimeout;
let setInterval = instanceContext.setInterval;
let clearInterval = instanceContext.clearInterval;
const __uniConfig = instanceContext.__uniConfig;
const __uniRoutes = instanceContext.__uniRoutes;
...
...
@@ -1867,8 +1868,12 @@ var serviceContext = (function (vue) {
return;
}
// 兼容 nvue
const hooks = (vm._$weex ? vm.$options : vm.$)[name]
;
{
if (vm.__call_hook) {
return vm.__call_hook(name, args);
}
}
const hooks = vm.$[name];
return hooks && invokeArrayFns(hooks, args);
}
...
...
@@ -9511,6 +9516,9 @@ var serviceContext = (function (vue) {
let lastStatusBarStyle;
let oldSetStatusBarStyle = plus.navigator.setStatusBarStyle;
function restoreOldSetStatusBarStyle(setStatusBarStyle) {
oldSetStatusBarStyle = setStatusBarStyle;
}
function newSetStatusBarStyle(style) {
lastStatusBarStyle = style;
oldSetStatusBarStyle(style);
...
...
@@ -9694,7 +9702,8 @@ var serviceContext = (function (vue) {
function initWebview(webview, path, query, routeMeta) {
// 首页或非 nvue 页面
if (webview.id === '1' || !routeMeta.isNVue) {
initWebviewStyle(webview, path, query, routeMeta);
// path 必须参数为空,因为首页已经在 manifest.json 中设置了 uniNView,不能再次设置,否则会二次加载
initWebviewStyle(webview, '', query, routeMeta);
}
initWebviewEvent(webview);
}
...
...
@@ -10103,6 +10112,36 @@ var serviceContext = (function (vue) {
};
}
function restoreGlobal(newVue, newWeex, newPlus, newSetTimeout, newClearTimeout, newSetInterval, newClearInterval) {
// 确保部分全局变量 是 app-service 中的
// 若首页 nvue 初始化比 app-service 快,导致框架处于该 nvue 环境下
// plus 如果不用 app-service,资源路径会出问题
// 若首页 nvue 被销毁,如 redirectTo 或 reLaunch,则这些全局功能会损坏
// 设置 vue3
// @ts-ignore 最终vue会被替换为vue
vue = newVue;
if (plus !== newPlus) {
if ((process.env.NODE_ENV !== 'production')) {
console.log(`[restoreGlobal][${Date.now()}]`);
}
weex = newWeex;
// @ts-ignore
plus = newPlus;
restoreOldSetStatusBarStyle(plus.navigator.setStatusBarStyle);
plus.navigator.setStatusBarStyle = newSetStatusBarStyle;
/* eslint-disable no-window-assign */
// @ts-ignore
setTimeout = newSetTimeout;
// @ts-ignore
clearTimeout = newClearTimeout;
// @ts-ignore
setInterval = newSetInterval;
// @ts-ignore
clearInterval = newClearInterval;
}
__uniConfig.serviceReady = true;
}
const EventType = {
load: 'load',
close: 'close',
...
...
@@ -10947,6 +10986,8 @@ var serviceContext = (function (vue) {
return {
$: {},
onNVuePageCreated(vm, curNVuePage) {
vm.$ = {}; // 补充一个 nvue 的 $ 对象,模拟 vue3 的,不然有部分地方访问了 $
vm.$getAppWebview = () => webview;
// 替换真实的 nvue 的 vm
initPageVm(vm, pageInstance);
const pages = getAllPages();
...
...
@@ -11361,6 +11402,7 @@ var serviceContext = (function (vue) {
shareWithSystem: shareWithSystem,
requestPayment: requestPayment,
__vuePlugin: index$1,
restoreGlobal: restoreGlobal,
createRewardedVideoAd: createRewardedVideoAd,
createFullScreenVideoAd: createFullScreenVideoAd,
createInterstitialAd: createInterstitialAd,
...
...
packages/uni-app-plus/src/service/api/index.ts
浏览文件 @
7cc0bc56
...
...
@@ -56,6 +56,7 @@ export * from './plugin/registerRuntime'
export
*
from
'
./plugin/share
'
export
*
from
'
./plugin/requestPayment
'
export
*
from
'
./plugin/vuePlugin
'
export
*
from
'
./plugin/restoreGlobal
'
export
*
from
'
./ad/rewardedVideoAd
'
export
*
from
'
./ad/fullScreenVideoAd
'
...
...
packages/uni-app-plus/src/service/api/plugin/restoreGlobal.ts
0 → 100644
浏览文件 @
7cc0bc56
import
{
newSetStatusBarStyle
,
restoreOldSetStatusBarStyle
,
}
from
'
../../statusBar
'
export
function
restoreGlobal
(
newVue
:
unknown
,
newWeex
:
unknown
,
newPlus
:
unknown
,
newSetTimeout
:
unknown
,
newClearTimeout
:
unknown
,
newSetInterval
:
unknown
,
newClearInterval
:
unknown
)
{
// 确保部分全局变量 是 app-service 中的
// 若首页 nvue 初始化比 app-service 快,导致框架处于该 nvue 环境下
// plus 如果不用 app-service,资源路径会出问题
// 若首页 nvue 被销毁,如 redirectTo 或 reLaunch,则这些全局功能会损坏
// 设置 vue3
// @ts-ignore 最终__VUE__会被替换为vue
__VUE__
=
newVue
if
(
plus
!==
newPlus
)
{
if
(
__DEV__
)
{
console
.
log
(
`[restoreGlobal][
${
Date
.
now
()}
]`
)
}
weex
=
newWeex
// @ts-ignore
plus
=
newPlus
restoreOldSetStatusBarStyle
(
plus
.
navigator
.
setStatusBarStyle
)
plus
.
navigator
.
setStatusBarStyle
=
newSetStatusBarStyle
/* eslint-disable no-global-assign */
// @ts-ignore
setTimeout
=
newSetTimeout
// @ts-ignore
clearTimeout
=
newClearTimeout
// @ts-ignore
setInterval
=
newSetInterval
// @ts-ignore
clearInterval
=
newClearInterval
}
__uniConfig
.
serviceReady
=
true
}
packages/uni-app-plus/src/service/framework/page/register.ts
浏览文件 @
7cc0bc56
...
...
@@ -163,6 +163,8 @@ function createNVueVm(
return
{
$
:
{},
// navigateBack 时,invokeHook 会调用 $
onNVuePageCreated
(
vm
:
ComponentPublicInstance
,
curNVuePage
:
unknown
)
{
;(
vm
as
any
).
$
=
{}
// 补充一个 nvue 的 $ 对象,模拟 vue3 的,不然有部分地方访问了 $
vm
.
$getAppWebview
=
()
=>
webview
// 替换真实的 nvue 的 vm
initPageVm
(
vm
,
pageInstance
)
const
pages
=
getAllPages
()
...
...
packages/uni-app-plus/src/service/framework/webview/init/index.ts
浏览文件 @
7cc0bc56
...
...
@@ -10,7 +10,8 @@ export function initWebview(
)
{
// 首页或非 nvue 页面
if
(
webview
.
id
===
'
1
'
||
!
routeMeta
.
isNVue
)
{
initWebviewStyle
(
webview
,
path
,
query
,
routeMeta
)
// path 必须参数为空,因为首页已经在 manifest.json 中设置了 uniNView,不能再次设置,否则会二次加载
initWebviewStyle
(
webview
,
''
,
query
,
routeMeta
)
}
initSubNVues
(
webview
,
path
,
routeMeta
)
initWebviewEvent
(
webview
)
...
...
packages/uni-app-plus/src/service/framework/webview/style/index.ts
浏览文件 @
7cc0bc56
...
...
@@ -23,7 +23,6 @@ export function parseWebviewStyle(
routeMeta
[
name
as
keyof
UniApp
.
PageRouteMeta
]
}
})
initNVue
(
webviewStyle
,
routeMeta
,
path
)
initPopGesture
(
webviewStyle
,
routeMeta
)
initBackgroundColor
(
webviewStyle
,
routeMeta
)
...
...
packages/uni-cli-shared/src/json/app/manifest/index.ts
浏览文件 @
7cc0bc56
...
...
@@ -19,7 +19,6 @@ export function normalizeAppManifestJson(
initAppStatusbar
(
initDefaultManifestJson
(),
pagesJson
),
userManifestJson
)
initArguments
(
manifestJson
,
pagesJson
)
initPlus
(
manifestJson
,
pagesJson
)
initNVue
(
manifestJson
,
pagesJson
)
...
...
@@ -27,8 +26,12 @@ export function normalizeAppManifestJson(
initSplashscreen
(
manifestJson
,
userManifestJson
)
initConfusion
(
manifestJson
)
initUniApp
(
manifestJson
)
initLaunchwebview
(
manifestJson
,
pagesJson
)
// 依赖 initArguments 先执行
initTabBar
(
manifestJson
,
pagesJson
)
// 依赖 initLaunchwebview 先执行
// 依赖 initArguments 先执行
initTabBar
(
initLaunchwebview
(
manifestJson
,
pagesJson
),
manifestJson
,
pagesJson
)
return
manifestJson
}
...
...
packages/uni-cli-shared/src/json/app/manifest/launchwebview.ts
浏览文件 @
7cc0bc56
...
...
@@ -13,8 +13,6 @@ export function initLaunchwebview(
}
}
catch
(
e
)
{}
}
// 标记入口页,方便后边的 initTabBar 使用
process
.
env
.
UNI_ENTRY_PAGE_PATH
=
entryPagePath
manifestJson
.
plus
.
useragent
.
value
=
'
uni-app
'
extend
(
manifestJson
.
plus
.
launchwebview
,
{
...
...
@@ -26,8 +24,8 @@ export function initLaunchwebview(
const
entryPage
=
pagesJson
.
pages
.
find
((
p
)
=>
p
.
path
===
entryPagePath
)
if
(
entryPage
?.
style
.
isNVue
)
{
manifestJson
.
plus
.
launchwebview
.
uniNView
=
{
path
:
entryPagePath
+
'
.js
'
}
manifestJson
.
plus
.
launchwebview
.
id
=
'
2
'
}
else
{
manifestJson
.
launch_path
=
'
__uniappview.html
'
}
return
entryPagePath
}
packages/uni-cli-shared/src/json/app/manifest/tabBar.ts
浏览文件 @
7cc0bc56
...
...
@@ -3,6 +3,7 @@ import { SELECTED_COLOR, TABBAR_HEIGHT } from '@dcloudio/uni-shared'
const
TABBAR_WHITE
=
'
rgba(255,255,255,0.4)
'
const
TABBAR_BLACK
=
'
rgba(0,0,0,0.4)
'
export
function
initTabBar
(
entryPagePath
:
string
,
manifestJson
:
Record
<
string
,
any
>
,
pagesJson
:
UniApp
.
PagesJson
)
{
...
...
@@ -23,9 +24,7 @@ export function initTabBar(
tabBar
.
height
=
`
${
parseFloat
(
tabBar
.
height
!
)
||
TABBAR_HEIGHT
}
px`
// 首页是 tabBar 页面
const
item
=
tabBar
.
list
.
find
(
(
page
)
=>
page
.
pagePath
===
process
.
env
.
UNI_ENTRY_PAGE_PATH
)
const
item
=
tabBar
.
list
.
find
((
page
)
=>
page
.
pagePath
===
entryPagePath
)
if
(
item
)
{
;(
tabBar
as
any
).
child
=
[
'
lauchwebview
'
]
;(
tabBar
as
any
).
selected
=
tabBar
.
list
.
indexOf
(
item
)
...
...
packages/uni-cli-shared/src/json/app/pages/code.ts
浏览文件 @
7cc0bc56
...
...
@@ -12,8 +12,9 @@ if (typeof Promise !== 'undefined' && !Promise.prototype.finally) {
}
`
export
const
restoreGlobalCode
=
`
import * as vue from 'vue'
if(uni.restoreGlobal){
uni.restoreGlobal(weex,plus,setTimeout,clearTimeout,setInterval,clearInterval)
uni.restoreGlobal(
vue,
weex,plus,setTimeout,clearTimeout,setInterval,clearInterval)
}
`
...
...
packages/uni-core/src/helpers/hook.ts
浏览文件 @
7cc0bc56
...
...
@@ -31,11 +31,12 @@ export function invokeHook(
return
}
// 兼容 nvue
const
hooks
=
__PLATFORM__
===
'
app
'
?
((
vm
as
any
).
_$weex
?
vm
.
$options
:
vm
.
$
)[
name
as
string
]
:
vm
.
$
[
name
as
string
]
if
(
__PLATFORM__
===
'
app
'
)
{
if
((
vm
as
any
).
__call_hook
)
{
return
(
vm
as
any
).
__call_hook
(
name
,
args
)
}
}
const
hooks
=
vm
.
$
[
name
as
string
]
return
hooks
&&
invokeArrayFns
(
hooks
,
args
)
}
...
...
packages/vite-plugin-uni/src/cli/action.ts
浏览文件 @
7cc0bc56
...
...
@@ -7,12 +7,13 @@ import { createServer, createSSRServer } from './server'
import
{
initEnv
}
from
'
./utils
'
export
async
function
runDev
(
options
:
CliOptions
&
ServerOptions
)
{
extend
(
options
,
{
watch
:
true
,
minify
:
false
})
initEnv
(
'
dev
'
,
options
)
try
{
if
(
options
.
platform
===
'
h5
'
)
{
await
(
options
.
ssr
?
createSSRServer
(
options
)
:
createServer
(
options
))
}
else
{
await
build
(
extend
(
options
,
{
watch
:
true
})
)
await
build
(
options
)
}
if
(
options
.
platform
===
'
app
'
)
{
await
runNVue
(
'
dev
'
)
...
...
packages/vite-plugin-uni/src/cli/build.ts
浏览文件 @
7cc0bc56
import
fs
from
'
fs-extra
'
import
path
from
'
path
'
import
{
build
as
buildByVite
,
BuildOptions
}
from
'
vite
'
import
{
build
as
buildByVite
,
BuildOptions
,
InlineConfig
}
from
'
vite
'
import
{
CliOptions
}
from
'
.
'
import
{
addConfigFile
,
cleanOptions
}
from
'
./utils
'
export
async
function
build
(
options
:
CliOptions
)
{
await
buildByVite
(
addConfigFile
({
root
:
process
.
env
.
VITE_ROOT_DIR
,
logLevel
:
options
.
logLevel
,
clearScreen
:
options
.
clearScreen
,
build
:
cleanOptions
(
options
)
as
BuildOptions
,
})
addConfigFile
(
initBuildOptions
(
options
,
cleanOptions
(
options
)
as
BuildOptions
)
)
)
}
...
...
@@ -24,12 +21,7 @@ export async function buildSSR(options: CliOptions) {
ssrBuildClientOptions
.
outDir
=
process
.
env
.
UNI_OUTPUT_DIR
process
.
env
.
UNI_SSR_CLIENT
=
'
true
'
await
buildByVite
(
addConfigFile
({
root
:
process
.
env
.
VITE_ROOT_DIR
,
logLevel
:
options
.
logLevel
,
clearScreen
:
options
.
clearScreen
,
build
:
ssrBuildClientOptions
,
})
addConfigFile
(
initBuildOptions
(
options
,
ssrBuildClientOptions
))
)
const
ssrServerDir
=
path
.
resolve
(
outputDir
,
'
server
'
)
process
.
env
.
UNI_OUTPUT_DIR
=
ssrServerDir
...
...
@@ -54,12 +46,7 @@ export async function buildSSR(options: CliOptions) {
process
.
env
.
UNI_SSR_CLIENT
=
''
process
.
env
.
UNI_SSR_SERVER
=
'
true
'
await
buildByVite
(
addConfigFile
({
root
:
process
.
env
.
VITE_ROOT_DIR
,
logLevel
:
options
.
logLevel
,
clearScreen
:
options
.
clearScreen
,
build
:
ssrBuildServerOptions
,
})
addConfigFile
(
initBuildOptions
(
options
,
ssrBuildServerOptions
))
)
// copy ssr-manfiest.json to server
const
assets
=
[
'
ssr-manifest.json
'
,
'
index.html
'
]
...
...
@@ -70,3 +57,16 @@ export async function buildSSR(options: CliOptions) {
}
})
}
function
initBuildOptions
(
options
:
CliOptions
,
build
:
BuildOptions
):
InlineConfig
{
return
{
root
:
process
.
env
.
VITE_ROOT_DIR
,
logLevel
:
options
.
logLevel
,
clearScreen
:
options
.
clearScreen
,
mode
:
process
.
env
.
NODE_ENV
,
build
,
}
}
packages/vite-plugin-uni/src/cli/utils.ts
浏览文件 @
7cc0bc56
...
...
@@ -75,14 +75,14 @@ export function initEnv(type: 'dev' | 'build', options: CliOptions) {
process
.
env
.
UNI_OUTPUT_DIR
=
(
options
as
BuildOptions
).
outDir
!
}
// tips
if
(
isInHBuilderX
()
&&
options
.
platform
===
'
app
'
)
{
return
(
console
.
error
(
`当前项目 Vue 版本为3,暂不支持编译至 App 端,近期将升级支持。`
),
process
.
exit
(
1
)
)
}
//
if (isInHBuilderX() && options.platform === 'app') {
//
return (
//
console.error(
//
`当前项目 Vue 版本为3,暂不支持编译至 App 端,近期将升级支持。`
//
),
//
process.exit(1)
//
)
//
}
if
(
process
.
env
.
UNI_PLATFORM
===
'
app
'
)
{
initNVueEnv
()
}
...
...
rollup.config.js
浏览文件 @
7cc0bc56
...
...
@@ -132,6 +132,27 @@ function createConfig(entryFile, output, buildOption) {
})
)
}
if
(
buildOption
.
replaceAfterBundled
)
{
const
replacements
=
buildOption
.
replaceAfterBundled
plugins
.
push
({
name
:
'
replace-after-bundled
'
,
generateBundle
(
_options
,
bundles
)
{
Object
.
keys
(
bundles
).
forEach
((
name
)
=>
{
const
bundle
=
bundles
[
name
]
if
(
!
bundle
.
code
)
{
return
}
Object
.
keys
(
replacements
).
forEach
((
replacement
)
=>
{
bundle
.
code
=
bundle
.
code
.
replace
(
new
RegExp
(
replacement
,
'
g
'
),
replacements
[
replacement
]
)
})
})
},
})
}
return
{
input
:
resolve
(
entryFile
),
external
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录