提交 199f7e66 编写于 作者: fxy060608's avatar fxy060608

fix(nvue): easycom

上级 ebe593bf
......@@ -10,79 +10,79 @@ const __uniRoutes = instanceContext.__uniRoutes;
var serviceContext = (function (vue) {
'use strict';
/*
* base64-arraybuffer
* https://github.com/niklasvh/base64-arraybuffer
*
* Copyright (c) 2012 Niklas von Hertzen
* Licensed under the MIT license.
*/
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
// Use a lookup table to find the index.
var lookup = /*#__PURE__*/ (function () {
const lookup = new Uint8Array(256);
for (var i = 0; i < chars.length; i++) {
lookup[chars.charCodeAt(i)] = i;
}
return lookup
})();
function encode$3(arraybuffer) {
var bytes = new Uint8Array(arraybuffer),
i,
len = bytes.length,
base64 = '';
for (i = 0; i < len; i += 3) {
base64 += chars[bytes[i] >> 2];
base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
base64 += chars[bytes[i + 2] & 63];
}
if (len % 3 === 2) {
base64 = base64.substring(0, base64.length - 1) + '=';
} else if (len % 3 === 1) {
base64 = base64.substring(0, base64.length - 2) + '==';
}
return base64
}
function decode$1(base64) {
var bufferLength = base64.length * 0.75,
len = base64.length,
i,
p = 0,
encoded1,
encoded2,
encoded3,
encoded4;
if (base64[base64.length - 1] === '=') {
bufferLength--;
if (base64[base64.length - 2] === '=') {
bufferLength--;
}
}
var arraybuffer = new ArrayBuffer(bufferLength),
bytes = new Uint8Array(arraybuffer);
for (i = 0; i < len; i += 4) {
encoded1 = lookup[base64.charCodeAt(i)];
encoded2 = lookup[base64.charCodeAt(i + 1)];
encoded3 = lookup[base64.charCodeAt(i + 2)];
encoded4 = lookup[base64.charCodeAt(i + 3)];
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
}
return arraybuffer
/*
* base64-arraybuffer
* https://github.com/niklasvh/base64-arraybuffer
*
* Copyright (c) 2012 Niklas von Hertzen
* Licensed under the MIT license.
*/
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
// Use a lookup table to find the index.
var lookup = /*#__PURE__*/ (function () {
const lookup = new Uint8Array(256);
for (var i = 0; i < chars.length; i++) {
lookup[chars.charCodeAt(i)] = i;
}
return lookup
})();
function encode$3(arraybuffer) {
var bytes = new Uint8Array(arraybuffer),
i,
len = bytes.length,
base64 = '';
for (i = 0; i < len; i += 3) {
base64 += chars[bytes[i] >> 2];
base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
base64 += chars[bytes[i + 2] & 63];
}
if (len % 3 === 2) {
base64 = base64.substring(0, base64.length - 1) + '=';
} else if (len % 3 === 1) {
base64 = base64.substring(0, base64.length - 2) + '==';
}
return base64
}
function decode$1(base64) {
var bufferLength = base64.length * 0.75,
len = base64.length,
i,
p = 0,
encoded1,
encoded2,
encoded3,
encoded4;
if (base64[base64.length - 1] === '=') {
bufferLength--;
if (base64[base64.length - 2] === '=') {
bufferLength--;
}
}
var arraybuffer = new ArrayBuffer(bufferLength),
bytes = new Uint8Array(arraybuffer);
for (i = 0; i < len; i += 4) {
encoded1 = lookup[base64.charCodeAt(i)];
encoded2 = lookup[base64.charCodeAt(i + 1)];
encoded3 = lookup[base64.charCodeAt(i + 2)];
encoded4 = lookup[base64.charCodeAt(i + 3)];
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63);
}
return arraybuffer
}
/**
......@@ -3628,14 +3628,14 @@ var serviceContext = (function (vue) {
});
// let eventReady = false
let index$2 = 0;
let index$3 = 0;
let optionsCache = {};
function operateEditor(componentId, pageId, type, options) {
const data = { options };
const needCallOptions = options &&
('success' in options || 'fail' in options || 'complete' in options);
if (needCallOptions) {
const callbackId = String(index$2++);
const callbackId = String(index$3++);
data.callbackId = callbackId;
optionsCache[callbackId] = options;
}
......@@ -4138,6 +4138,10 @@ var serviceContext = (function (vue) {
};
const API_STOP_BEACON_DISCOVERY = 'stopBeaconDiscovery';
const API_GET_SCREEN_BRIGHTNESS = 'getScreenBrightness';
const API_SET_SCREEN_BRIGHTNESS = 'setScreenBrightness';
const API_SET_KEEP_SCREEN_ON = 'setKeepScreenOn';
const API_CHECK_IS_SUPPORT_SOTER_AUTHENTICATION = 'soterAuthentication';
const API_CHECK_IS_SOTER_ENROLLED_IN_DEVICE = 'checkIsSoterEnrolledInDevice';
const CheckAuthModes = [
......@@ -4222,6 +4226,21 @@ var serviceContext = (function (vue) {
const RemoveStorageProtocol = GetStorageProtocol;
const RemoveStorageSyncProtocol = GetStorageSyncProtocol;
const API_SAVE_FILE = 'saveFile';
const SaveFileOptions = {
formatArgs: {
tempFilePath(savedFilePath, params) {
params.tempFilePath = getRealPath(savedFilePath);
},
},
};
const SaveFileProtocol = {
tempFilePath: {
type: String,
required: true,
},
};
const API_GET_FILE_INFO = 'getFileInfo';
const GetFileInfoOptions = {
formatArgs: {
......@@ -5573,6 +5592,45 @@ var serviceContext = (function (vue) {
});
}, OpenDocumentProtocol, OpenDocumentOptions);
function getFileName(path) {
const array = path.split('/');
return array[array.length - 1];
}
function getExtName(path) {
const array = path.split('.');
return array.length > 1 ? '.' + array[array.length - 1] : '';
}
let index$2 = 0;
const SAVED_DIR = 'uniapp_save';
const SAVE_PATH = `_doc/${SAVED_DIR}`;
function getSavedFileDir(success, fail) {
fail = fail || function () { };
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, (fs) => {
// 请求_doc fs
fs.root.getDirectory(SAVED_DIR, {
// 获取文件保存目录对象
create: true,
}, success, fail);
}, fail);
}
const saveFile = defineAsyncApi(API_SAVE_FILE, ({ tempFilePath }, { resolve, reject }) => {
const errorCallback = warpPlusErrorCallback(reject);
const fileName = `${Date.now()}${index$2++}${getExtName(tempFilePath)}`;
plus.io.resolveLocalFileSystemURL(tempFilePath, (entry) => {
// 读取临时文件 FileEntry
getSavedFileDir((dir) => {
entry.copyTo(dir, fileName, () => {
// 复制临时文件 FileEntry,为了避免把相册里的文件删除,使用 copy,微信中是要删除临时文件的
const savedFilePath = SAVE_PATH + '/' + fileName;
resolve({
savedFilePath,
});
}, errorCallback);
}, errorCallback);
}, errorCallback);
}, SaveFileProtocol, SaveFileOptions);
const isIOS = plus.os.name === 'iOS';
let config;
/**
......@@ -6687,6 +6745,19 @@ var serviceContext = (function (vue) {
});
});
const getScreenBrightness = defineAsyncApi(API_GET_SCREEN_BRIGHTNESS, (_, { resolve }) => {
const value = plus.screen.getBrightness(false);
resolve({ value });
});
const setScreenBrightness = defineAsyncApi(API_SET_SCREEN_BRIGHTNESS, (options, { resolve }) => {
plus.screen.setBrightness(options.value, false);
resolve();
});
const setKeepScreenOn = defineAsyncApi(API_SET_KEEP_SCREEN_ON, (options, { resolve }) => {
plus.device.setWakelock(!!options.keepScreenOn);
resolve();
});
const getImageInfo = defineAsyncApi(API_GET_IMAGE_INFO, (options, { resolve, reject }) => {
const path = TEMP_PATH + '/download/';
plus.io.getImageInfo(extend(options, {
......@@ -6895,11 +6966,6 @@ var serviceContext = (function (vue) {
plus.gallery.save(options.filePath, warpPlusSuccessCallback(resolve), warpPlusErrorCallback(reject));
}, SaveImageToPhotosAlbumProtocol, SaveImageToPhotosAlbumOptions);
function getFileName(path) {
const array = path.split('/');
return array[array.length - 1];
}
const compressImage$1 = defineAsyncApi(API_COMPRESS_IMAGE, (options, { resolve, reject }) => {
const dst = `${TEMP_PATH}/compressed/${Date.now()}_${getFileName(options.src)}`;
plus.zip.compressImage(extend({}, options, {
......@@ -11508,6 +11574,7 @@ var serviceContext = (function (vue) {
getStorageInfo: getStorageInfo,
getFileInfo: getFileInfo$1,
openDocument: openDocument,
saveFile: saveFile,
getSystemInfoSync: getSystemInfoSync,
getSystemInfo: getSystemInfo,
onCompassChange: onCompassChange,
......@@ -11557,6 +11624,9 @@ var serviceContext = (function (vue) {
startSoterAuthentication: startSoterAuthentication,
scanCode: scanCode,
onThemeChange: onThemeChange,
getScreenBrightness: getScreenBrightness,
setScreenBrightness: setScreenBrightness,
setKeepScreenOn: setKeepScreenOn,
getImageInfo: getImageInfo,
getVideoInfo: getVideoInfo,
previewImage: previewImage,
......
......@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.uniOptions = void 0;
const uni_shared_1 = require("@dcloudio/uni-shared");
exports.uniOptions = {
copyOptions: { assets: ['hybrid/html'] },
compilerOptions: {
isNativeTag: uni_shared_1.isServiceNativeTag,
isCustomElement: uni_shared_1.isServiceCustomElement,
......
......@@ -5,6 +5,7 @@ import {
import { UniVitePlugin } from '@dcloudio/uni-cli-shared'
export const uniOptions: UniVitePlugin['uni'] = {
copyOptions: { assets: ['hybrid/html'] },
compilerOptions: {
isNativeTag: isServiceNativeTag,
isCustomElement: isServiceCustomElement,
......
......@@ -2,10 +2,29 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.createEasycomModule = void 0;
const uni_shared_1 = require("@dcloudio/uni-shared");
const BUILT_IN_COMPONENTS = [
'App',
'block',
'component',
'transition',
'transition-group',
'keep-alive',
'slot',
'teleport',
];
function isComponent(tagName) {
if (BUILT_IN_COMPONENTS.includes(tagName)) {
return false;
}
if (uni_shared_1.isBuiltInComponent(tagName)) {
return false;
}
return true;
}
function createEasycomModule() {
return {
preTransformNode(el, options) {
if (uni_shared_1.isBuiltInComponent(el.tag) && el.tag !== 'App') {
if (isComponent(el.tag)) {
// 挂在 isUnaryTag 上边,可以保证外部访问到
;
(options.isUnaryTag.autoComponents ||
......
......@@ -166,8 +166,8 @@ var component = normalizer(
${hasFunctional ? `true` : `false`},
${`null`/* fixed by xxxxxx */},
${hasScoped ? JSON.stringify(id) : `null`},
${isServer ? JSON.stringify(hash(request)) : `null`}
${isShadow ? `,true` : ``},
${isServer ? JSON.stringify(hash(request)) : `null`},
${isShadow ? `,true` : `false`},
components
)
`.trim() + `\n`
......
......@@ -12,13 +12,26 @@ export default function normalizeComponent (
injectStyles,
scopeId,
moduleIdentifier, /* server only */
shadowMode /* vue-cli only */
shadowMode, /* vue-cli only */
components, // fixed by xxxxxx auto components
) {
// Vue.extend constructor export interop
var options = typeof scriptExports === 'function'
? scriptExports.options
: scriptExports
// fixed by xxxxxx auto components
if (components) {
if (!options.components) {
options.components = {}
}
var hasOwn = Object.prototype.hasOwnProperty
for (var name in components) {
if (hasOwn.call(components, name) && !hasOwn.call(options.components, name)) {
options.components[name] = components[name]
}
}
}
// render functions
if (render) {
options.render = render
......
import { ASTElement, ModuleOptions } from 'vue-template-compiler'
import { isBuiltInComponent } from '@dcloudio/uni-shared'
const BUILT_IN_COMPONENTS = [
'App',
'block',
'component',
'transition',
'transition-group',
'keep-alive',
'slot',
'teleport',
]
function isComponent(tagName: string) {
if (BUILT_IN_COMPONENTS.includes(tagName)) {
return false
}
if (isBuiltInComponent(tagName)) {
return false
}
return true
}
export function createEasycomModule() {
return {
preTransformNode(el: ASTElement, options: any) {
if (isBuiltInComponent(el.tag) && el.tag !== 'App') {
if (isComponent(el.tag)) {
// 挂在 isUnaryTag 上边,可以保证外部访问到
;(
options.isUnaryTag.autoComponents ||
......
import { Plugin } from 'vite'
import { ParserOptions } from '@vue/compiler-core'
import { CompilerOptions } from '@vue/compiler-sfc'
import type { Plugin } from 'vite'
import type { ParserOptions } from '@vue/compiler-core'
import type { CompilerOptions } from '@vue/compiler-sfc'
import type { Target } from 'rollup-plugin-copy'
interface CopyOptions {
/**
* 静态资源,配置的目录,在 uni_modules 中同样支持
*/
assets?: string[]
targets?: readonly Target[]
}
export interface UniVitePlugin extends Plugin {
uni?: {
compilerOptions?: {
......@@ -9,6 +17,7 @@ export interface UniVitePlugin extends Plugin {
directiveTransforms?: CompilerOptions['directiveTransforms']
}
transformEvent?: Record<string, string>
copyOptions?: CopyOptions | (() => CopyOptions)
}
}
......
......@@ -21,6 +21,9 @@ const transformIndexHtml_1 = require("./transformIndexHtml");
const UniH5Plugin = {
name: 'vite:uni-h5',
uni: {
copyOptions: {
assets: ['hybrid/html'],
},
transformEvent: {
tap: 'click',
},
......
......@@ -18,6 +18,9 @@ import { createTransformIndexHtml } from './transformIndexHtml'
const UniH5Plugin: UniVitePlugin = {
name: 'vite:uni-h5',
uni: {
copyOptions: {
assets: ['hybrid/html'],
},
transformEvent: {
tap: 'click',
},
......
......@@ -786,7 +786,7 @@ var safeAreaInsets = {
onChange,
offChange
};
var D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out = safeAreaInsets;
var out = safeAreaInsets;
const onEventPrevent = /* @__PURE__ */ withModifiers(() => {
}, ["prevent"]);
const onEventStop = /* @__PURE__ */ withModifiers(() => {
......@@ -798,10 +798,10 @@ function getWindowOffset() {
const left = parseInt(style.getPropertyValue("--window-left"));
const right = parseInt(style.getPropertyValue("--window-right"));
return {
top: top ? top + D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.top : 0,
bottom: bottom ? bottom + D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.bottom : 0,
left: left ? left + D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.left : 0,
right: right ? right + D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.right : 0
top: top ? top + out.top : 0,
bottom: bottom ? bottom + out.bottom : 0,
left: left ? left + out.left : 0,
right: right ? right + out.right : 0
};
}
function updateCssVar(cssVars) {
......@@ -13347,7 +13347,7 @@ function normalizePageMeta(pageMeta) {
}, pageMeta.pullToRefresh));
const { type, style } = navigationBar;
if (style !== "custom" && type !== "transparent") {
pullToRefresh.offset += NAVBAR_HEIGHT + D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.top;
pullToRefresh.offset += NAVBAR_HEIGHT + out.top;
}
pageMeta.pullToRefresh = pullToRefresh;
}
......@@ -15545,7 +15545,7 @@ const getSystemInfoSync = /* @__PURE__ */ defineSyncApi("getSystemInfoSync", ()
const windowWidth = getWindowWidth(screenWidth);
let windowHeight = window.innerHeight;
const language = navigator.language;
const statusBarHeight = D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.top;
const statusBarHeight = out.top;
let osname;
let osversion;
let model;
......@@ -15658,12 +15658,12 @@ const getSystemInfoSync = /* @__PURE__ */ defineSyncApi("getSystemInfoSync", ()
const system = `${osname} ${osversion}`;
const platform = osname.toLocaleLowerCase();
const safeArea = {
left: D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.left,
right: windowWidth - D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.right,
top: D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.top,
bottom: windowHeight - D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.bottom,
width: windowWidth - D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.left - D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.right,
height: windowHeight - D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.top - D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.bottom
left: out.left,
right: windowWidth - out.right,
top: out.top,
bottom: windowHeight - out.bottom,
width: windowWidth - out.left - out.right,
height: windowHeight - out.top - out.bottom
};
const { top: windowTop, bottom: windowBottom } = getWindowOffset();
windowHeight -= windowTop;
......@@ -15683,10 +15683,10 @@ const getSystemInfoSync = /* @__PURE__ */ defineSyncApi("getSystemInfoSync", ()
model,
safeArea,
safeAreaInsets: {
top: D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.top,
right: D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.right,
bottom: D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.bottom,
left: D__DCloud_local_git_uniAppNext_node_modules_safeAreaInsets_out.left
top: out.top,
right: out.right,
bottom: out.bottom,
left: out.left
}
};
});
......
import { isArray, isString } from '@vue/shared'
import path from 'path'
import { Plugin } from 'vite'
import { extend, isArray, isString } from '@vue/shared'
import { isCustomElement, isNativeTag } from '@dcloudio/uni-shared'
import { UniVitePlugin } from '@dcloudio/uni-cli-shared'
import { CompilerOptions } from '@vue/compiler-sfc'
interface PluginConfig {
id: string
......@@ -13,6 +15,39 @@ interface PluginConfig {
}
}
export function initPluginUniOptions(UniVitePlugins: UniVitePlugin[]) {
const transformEvent: Record<string, string> = Object.create(null)
const compilerOptions: CompilerOptions = {
isNativeTag,
isCustomElement,
}
UniVitePlugins.forEach((plugin) => {
const {
compilerOptions: pluginCompilerOptions,
transformEvent: pluginTransformEvent,
} = plugin.uni || {}
if (pluginCompilerOptions) {
if (pluginCompilerOptions.isNativeTag) {
compilerOptions.isNativeTag = pluginCompilerOptions.isNativeTag
}
if (pluginCompilerOptions.isCustomElement) {
compilerOptions.isCustomElement = pluginCompilerOptions.isCustomElement
}
if (pluginCompilerOptions.directiveTransforms) {
compilerOptions.directiveTransforms =
pluginCompilerOptions.directiveTransforms
}
}
if (pluginTransformEvent) {
extend(transformEvent, pluginTransformEvent)
}
})
return {
transformEvent,
compilerOptions,
}
}
export function initExtraPlugins(cliRoot: string, platform: UniApp.PLATFORM) {
return initPlugins(resolvePlugins(cliRoot, platform))
}
......
import { extend, hasOwn, isArray } from '@vue/shared'
import { ParserOptions } from '@vue/compiler-core'
import { CompilerOptions, SFCTemplateCompileOptions } from '@vue/compiler-sfc'
import { isCustomElement, isNativeTag } from '@dcloudio/uni-shared'
import { SFCTemplateCompileOptions } from '@vue/compiler-sfc'
import { isCustomElement } from '@dcloudio/uni-shared'
import {
EXTNAME_VUE_RE,
parseCompatConfigOnce,
// parseCompatConfigOnce,
UniVitePlugin,
} from '@dcloudio/uni-cli-shared'
import { VitePluginUniResolvedOptions } from '..'
import { transformMatchMedia } from './transforms/transformMatchMedia'
import { createTransformEvent } from './transforms/transformEvent'
import { initPluginUniOptions } from '../utils/plugin'
// import { transformContext } from './transforms/transformContext'
function createUniVueTransformAssetUrls(
......@@ -56,41 +55,32 @@ export function initPluginVueOptions(
options.base
)
let isCompilerNativeTag: ParserOptions['isNativeTag'] = isNativeTag
let isCompilerCustomElement: ParserOptions['isCustomElement'] =
isCustomElement
let directiveTransforms: CompilerOptions['directiveTransforms']
const {
compilerOptions: { isNativeTag, isCustomElement, directiveTransforms },
} = initPluginUniOptions(UniVitePlugins)
UniVitePlugins.forEach((plugin) => {
const compilerOptions = plugin.uni?.compilerOptions
if (compilerOptions) {
if (compilerOptions.isNativeTag) {
isCompilerNativeTag = compilerOptions.isNativeTag
}
if (compilerOptions.isCustomElement) {
isCompilerCustomElement = compilerOptions.isCustomElement
}
if (compilerOptions.directiveTransforms) {
directiveTransforms = compilerOptions.directiveTransforms
}
}
})
const compilerOptions =
templateOptions.compilerOptions || (templateOptions.compilerOptions = {})
compilerOptions.isNativeTag = isCompilerNativeTag
compilerOptions.isNativeTag = isNativeTag
compilerOptions.isCustomElement = isCustomElement
if (directiveTransforms) {
compilerOptions.directiveTransforms = extend(
compilerOptions.directiveTransforms || {},
directiveTransforms
)
}
if (!compilerOptions.nodeTransforms) {
compilerOptions.nodeTransforms = []
}
const compatConfig = parseCompatConfigOnce(options.inputDir)
// const compatConfig = parseCompatConfigOnce(options.inputDir)
compilerOptions.compatConfig = extend(
compilerOptions.compatConfig || {},
compatConfig
)
compilerOptions.isCustomElement = isCompilerCustomElement
// compilerOptions.compatConfig = extend(
// compilerOptions.compatConfig || {},
// compatConfig
// )
const eventOpts = UniVitePlugins.reduce<Record<string, string>>(
(eventOpts, UniVitePlugin) => {
......@@ -104,15 +94,8 @@ export function initPluginVueOptions(
compilerOptions.nodeTransforms.unshift(transformMatchMedia)
}
if (directiveTransforms) {
compilerOptions.directiveTransforms = extend(
compilerOptions.directiveTransforms || {},
directiveTransforms
)
}
// App,MP 平台不支持使用静态节点
compilerOptions.hoistStatic = false
return vueOptions
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册