diff --git a/extension.json b/extension.json index 91949de..e5d4c8b 100644 --- a/extension.json +++ b/extension.json @@ -25,6 +25,9 @@ "ParserFirstCallInit": "Isekai\\Widgets\\Widgets::onParserSetup", "BeforePageDisplay": "Isekai\\Widgets\\Widgets::onLoad" }, + "APIModules": { + "isekaiwidgets": "Isekai\\Widgets\\Api\\ApiIsekaiWidgets" + }, "ResourceModules": { "ext.isekai.widgets.global": { "styles": [ @@ -56,7 +59,9 @@ "isekai-createpage-create-page-button", "isekai-createpage-page-exists", "isekai-createpage-title-empty", - "isekai-createpage-redirecting" + "isekai-createpage-redirecting", + "isekai-createpage-warning-ignore", + "isekai-createpage-ignore-warnings-help" ] }, "ext.isekai.discover": { @@ -277,7 +282,7 @@ "IsekaiGlobalWidgets": { "value": ["baseWidgets", "offcanvasTOC"] }, - "IsekaiCreatePageNamespaces": { + "IsekaiCreatePageTypes": { "value": [] } }, diff --git a/i18n/zh-hans.json b/i18n/zh-hans.json index 32ca18a..58add66 100644 --- a/i18n/zh-hans.json +++ b/i18n/zh-hans.json @@ -1,6 +1,9 @@ { "isekai-widgets": "异世界百科 小部件", "isekai-widgets-desc": "在异世界百科上使用的一些小部件", + + "apihelp-isekaiwidgets-summary": "异世界百科提供的小组件所需的API", + "apihelp-isekaiwidgets-param-method": "操作", "isekai-createpage-page-title": "页面标题", "isekai-createpage-create-page": "新建页面", @@ -8,6 +11,12 @@ "isekai-createpage-page-exists": "已有相同名字的页面存在,换一个名字吧。", "isekai-createpage-title-empty": "请填写标题", "isekai-createpage-redirecting": "正在跳转,请稍后……", + "isekai-createpage-warning-ignore": "忽略警告", + "isekai-createpage-ignore-warnings-help": "如果你确定要以当前页面标题新建页面,可以忽略这些警告,不过新建的页面可能被管理员删除或重命名。", + + "apihelp-isekaiwidgets+createpagevalidatetitle-summary": "检测新建页面标题是否有效", + "apihelp-isekaiwidgets+createpagevalidatetitle-param-iwnewpagetitle": "新建页面的标题", + "apihelp-isekaiwidgets+createpagevalidatetitle-param-iwnewpagetype": "新建页面的类型", "isekai-discover-langcode": "zh", "isekai-discover-randompage": "随机页面", diff --git a/includes/Api/ApiIsekaiWidgets.php b/includes/Api/ApiIsekaiWidgets.php new file mode 100644 index 0000000..00dbbf8 --- /dev/null +++ b/includes/Api/ApiIsekaiWidgets.php @@ -0,0 +1,96 @@ + [ + 'class' => ApiCreatePageValidateTitle::class, + ], + ]; + + private $mModuleMgr; + private $mParams; + /** + * @param ApiMain $main + * @param string $action + */ + public function __construct( ApiMain $main, $action ) + { + parent::__construct($main, $action); + + $this->mModuleMgr = new ApiModuleManager( + $this, + MediaWikiServices::getInstance()->getObjectFactory() + ); + + // Allow custom modules to be added in LocalSettings.php + $config = $this->getConfig(); + $this->mModuleMgr->addModules( self::$methodModules, 'method' ); + } + + /** + * Overrides to return this instance's module manager. + * @return ApiModuleManager + */ + public function getModuleManager() { + return $this->mModuleMgr; + } + + public function execute() { + $this->mParams = $this->extractRequestParams(); + + $modules = []; + $this->instantiateModules( $modules, 'method' ); + $this->getResult()->addValue(null, 'modules', array_keys($modules)); + + foreach ( $modules as $module ) { + $module->execute(); + } + } + + /** + * Create instances of all modules requested by the client + * @param array &$modules To append instantiated modules to + * @param string $param Parameter name to read modules from + */ + private function instantiateModules( &$modules, $param ) { + $wasPosted = $this->getRequest()->wasPosted(); + if ( isset( $this->mParams[$param] ) ) { + foreach ( $this->mParams[$param] as $moduleName ) { + $instance = $this->mModuleMgr->getModule( $moduleName, $param ); + if ( $instance === null ) { + ApiBase::dieDebug( __METHOD__, 'Error instantiating module' ); + } + if ( !$wasPosted && $instance->mustBePosted() ) { + $this->dieWithErrorOrDebug( [ 'apierror-mustbeposted', $moduleName ] ); + } + // Ignore duplicates. TODO 2.0: die()? + if ( !array_key_exists( $moduleName, $modules ) ) { + $modules[$moduleName] = $instance; + } + } + } + } + + public function getAllowedParams( $flags = 0 ) { + $result = [ + 'method' => [ + ParamValidator::PARAM_ISMULTI => true, + ParamValidator::PARAM_TYPE => 'submodule', + ], + ]; + + return $result; + } + + public function isInternal() { + return true; + } +} \ No newline at end of file diff --git a/includes/Api/IsekaiWidgets/ApiCreatePageValidateTitle.php b/includes/Api/IsekaiWidgets/ApiCreatePageValidateTitle.php new file mode 100644 index 0000000..7a63ffa --- /dev/null +++ b/includes/Api/IsekaiWidgets/ApiCreatePageValidateTitle.php @@ -0,0 +1,100 @@ +getMain(), $method); + + $this->mParent = $main; + $this->services = MediaWikiServices::getInstance(); + } + + public function execute() { + $newPageTitle = $this->getParameter('iwnewpagetitle'); + $newPageType = $this->getParameter('iwnewpagetype'); + + $config = $this->services->getMainConfig(); + $pageTypes = $config->get('IsekaiCreatePageTypes'); + + $newPageTypePrefix = ""; + foreach ($pageTypes as $item) { + if ($item['id'] === $newPageType) { + $newPageTypePrefix = $item['prefix'] ?? ''; + break; + } + } + + $newPageTitle = $newPageTypePrefix . $newPageTitle; + + $user = $this->getUser(); + $permissionManager = $this->services->getPermissionManager(); + + $result = $this->getResult(); + + $validationResult = new NewPageTitleValidationResult(); + + /*if ($permissionManager->userHasRight($user, 'editprotected')) { + // 允许编辑受保护页面的用户,不进行标题检查 + $result->addValue(['isekaiwidget'], $this->getModuleName(), $validationResult->toArray()); + return true; + }*/ + + // 检查页面是否已经存在 + try { + $title = Title::newFromText($newPageTitle); + if ($title && $title->exists()) { + $validationResult->addError('pageexists', wfMessage('isekai-createpage-page-exists')->text()); + } + } catch (\Exception $e) { + wfLogWarning('Failed to validate new page title: ' . $e->getMessage()); + } + + // 调用Hook检查标题是否正确 + $hookContainer = $this->services->getHookContainer(); + $hookContainer->run('IsekaiWidgets::CreatePageValidateTitle', [ + $validationResult, + $user, + $newPageTitle, + $newPageType, + ]); + + $result->addValue(['isekaiwidget'], $this->getModuleName(), $validationResult->toArray()); + return true; + } + + public function getAllowedParams($flags = 0) { + return [ + 'iwnewpagetitle' => [ + ParamValidator::PARAM_TYPE => 'string', + ParamValidator::PARAM_DEFAULT => null, + ParamValidator::PARAM_REQUIRED => true, + ], + 'iwnewpagetype' => [ + ParamValidator::PARAM_TYPE => 'string', + ParamValidator::PARAM_DEFAULT => 'default', + ParamValidator::PARAM_REQUIRED => false, + ], + ]; + } + + public function getCacheMode($params) { + return 'private'; + } + + public function getParent() { + return $this->mParent; + } +} \ No newline at end of file diff --git a/includes/CreatePageWidget.php b/includes/CreatePageWidget.php index ead4de9..66cd418 100644 --- a/includes/CreatePageWidget.php +++ b/includes/CreatePageWidget.php @@ -18,9 +18,9 @@ class CreatePageWidget { public static function create($text, $params, Parser $parser, PPFrame $frame) { $config = MediaWikiServices::getInstance()->getMainConfig(); - $configCreatePageNamespaces = $config->get('IsekaiCreatePageNamespaces'); + $configCreatePageTypes = $config->get('IsekaiCreatePageTypes'); - $parser->getOutput()->setJsConfigVar('wgIsekaiCreatePageNamespaces', $configCreatePageNamespaces); + $parser->getOutput()->setJsConfigVar('wgIsekaiCreatePageTypes', $configCreatePageTypes); $parser->getOutput()->addModules(['ext.isekai.createPage']); return self::getHtml(); diff --git a/includes/Utils/NewPageTitleValidationResult.php b/includes/Utils/NewPageTitleValidationResult.php new file mode 100644 index 0000000..45a4451 --- /dev/null +++ b/includes/Utils/NewPageTitleValidationResult.php @@ -0,0 +1,46 @@ + $this->hasError ? 1 : 0, + 'hasWarning' => $this->hasWarning ? 1 : 0, + 'warnings' => $this->warnings, + 'errors' => $this->errors, + ]; + } + + public function __serialize(): array { + return $this->toArray(); + } + + public function __unserialize(array $data): void { + $this->hasError = (bool)$data['hasError'] ?? false; + $this->hasWarning = (bool)$data['hasWarning'] ?? false; + $this->warnings = $data['warnings'] ?? []; + $this->errors = $data['errors'] ?? []; + } + + public function addError(string $errorCode, string $errorMessage): void { + $this->hasError = true; + $this->errors[] = [ + 'code' => $errorCode, + 'message' => $errorMessage, + ]; + } + + public function addWarning(string $warningCode, string $warningMessage): void { + $this->hasWarning = true; + $this->warnings[] = [ + 'code' => $warningCode, + 'message' => $warningMessage, + ]; + } +} \ No newline at end of file diff --git a/modules/createPage/ext.isekai.createPage.base.less b/modules/createPage/ext.isekai.createPage.base.less index 0d4231f..145ee6d 100644 --- a/modules/createPage/ext.isekai.createPage.base.less +++ b/modules/createPage/ext.isekai.createPage.base.less @@ -23,6 +23,23 @@ display: none; } + .isekai-createpage-ignore-warnings-field { + margin-top: 0.5em; + .oo-ui-fieldLayout-header { + display: block; + + .oo-ui-labelElement-label { + line-height: 2.4em; + font-size: var(--font-size-medium); + } + + .oo-ui-labelWidget.oo-ui-inline-help { + font-size: var(--font-size-small); + line-height: 1.42857143em; + } + } + } + .oo-ui-fieldLayout-messages { margin: 0.5em 0 0 0.5em; } @@ -46,6 +63,14 @@ flex-shrink: 1; } } + + .errors-container:not(:empty) { + padding-top: 0.5rem; + } + + .errors-container > * { + margin-top: 0.5em; + } } } } \ No newline at end of file diff --git a/modules/createPage/ext.isekai.createPage.js b/modules/createPage/ext.isekai.createPage.js index 1ffdd7b..f9150a9 100644 --- a/modules/createPage/ext.isekai.createPage.js +++ b/modules/createPage/ext.isekai.createPage.js @@ -1 +1 @@ -(()=>{"use strict";function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(t)}function t(t,i){for(var a=0;a0?(this.createButton.setDisabled(!0),this.pageExists(t).then((function(i){if(i)e.createButton.setDisabled(!1),e.setError(mw.message("isekai-createpage-page-exists").parse());else{var a=mw.util.getUrl(t,{veaction:"edit"});e.inputGroup.setSuccess([mw.message("isekai-createpage-redirecting").parse()]),location.href=a}}))):this.setError(mw.message("isekai-createpage-title-empty").parse())}},{key:"onPageNameChange",value:function(){this.hasError&&this.clearError();var e=this.pageNameInput.getValue();if(-1!==e.indexOf(":")||-1!==e.indexOf("`")){var t=this.pageNameInput.getRange();e=e.replace(/:/g,":").replace(/`/g,"·"),this.pageNameInput.setValue(e),this.pageNameInput.selectRange(t.from,t.to)}}},{key:"onNamespaceChange",value:function(){this.pageNameInput.setPagePrefix(this.selectNamespaceDropdown.getValue())}},{key:"setError",value:function(e){this.inputGroup.setErrors([e]),this.hasError=!0}},{key:"clearError",value:function(){this.inputGroup.setErrors([]),this.hasError=!1}},{key:"pageExists",value:function(e){var t=this;return new Promise((function(i,a){t.api.get({action:"query",titles:e}).done((function(e){e.query&&e.query.pages?e.query.pages[-1]?i(!1):i(!0):i(!1)})).fail(a)}))}},{key:"setTitle",value:function(e){this.title.text(e)}}])&&t(i.prototype,a),Object.defineProperty(i,"prototype",{writable:!1}),e}())})(); \ No newline at end of file +(()=>{"use strict";function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e(t)}function t(t,i){for(var n=0;n'),this.ignoreWarningsCheckbox=new OO.ui.CheckboxInputWidget({selected:!1}),this.ignoreWarningsCheckbox.on("change",this.refreshCreatePageBtnEnabled.bind(this)),this.ignoreWarningsCheckboxField=new OO.ui.FieldLayout(this.ignoreWarningsCheckbox,{align:"inline",label:mw.message("isekai-createpage-warning-ignore").parse(),helpInline:!0,help:mw.message("isekai-createpage-ignore-warnings-help").parse()}),this.ignoreWarningsCheckboxField.$element.addClass("isekai-createpage-ignore-warnings-field").hide(),this.cardContent=this.baseDom.find(".card-body .card-content"),this.cardContent.append(this.formGroup.$element),this.cardContent.append(this.errorsContainer),this.cardContent.append(this.ignoreWarningsCheckboxField.$element)}},{key:"createPage",value:function(){var e=this,t=this.pageNameInput.getValue(),i=this.selectPageTypeDropdown.getValue(),n=(i=JSON.parse(i||"{}")).id||"default",a=(i.prefix||"")+t;t.trim().length>0?(this.createButton.setDisabled(!0),this.hasWarnings&&this.ignoreWarningsCheckbox.isSelected()?this._doCreatePage(a):this.validateNewPageTitle(t,n).then((function(t){t&&e._doCreatePage(a)}))):this.setErrors([mw.message("isekai-createpage-title-empty").parse()])}},{key:"_doCreatePage",value:function(e){var t=mw.util.getUrl(e,{veaction:"edit"});window.open(t,"_blank"),this.pageNameInput.setValue(""),this.clearErrorWarnings()}},{key:"onPageNameChange",value:function(){this.clearErrorWarnings();var e=this.pageNameInput.getValue();if(-1!==e.indexOf(":")||-1!==e.indexOf("`")){var t=this.pageNameInput.getRange();e=e.replace(/:/g,":").replace(/`/g,"·"),this.pageNameInput.setValue(e),this.pageNameInput.selectRange(t.from,t.to)}}},{key:"onPageTypeChange",value:function(){var e=this.selectPageTypeDropdown.getValue();this.pageNameInput.setPagePrefix(e.prefix),this.clearErrorWarnings()}},{key:"makeMessageRaw",value:function(e,t){var i=new OO.ui.MessageWidget({type:e,inline:!0,label:t}).$element;return i.find(".oo-ui-labelElement-label").html(t),i}},{key:"setErrors",value:function(e){var t=this;e.forEach((function(e){var i=t.makeMessageRaw("error",e);t.errorsContainer.append(i)})),this.hasErrors=!0,this.refreshCreatePageBtnEnabled(),this.refreshIgnoreWarningsCheckbox()}},{key:"setWarnings",value:function(e){var t=this;e.forEach((function(e){var i=t.makeMessageRaw("warning",e);t.errorsContainer.append(i)})),this.hasWarnings=!0,this.refreshCreatePageBtnEnabled(),this.refreshIgnoreWarningsCheckbox()}},{key:"clearErrorWarnings",value:function(){(this.hasErrors||this.hasWarnings)&&(this.errorsContainer.empty(),this.hasErrors=!1,this.hasWarnings=!1,this.refreshCreatePageBtnEnabled(),this.refreshIgnoreWarningsCheckbox())}},{key:"refreshCreatePageBtnEnabled",value:function(){var e=this;this.createButtonEnabled=!e.hasErrors&&(!e.hasWarnings||e.ignoreWarningsCheckbox.isSelected()),this.createButton.setDisabled(!this.createButtonEnabled)}},{key:"refreshIgnoreWarningsCheckbox",value:function(){this.hasWarnings&&!this.hasErrors?this.ignoreWarningsCheckboxField.$element.show():this.ignoreWarningsCheckboxField.$element.hide(),this.hasWarnings||this.hasErrors||this.ignoreWarningsCheckbox.setSelected(!1)}},{key:"validateNewPageTitle",value:function(e){var t=this,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"default";return new Promise((function(n,a){t.api.get({action:"isekaiwidgets",method:"createpagevalidatetitle",iwnewpagetitle:e,iwnewpagetype:i}).done((function(e){if(e.isekaiwidget&&e.isekaiwidget.createpagevalidatetitle){var i=e.isekaiwidget.createpagevalidatetitle;if(!i.hasError&&!i.hasWarning)return void n(!0);i.hasError&&t.setErrors(i.errors.map((function(e){return e.message}))),i.hasWarning&&t.setWarnings(i.warnings.map((function(e){return e.message}))),n(!1)}else n(!1)})).fail(a)}))}}],n&&t(i.prototype,n),Object.defineProperty(i,"prototype",{writable:!1}),e}())})(); \ No newline at end of file diff --git a/src/createPage/ext.isekai.createPage.js b/src/createPage/ext.isekai.createPage.js index db2379b..2f374c6 100644 --- a/src/createPage/ext.isekai.createPage.js +++ b/src/createPage/ext.isekai.createPage.js @@ -6,29 +6,33 @@ class CreatePageWidget { this.pageUrl = null; this.api = new mw.Api(); - this.hasError = false; + this.hasErrors = false; + this.hasWarnings = false; + + this.createButtonEnabled = true; this.initDom(); } initDom() { - let namespaces = mw.config.get('wgIsekaiCreatePageNamespaces'); + let namespaces = mw.config.get('wgIsekaiCreatePageTypes'); if (!Array.isArray(namespaces) || namespaces.length === 0) { namespaces = [ { + type: 'default', name: 'Main', prefix: '', } ]; } - this.selectNamespaceDropdown = new OO.ui.DropdownInputWidget({ + this.selectPageTypeDropdown = new OO.ui.DropdownInputWidget({ options: namespaces.map((nsInfo) => ({ - data: nsInfo.prefix, + data: JSON.stringify(nsInfo), label: nsInfo.name, })), }); - this.selectNamespaceDropdown.on('change', this.onNamespaceChange.bind(this)); + this.selectPageTypeDropdown.on('change', this.onPageTypeChange.bind(this)); this.pageNameInput = new isekai.ui.CreatePageInputWidget({ placeholder: mw.message('isekai-createpage-page-title').parse(), @@ -46,48 +50,77 @@ class CreatePageWidget { this.createButton.on('click', this.createPage.bind(this)); this.inputGroup = new OO.ui.ActionFieldLayout(this.pageNameInput, this.createButton, { - align: 'top' + align: 'center' }); this.formGroup = new OO.ui.HorizontalLayout({ items: [ - this.selectNamespaceDropdown, + this.selectPageTypeDropdown, this.inputGroup ] }); - this.baseDom.find('.card-body .card-content').append(this.formGroup.$element); + this.errorsContainer = $('
'); + + this.ignoreWarningsCheckbox = new OO.ui.CheckboxInputWidget({ + selected: false + }); + this.ignoreWarningsCheckbox.on('change', this.refreshCreatePageBtnEnabled.bind(this)); + + this.ignoreWarningsCheckboxField = new OO.ui.FieldLayout(this.ignoreWarningsCheckbox, { + align: 'inline', + label: mw.message('isekai-createpage-warning-ignore').parse(), + helpInline: true, + help: mw.message('isekai-createpage-ignore-warnings-help').parse(), + }); + this.ignoreWarningsCheckboxField.$element + .addClass('isekai-createpage-ignore-warnings-field') + .hide(); + + this.cardContent = this.baseDom.find('.card-body .card-content'); + this.cardContent.append(this.formGroup.$element); + this.cardContent.append(this.errorsContainer); + this.cardContent.append(this.ignoreWarningsCheckboxField.$element); } createPage() { - let title = this.selectNamespaceDropdown.getValue() + this.pageNameInput.getValue(); - console.log(title); - if (this.hasError) { - this.clearError(); //清除errors - } + let title = this.pageNameInput.getValue(); + let pageTypeConfig = this.selectPageTypeDropdown.getValue(); + pageTypeConfig = JSON.parse(pageTypeConfig || '{}'); + + let pageTypeId = pageTypeConfig.id || 'default'; + let fullTitle = (pageTypeConfig.prefix || '') + title; + if (title.trim().length > 0) { this.createButton.setDisabled(true); - this.pageExists(title).then((exists) => { - if (exists) { - this.createButton.setDisabled(false); - this.setError(mw.message('isekai-createpage-page-exists').parse()); //提示页面已经存在 - } else { - let targetUrl = mw.util.getUrl(title, { veaction: 'edit' }); - this.inputGroup.setSuccess([ - mw.message('isekai-createpage-redirecting').parse() - ]); //提示正在跳转 - location.href = targetUrl; - } - }); + + if (this.hasWarnings && this.ignoreWarningsCheckbox.isSelected()) { + // 已忽略警告 + this._doCreatePage(fullTitle); + } else { + this.validateNewPageTitle(title, pageTypeId).then((valid) => { + if (valid) { + this._doCreatePage(fullTitle); + } + }); + } } else { - this.setError(mw.message('isekai-createpage-title-empty').parse()); + this.setErrors([ + mw.message('isekai-createpage-title-empty').parse() + ]); } } + _doCreatePage(fullTitle) { + let targetUrl = mw.util.getUrl(fullTitle, { veaction: 'edit' }); + window.open(targetUrl, '_blank'); + + this.pageNameInput.setValue(''); + this.clearErrorWarnings(); + } + onPageNameChange() { - if (this.hasError) { - this.clearError(); - } + this.clearErrorWarnings(); let value = this.pageNameInput.getValue(); if (value.indexOf(':') !== -1 || value.indexOf('`') !== -1) { @@ -98,42 +131,118 @@ class CreatePageWidget { } } - onNamespaceChange() { - this.pageNameInput.setPagePrefix(this.selectNamespaceDropdown.getValue()); + onPageTypeChange() { + let pageTypeConfig = this.selectPageTypeDropdown.getValue(); + this.pageNameInput.setPagePrefix(pageTypeConfig.prefix); + this.clearErrorWarnings(); } - setError(msg) { - this.inputGroup.setErrors([msg]); //提示页面已经存在 - this.hasError = true; + makeMessageRaw(kind, html) { + let $el = new OO.ui.MessageWidget({ + type: kind, + inline: true, + label: html, + }).$element; + let $label = $el.find('.oo-ui-labelElement-label'); + $label.html(html); + + return $el; } - clearError() { - this.inputGroup.setErrors([]); - this.hasError = false; + setErrors(errorMessages) { + errorMessages.forEach((errorMessage) => { + let $message = this.makeMessageRaw('error', errorMessage); + this.errorsContainer.append($message); + }); + this.hasErrors = true; + + this.refreshCreatePageBtnEnabled(); + this.refreshIgnoreWarningsCheckbox(); } - pageExists(title) { + setWarnings(warningMessages) { + warningMessages.forEach((warningMessage) => { + let $message = this.makeMessageRaw('warning', warningMessage); + this.errorsContainer.append($message); + }); + this.hasWarnings = true; + + this.refreshCreatePageBtnEnabled(); + this.refreshIgnoreWarningsCheckbox(); + } + + clearErrorWarnings() { + if (this.hasErrors || this.hasWarnings) { + this.errorsContainer.empty(); + + this.hasErrors = false; + this.hasWarnings = false; + + this.refreshCreatePageBtnEnabled(); + this.refreshIgnoreWarningsCheckbox(); + } + } + + refreshCreatePageBtnEnabled() { + this.createButtonEnabled = (() => { + if (this.hasErrors) { + return false; + } + + if (this.hasWarnings) { + // 检查是否忽略警告 + return this.ignoreWarningsCheckbox.isSelected(); + } + + return true; + })(); + + this.createButton.setDisabled(!this.createButtonEnabled); + } + + refreshIgnoreWarningsCheckbox() { + if (this.hasWarnings && !this.hasErrors) { + this.ignoreWarningsCheckboxField.$element.show(); + } else { + this.ignoreWarningsCheckboxField.$element.hide(); + } + + if (!this.hasWarnings && !this.hasErrors) { + // 没有警告和错误时,重置忽略警告复选框 + this.ignoreWarningsCheckbox.setSelected(false); + } + } + + validateNewPageTitle(title, pageType = 'default') { return new Promise((resolve, reject) => { this.api.get({ - action: 'query', - titles: title, + action: 'isekaiwidgets', + method: 'createpagevalidatetitle', + iwnewpagetitle: title, + iwnewpagetype: pageType, }).done((data) => { - if (data.query && data.query.pages) { - if (data.query.pages["-1"]) { - resolve(false); - } else { + if (data.isekaiwidget && data.isekaiwidget.createpagevalidatetitle) { + let result = data.isekaiwidget.createpagevalidatetitle; + + if (!result.hasError && !result.hasWarning) { resolve(true); + return; } + + if (result.hasError) { + this.setErrors(result.errors.map(error => error.message)); + } + if (result.hasWarning) { + this.setWarnings(result.warnings.map(warning => warning.message)); + } + + resolve(false); } else { resolve(false); } }).fail(reject); }); } - - setTitle(title) { - this.title.text(title); - } } registerModule('ui.CreatePageWidget', CreatePageWidget); \ No newline at end of file