Inline editor - Ext JS

解决编辑器滚动问题
讨论了内联编辑器在编辑树节点文本时遇到的滚动问题,并提出了几种解决方案,包括将编辑器绑定到树面板主体使其随节点滚动,使用定时验证位置的方法以及监听滚动容器属性变化等。
The inline editor that's used to for example edit tree text nodes does not scroll when the container of the element it is editing scrolls. I seem to remember there's a neat, Ext way of fixing this, but it eludes me right now...
Reply With Quote
  #2  
Old 03-08-2007, 07:38 AM
Default

It could be rendered to the tree panels body so it scrolls with the node. The problem with that is it can get clipped.

It could also use an interval to validate it's position while in edit mode... would be delayed though.
Reply With Quote
  #3  
Old 03-08-2007, 10:17 AM
Default

I would expect the scroll event to end the edit session on the field, much like clicking on a page would close a menu.

my $.02
Reply With Quote
  #4  
Old 03-08-2007, 05:27 PM
Default

simeon, I agree 100%. The problem is that scroll events don't bubble so there's no way I can generically attach and hide the editor. Maybe a code example in the download (it would be very short) showing how to wire it to the tree's scroll would make sense.
Reply With Quote
  #5  
Old 03-09-2007, 09:22 AM
Default

If there is an ext equivalent to IE's onpropertychange event(custom event?). I would use a property on the scrolling container and attach a listener to that property.

<div onscroll="this.isScrolling = this.isScrolling*-1" isScrolling="1">

    <div>floating stuff here</div>
    <div>floating stuff here</div>

</div>
Then when I create a floating element (menu, edit form field, etc.), I would attach an onpropertychange event listener to the scrolling div. I would listen for a change to the isScrolling property which will be cycling between 1 and -1 as the container scrolls. If that listener is called then the floating elements will close themselves independently.

This could be accomplished implicitly when the floating elements are created by looping up through the dom looking to see if the containing elements have an isScrolling attribute. If it does, then the floating element could attach an event listener to its isScrolling attribute.

As for getting a working example, i would need to work on that next week. I have to have my prototype ready for a QA sneak peak on monday. :-)
Reply With Quote
  #6  
Old 03-09-2007, 05:15 PM
Default

It's pretty easy to wire it up:

tree.getEl().on('scroll', function(){
    if(editor.editing){
        editor.cancelEdit();
    }
});
It will do the editing check internally in the next build.
Reply With Quote
ERROR in ./node_modules/monaco-editor/esm/vs/base/browser/ui/codicons/codicon/codicon.css (./node_modules/monaco-editor/esm/vs/base/browser/ui/codicons/codicon/codicon.css.webpack[javascript/auto]!=!./node_modules/css-loader/dist/cjs.js??clonedRuleSet-14.use[1]!./node_modules/postcss-loader/dist/cjs.js??clonedRuleSet-14.use[2]!./node_modules/monaco-editor/esm/vs/base/browser/ui/codicons/codicon/codicon.css) 5:36-77 Module not found: Error: Can't resolve './codicon.ttf' in 'E:\daima\DT\longdexunjian\front\node_modules\monaco-editor\esm\vs\base\browser\ui\codicons\codicon' @ ./node_modules/monaco-editor/esm/vs/base/browser/ui/codicons/codicon/codicon.css @ ./node_modules/monaco-editor/esm/vs/base/browser/ui/codicons/codiconStyles.js 5:0-31 @ ./node_modules/monaco-editor/esm/vs/editor/editor.all.js 64:0-54 @ ./node_modules/monaco-editor/esm/vs/editor/edcore.main.js 5:0-25 @ ./node_modules/monaco-editor/esm/vs/editor/editor.main.js 7:0-30 7:0-30 @ ./node_modules/@marsgis/editor/dist/editor.umd.js 1:78-102 @ ./src/main.js 49:14-40 ERROR in ./node_modules/monaco-editor/esm/vs/base/browser/ui/codicons/codicon/codicon.css Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js): HookWebpackError: Cannot find module './codicon.ttf' at tryRunOrWebpackError (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\HookWebpackError.js:86:9) at __webpack_require_module__ (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5464:12) at __webpack_require__ (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5411:18) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5498:20 at symbolIterator (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3485:9) at done (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3527:9) at Hook.eval [as callAsync] (eval at create (E:\daima\DT\longdexunjian\front\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5386:43 at symbolIterator (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3482:9) at timesSync (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:2297:7) at Object.eachLimit (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3463:5) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5348:16 at symbolIterator (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3485:9) at done (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3527:9) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5262:8 at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:3680:5 at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Cache.js:99:5 at Hook.eval [as callAsync] (eval at create (E:\daima\DT\longdexunjian\front\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:16:1) at Cache.get (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Cache.js:81:18) at ItemCacheFacade.get (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\CacheFacade.js:116:15) at Compilation._codeGenerationModule (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:3644:9) at codeGen (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5250:11) at symbolIterator (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3482:9) at timesSync (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:2297:7) at Object.eachLimit (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3463:5) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5316:15 at symbolIterator (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3485:9) at timesSync (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:2297:7) at Object.eachLimit (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3463:5) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5280:14 at processQueue (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\util\processAsyncTree.js:61:4) at process.processTicksAndRejections (node:internal/process/task_queues:85:11) -- inner error -- Error: Cannot find module './codicon.ttf' at webpackMissingModule (E:\daima\DT\longdexunjian\front\node_modules\css-loader\dist\cjs.js??clonedRuleSet-14.use[1]!E:\daima\DT\longdexunjian\front\node_modules\postcss-loader\dist\cjs.js??clonedRuleSet-14.use[2]!E:\daima\DT\longdexunjian\front\node_modules\monaco-editor\esm\vs\base\browser\ui\codicons\codicon\codicon.css:12:113) at Module.<anonymous> (E:\daima\DT\longdexunjian\front\node_modules\css-loader\dist\cjs.js??clonedRuleSet-14.use[1]!E:\daima\DT\longdexunjian\front\node_modules\postcss-loader\dist\cjs.js??clonedRuleSet-14.use[2]!E:\daima\DT\longdexunjian\front\node_modules\monaco-editor\esm\vs\base\browser\ui\codicons\codicon\codicon.css:12:201) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\javascript\JavascriptModulesPlugin.js:518:10 at Hook.eval [as call] (eval at create (E:\daima\DT\longdexunjian\front\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:19:10), <anonymous>:7:1) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5466:39 at tryRunOrWebpackError (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\HookWebpackError.js:81:7) at __webpack_require_module__ (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5464:12) at __webpack_require__ (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5411:18) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5498:20 at symbolIterator (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3485:9) at done (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3527:9) at Hook.eval [as callAsync] (eval at create (E:\daima\DT\longdexunjian\front\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:15:1) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5386:43 at symbolIterator (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3482:9) at timesSync (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:2297:7) at Object.eachLimit (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3463:5) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5348:16 at symbolIterator (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3485:9) at done (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3527:9) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5262:8 at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:3680:5 at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Cache.js:99:5 at Hook.eval [as callAsync] (eval at create (E:\daima\DT\longdexunjian\front\node_modules\webpack\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:16:1) at Cache.get (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Cache.js:81:18) at ItemCacheFacade.get (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\CacheFacade.js:116:15) at Compilation._codeGenerationModule (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:3644:9) at codeGen (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5250:11) at symbolIterator (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3482:9) at timesSync (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:2297:7) at Object.eachLimit (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3463:5) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5316:15 at symbolIterator (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3485:9) at timesSync (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:2297:7) at Object.eachLimit (E:\daima\DT\longdexunjian\front\node_modules\neo-async\async.js:3463:5) at E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\Compilation.js:5280:14 at processQueue (E:\daima\DT\longdexunjian\front\node_modules\webpack\lib\util\processAsyncTree.js:61:4) at process.processTicksAndRejections (node:internal/process/task_queues:85:11) Generated code for E:\daima\DT\longdexunjian\front\node_modules\css-loader\dist\cjs.js??clonedRuleSet-14.use[1]!E:\daima\DT\longdexunjian\front\node_modules\postcss-loader\dist\cjs.js??clonedRuleSet-14.use[2]!E:\daima\DT\longdexunjian\front\node_modules\monaco-editor\esm\vs\base\browser\ui\codicons\codicon\codicon.css 1 | __webpack_require__.r(__webpack_exports__); 2 | /* harmony import */ var _css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../../../../../../css-loader/dist/runtime/noSourceMaps.js */ "E:\\daima\\DT\\longdexunjian\\front\\node_modules\\css-loader\\dist\\runtime\\noSourceMaps.js"); 3 | /* harmony import */ var _css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__); 4 | /* harmony import */ var _css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../../../../../../css-loader/dist/runtime/api.js */ "E:\\daima\\DT\\longdexunjian\\front\\node_modules\\css-loader\\dist\\runtime\\api.js"); 5 | /* harmony import */ var _css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__); 6 | /* harmony import */ var _css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../../../../../css-loader/dist/runtime/getUrl.js */ "E:\\daima\\DT\\longdexunjian\\front\\node_modules\\css-loader\\dist\\runtime\\getUrl.js"); 7 | /* harmony import */ var _css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2__); 8 | // Imports 9 | 10 | 11 | 12 | var ___CSS_LOADER_URL_IMPORT_0___ = new URL(/* asset import */ Object(function webpackMissingModule() { var e = new Error("Cannot find module './codicon.ttf'"); e.code = 'MODULE_NOT_FOUND'; throw e; }()), __webpack_require__.b); 13 | var ___CSS_LOADER_EXPORT___ = _css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default())); 14 | var ___CSS_LOADER_URL_REPLACEMENT_0___ = _css_loader_dist_runtime_getUrl_js__WEBPACK_IMPORTED_MODULE_2___default()(___CSS_LOADER_URL_IMPORT_0___); 15 | // Module 16 | ___CSS_LOADER_EXPORT___.push([module.id, "/*---------------------------------------------------------------------------------------------\n * Copyright (c) Microsoft Corporation. All rights reserved.\n * Licensed under the MIT License. S ee License.txt in the project root for license information.\n *--------------------------------------------------------------------------------------------*/\n\n@font-face {\n\tfont-family: \"codicon\";\n\tfont-display: block;\n\tsrc: url(" + _ __CSS_LOADER_URL_REPLACEMENT_0___ + ") format(\"truetype\");\n}\n\n.codicon[class*='codicon-'] {\n\tfont: normal normal normal 16px/1 codicon;\n\tdisplay: inline-block;\n\ttext-decoration: none;\n\ttext-rendering: auto;\n\ttext-align: center;\n \ttext-transform: none;\n\t-webkit-font-smoothing: antialiased;\n\t-moz-osx-font-smoothing: grayscale;\n\t-moz-user-select: none;\n\t -ms-user-select: none;\n\t user-select: none;\n\t-webkit-user-select: none;\n}\n\n/* icon rules are dynamically created by the platform theme service (see iconsStyleSheet.ts) */\n", ""]); 17 | // Exports 18 | /* harmony default export */ __webpack_exports__["default"] = (___CSS_LOADER_EXPORT___); 19 | @ ./node_modules/monaco-editor/esm/vs/base/browser/ui/codicons/codiconStyles.js 5:0-31 @ ./node_modules/monaco-editor/esm/vs/editor/editor.all.js 64:0-54 @ ./node_modules/monaco-editor/esm/vs/editor/edcore.main.js 5:0-25 @ ./node_modules/monaco-editor/esm/vs/editor/editor.main.js 7:0-30 7:0-30 @ ./node_modules/@marsgis/editor/dist/editor.umd.js 1:78-102 @ ./src/main.js 49:14-40 巡检业务管理平台 compiled with 2 errors
07-02
{ "name": "admin", "version": "1.2.8", "description": "eapAdmin", "author": "shan", "email": "595485548@qq.com", "private": true, "scripts": { "dev": "cross-env NODE_ENV=development webpack-dev-server --inline --progress --config build/webpack.dev.conf.js", "start": "npm run dev", "unit": "jest --config test/unit/jest.conf.js --coverage", "e2e": "node test/e2e/runner.js", "test": "npm run unit && npm run e2e", "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs", "build": "node build/build.js", "analyz": "cross-env NODE_ENV=production npm_config_report=true npm run build", "startdll": "webpack --config build/webpack.dll.config.js" }, "dependencies": { "@jiaminghi/data-view": "^2.10.0", "ant-design-vue": "^1.7.2", "axios": "^0.19.2", "crypto-js": "^4.1.1", "dayjs": "^1.11.3", "echarts": "^4.1.0", "element-resize-detector": "^1.2.4", "element-ui": "^2.13.1", "file-save": "^0.2.0", "file-saver": "^2.0.5", "font-awesome": "^4.7.0", "js-cookie": "^2.2.0", "js-md5": "^0.7.3", "jsencrypt": "^3.3.2", "module": "^1.2.5", "moment": "^2.29.4", "nprogress": "^0.2.0", "pinyin": "^2.10.2", "screenfull": "^3.3.3", "scriptjs": "^2.5.8", "shortid": "^2.2.15", "sortablejs": "^1.7.0", "vue": "^2.5.2", "vue-i18n": "^8.4.0", "vue-quill-editor": "^3.0.6", "vue-router": "^3.0.1", "vue-svgicon": "^3.2.9", "vuex": "^3.0.1", "wangeditor": "^3.1.1", "xlsx": "^0.17.0" }, "devDependencies": { "ajv": "^5.5.2", "autoprefixer": "^7.1.2", "babel-core": "^6.22.1", "babel-eslint": "^8.2.1", "babel-helper-vue-jsx-merge-props": "^2.0.3", "babel-jest": "^21.0.2", "babel-loader": "^7.1.1", "babel-plugin-dynamic-import-node": "^1.2.0", "babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", "babel-plugin-transform-runtime": "^6.22.0", "babel-plugin-transform-vue-jsx": "^3.5.0", "babel-preset-env": "^1.3.2", "babel-preset-stage-2": "^6.22.0", "babel-register": "^6.22.0", "browserslist": "^4.25.1", "cache-loader": "^4.1.0", "chalk": "^2.0.1", "chromedriver": "^2.27.2", "compression-webpack-plugin": "^3.1.0", "copy-webpack-plugin": "^4.0.1", "cross-env": "^6.0.3", "cross-spawn": "^5.0.1", "css-loader": "^3.5.2", "eslint": "^7.32.0", "eslint-config-standard": "^10.2.1", "eslint-friendly-formatter": "^3.0.0", "eslint-loader": "^4.0.0", "eslint-plugin-import": "^2.32.0", "eslint-plugin-node": "^5.2.1", "eslint-plugin-promise": "^3.4.0", "eslint-plugin-standard": "^3.0.1", "eslint-plugin-vue": "^4.0.0", "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^3.0.1", "friendly-errors-webpack-plugin": "^1.6.1", "gulp": "^3.9.1", "hard-source-webpack-plugin": "^0.13.1", "html-webpack-plugin": "^4.2.0", "jest": "^22.0.4", "jest-serializer-vue": "^0.3.0", "less": "^3.10.3", "less-loader": "^5.0.0", "mini-css-extract-plugin": "^0.9.0", "nightwatch": "^0.9.12", "node-notifier": "^5.1.2", "optimize-css-assets-webpack-plugin": "^3.2.0", "ora": "^1.2.0", "portfinder": "^1.0.13", "postcss-import": "^12.0.1", "postcss-loader": "^3.0.0", "postcss-url": "^7.2.1", "rimraf": "^2.6.0", "sass-loader": "^7.1.0", "script-loader": "^0.7.2", "selenium-server": "^3.0.1", "semver": "^5.3.0", "shelljs": "^0.7.6", "style-loader": "^1.1.4", "svg-sprite-loader": "^6.0.11", "thread-loader": "^2.1.3", "uglifyjs-webpack-plugin": "^2.2.0", "url-loader": "^4.1.0", "vue-jest": "^1.0.2", "vue-loader": "^15.9.1", "vue-style-loader": "^3.0.1", "vue-template-compiler": "^2.5.2", "webpack": "^4.47.0", "webpack-bundle-analyzer": "^2.9.0", "webpack-cli": "^3.3.11", "webpack-dev-server": "^3.10.3", "webpack-merge": "^4.1.0" }, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" }, "browserslist": [ "> 1%", "last 2 versions", "not ie <= 8" ] } 这是我的package.json
07-11
<template> <el-dialog :visible.sync="dialogVisible" :title="`${title[operateType]}范围子规则`" width="500" :close-on-click-modal="false" > <el-form :model="ruleForm" :rules="rules" ref="ruleFormRef" label-width="100px" class="base-ruleForm" label-position="top" size="mini" :disabled="operateType == 'detail'" > <el-form-item label="规则名称" prop="nameCn"> <el-input v-model="ruleForm.nameCn"></el-input> </el-form-item> <el-form-item label="描述" prop="description"> <el-input v-model="ruleForm.description" type="textarea" rows="3" show-word-limit maxlength="200" ></el-input> </el-form-item> </el-form> <el-form :model="customRuleForm" :rules="customRules" :inline="true" ref="customRuleFormRef" label-width="100px" class="custom-ruleForm" label-position="top" size="mini" :disabled="operateType == 'detail'" > <el-form-item label="发送人类型" prop="fromTypeList"> <el-select v-model="customRuleForm.fromTypeList" multiple @change="dealSelectAll('fromTypeList')" > <el-option v-for="opt in filterOptions.FromTypeEnum" :key="opt.code" :label="opt.info" :value="opt.code" > </el-option> </el-select> </el-form-item> <el-form-item label="接收人类型" prop="toTypeList"> <el-select v-model="customRuleForm.toTypeList" multiple @change="dealSelectAll('toTypeList')" > <el-option v-for="opt in filterOptions.ToTypeEnum" :key="opt.code" :label="opt.info" :value="opt.code" > </el-option> </el-select> </el-form-item> <el-form-item label="消息类型" prop="msgTypeList"> <el-select v-model="customRuleForm.msgTypeList" multiple> <el-option v-for="opt in filterOptions.MsgTypeEnum" :key="opt.code" :label="opt.info" :value="opt.code" > </el-option> </el-select> </el-form-item> <el-form-item label="聊天类型" prop="chatTypeList"> <el-select v-model="customRuleForm.chatTypeList" multiple @change="changeChatTypeList(false)" > <el-option v-for="opt in filterOptions.ChatTypeEnum" :key="opt.code" :label="opt.info" :value="opt.code" > </el-option> </el-select> </el-form-item> <el-form-item label="群聊群主" prop="roomOwnerIdList"> <el-select v-model="customRuleForm.roomOwnerIdList" multiple> <el-option v-for="opt in filterOptions.RoomOwnerIdListEnum" :key="opt.ownerId" :label="opt.ownerName" :value="opt.ownerId" > </el-option> </el-select> </el-form-item> <el-form-item label="群主员工所属部门" prop="roomOwnerDeptList"> <el-select v-model="customRuleForm.roomOwnerDeptList" multiple filterable remote :remote-method="searchDepts" :loading="roomOwnerDeptScroll.loading" v-infinite-scroll="loadMoreDepts" infinite-scroll-disabled="roomOwnerDeptScroll.loading" infinite-scroll-distance="50" > <el-option v-for="opt in filterOptions.RoomOwnerDeptListEnum" :key="opt.id" :label="opt.name" :value="opt.id" > </el-option> <div v-if="roomOwnerDeptScroll.loading" class="loading-text"> 加载中... </div> <div v-if="!roomOwnerDeptScroll.noMore" class="loading-text"> 下拉加载更多... </div> <div v-if="roomOwnerDeptScroll.noMore" class="loading-text"> 没有更多了 </div> </el-select> </el-form-item> <el-form-item label="群聊列表" prop="roomIdList"> <el-select v-model="customRuleForm.roomIdList" multiple @change="changeRoomId(false)" > <el-option v-for="opt in filterOptions.RoomIdListEnum" :key="opt.roomId" :label="opt.roomName" :value="opt.roomId" > </el-option> </el-select> </el-form-item> <el-form-item label="群聊成员白名单" prop="roomExcludeList"> <el-select v-model="customRuleForm.roomExcludeList" multiple> <el-option v-for="opt in filterOptions.roomExcludeListEnum" :key="opt.qwUserId" :label="opt.name" :value="opt.qwUserId" > </el-option> </el-select> </el-form-item> <el-form-item label="群聊关注成员" prop="roomFocueList"> <el-select v-model="customRuleForm.roomFocueList" multiple> <el-option v-for="opt in filterOptions.roomExcludeListEnum" :key="opt.qwUserId" :label="opt.name" :value="opt.qwUserId" > </el-option> </el-select> </el-form-item> <el-form-item label="员工" prop="employeeList"> <private-cloud-member-select-new style="width: 100%" ref="privateCloudMemberUse" placeholder="请选择员工" :defaultCheckedKey="defalutValue.employeeList" mode="member" @selectedMembers="choseEmployeeList" /> </el-form-item> <el-form-item label="部门" prop="deptList"> <private-cloud-member-select-new style="width: 100%" ref="privateCloudDeptUse" mode="group" placeholder="请选择部门" :defaultCheckedKey="defalutValue.deptList" @selectedGroups="choseDeptList" /> </el-form-item> <el-form-item label="是否启用白名单" prop="enableWhite"> <el-switch v-model="customRuleForm.enableWhite" :active-value="1" :inactive-value="0" > </el-switch> </el-form-item> <el-form-item label="正则表达式" prop="textRegex" style="width: 100%"> <vue-json-editor v-model="customRuleForm.textRegex" style="width: 100%" mode="code" lang="zh" ></vue-json-editor> </el-form-item> </el-form> <div class="el-form-item el-form--label-top" style="margin-bottom: 0"> <label for="" class="el-form-item__label">扩展信息</label> <div class="el-form-item__content extra-info"> <vue-json-editor ref="jsonRef" v-model="ext" style="width: 100%" mode="code" lang="zh" ></vue-json-editor> </div> </div> <div slot="footer" class="dialog-footer"> <el-button @click="dialogVisible = false">取消</el-button> <el-button type="primary" @click="save" :disabled="operateType == 'detail'" > 确定 </el-button> </div> </el-dialog> </template> <script> import vueJsonEditor from 'vue-json-editor' import archivesApi from '@/api/archive/index' import dayjs from 'dayjs' import { debounce } from 'lodash' export default { components: { vueJsonEditor, }, props: { type: String, }, data() { return { dialogVisible: false, ruleForm: { nameCn: '', description: '', }, rules: { nameCn: [ { required: true, message: '请输入活动名称', trigger: 'blur' }, { max: 20, message: '长度不能超过20个字符', trigger: 'blur' }, ], }, formConfig: [], customRuleForm: { fromTypeList: null, toTypeList: null, msgTypeList: null, chatTypeList: null, roomOwnerIdList: null, roomOwnerDeptList: null, roomIdList: null, roomExcludeList: null, roomFocueList: null, employeeList: null, deptList: null, enableWhite: 0, textRegex: {}, }, filterOptions: {}, customRules: {}, ext: {}, hasJsonErrorFlag: false, defalutValue: { employeeList: [], deptList: [], }, isEdit: false, operateType: null, editIndex: null, groupData: [], title: { add: '添加', edit: '编辑', detail: '查看', }, roomOwnerDeptScroll: { page: 1, pageSize: 20, loading: false, noMore: false, keyword: '', total: 0, }, } }, watch: { dialogVisible(newVal) { if (!newVal) { this.resetFiled() } }, }, mounted() {}, methods: { // 获取筛选项 async getFilter(filter, ruleType, row = null, index) { this.operateType = ruleType this.isEdit = ruleType === 'edit' ? true : false if (this.isEdit) { this.editIndex = index } this.filterOptions = { ...filter } this.resetScrollData() await this.getRoomList(true) await this.getOwnerDeptList(true) if (ruleType === 'add' && row) { this.$set(this.ruleForm, 'nameCn', row.nameCn) } else if (row) { this.$set(this.ruleForm, 'nameCn', row.nameCn) this.$set(this.ruleForm, 'description', row.description) this.customRuleForm = { ...row } this.customRuleForm.textRegex = JSON.parse(row.textRegex) if (row.ext) { this.ext = JSON.parse(row.ext) } this.defalutValue.employeeList = row.employeeListIds?.map( (item) => `_${item}` || [] ) this.defalutValue.deptList = row.deptList ? [...row.deptList] : [] await this.changeChatTypeList(true) await this.changeRoomId(true) if (row.roomOwnerDeptList) { await this.handleMissingDepts(row.roomOwnerDeptList) } } }, dealSelectAll(type) { if (this.customRuleForm[type]?.includes(0)) { this.customRuleForm[type] = [0] } }, // 获取群主列表或者群聊列表 async getRoomList(isEditInit) { await archivesApi .getRoomList({}) .then((res) => { if (res.data.success) { const data = res.data.data this.groupData = [...data] this.changeChatTypeList(isEditInit) } else { this.$message.error(res.data.msg || '获取失败') } }) .catch(() => {}) }, // 选择群聊类型时 changeChatTypeList(isEditInit = false) { console.log('群聊类型isEditInit', isEditInit) if (this.customRuleForm.chatTypeList?.includes(0)) { this.$set(this.customRuleForm, 'chatTypeList', [0]) } if ( this.customRuleForm.chatTypeList.includes(0) || this.customRuleForm.chatTypeList == null ) { this.filterOptions.RoomOwnerIdListEnum = this.groupData.reduce( (acc, item) => { if (!acc.some((i) => i.ownerId === item.ownerId)) { acc.push(item) } return acc }, [] ) this.filterOptions.RoomIdListEnum = this.groupData.reduce( (acc, item) => { if (!acc.some((i) => i.roomId === item.roomId)) { acc.push(item) } return acc }, [] ) } else { this.filterOptions.RoomOwnerIdListEnum = this.groupData .filter((item) => this.customRuleForm.chatTypeList?.includes(item.chatType) ) .reduce((acc, item) => { if (!acc.some((i) => i.ownerId === item.ownerId)) { acc.push(item) } return acc }, []) this.filterOptions.RoomIdListEnum = this.groupData .filter((item) => this.customRuleForm.chatTypeList?.includes(item.chatType) ) .reduce((acc, item) => { if (!acc.some((i) => i.roomId === item.roomId)) { acc.push(item) } return acc }, []) } if (!isEditInit) { this.customRuleForm.roomOwnerIdList = [] this.customRuleForm.roomIdList = [] this.customRuleForm.roomExcludeList = [] this.customRuleForm.roomFocueList = [] } }, // 选择群列表 async changeRoomId(isEditInit = false) { if (this.customRuleForm.roomIdList?.length) { const params = { roomIds: this.customRuleForm.roomIdList, } await archivesApi .getRoomMemberList(params) .then((res) => { if (res.data.success) { const data = res.data.data this.$set(this.filterOptions, 'roomExcludeListEnum', data) this.filterOptions.roomExcludeListEnum = this.filterOptions.roomExcludeListEnum.reduce((acc, item) => { if (!acc.some((i) => i.qwUserId === item.qwUserId)) { acc.push(item) } return acc }, []) } else { this.filterOptions.roomExcludeListEnum = [] this.$message.error(res.data.msg || '获取失败') } }) .catch(() => {}) console.log('群列表isEditInit', isEditInit) if (!isEditInit) { this.customRuleForm.roomExcludeList = [] this.customRuleForm.roomFocueList = [] } } else { this.filterOptions.roomExcludeListEnum = [] } }, // 获取群主部门 async getOwnerDeptList(init = false) { if (this.roomOwnerDeptScroll.loading) return this.roomOwnerDeptScroll.loading = true if (init) { this.roomOwnerDeptScroll.page = 1 this.filterOptions.RoomOwnerDeptListEnum = [] this.roomOwnerDeptScroll.noMore = false } await archivesApi .getOwnerDeptList({}) .then((res) => { console.log('res', res) if (res.data.success) { const data = res.data.data this.$set(this.filterOptions, 'RoomOwnerDeptListEnum', data) this.roomOwnerDeptScroll.loading = false this.roomOwnerDeptScroll.noMore = false } else { this.$message.error(res.data.msg || '获取失败') } }) .catch(() => {}) }, // 加载更多部门(滚动触发) loadMoreDepts: debounce(function () { console.log('加载更多部门') if ( !this.roomOwnerDeptScroll.loading && !this.roomOwnerDeptScroll.noMore ) { this.roomOwnerDeptScroll.page++ this.getOwnerDeptList() } }, 300), // 部门搜索 searchDepts: debounce(function (query) { this.roomOwnerDeptScroll.keyword = query this.roomOwnerDeptScroll.page = 1 this.getOwnerDeptList(true) }, 500), // 处理编辑时缺失的部门选项(回显) async handleMissingDepts(deptIds) { // 找出当前不在列表中的部门ID const missingIds = deptIds.filter( (id) => !this.filterOptions.RoomOwnerDeptListEnum.some((opt) => opt.id === id) ) // if (missingIds.length > 0) { // try { // const res = await archivesApi.getDeptsByIds({ ids: missingIds }) // if (res.data.success) { // // 将缺失的部门添加到列表开头 // this.deptOptions = [...res.data.data, ...this.deptOptions] // } // } catch (e) { // console.error('加载缺失部门失败', e) // } // } }, // 重置滚动加载相关数据 resetScrollData() { // 部门下拉框 this.filterOptions.RoomOwnerDeptListEnum = [] this.roomOwnerDeptScroll = { page: 1, pageSize: 20, loading: false, noMore: false, keyword: '', total: 0, } }, save() { let isPass = true this.$refs.ruleFormRef.validate((valid) => { if (!valid) { isPass = false } }) this.$refs.customRuleFormRef.validate((valid) => { if (!valid) { isPass = false } }) console.log('筛选项验证通过', this.ext) if (this.$refs.jsonRef.error) { isPass = false this.$message.error('扩展信息JSON格式错误') return } if (!isPass) { return } const params = { ...this.customRuleForm, ...this.ruleForm, textRegex: JSON.stringify(this.customRuleForm.textRegex), ext: JSON.stringify(this.ext), } if (this.isEdit) { params.gmtModified = dayjs().format('YYYY-MM-DD HH:mm:ss') this.$emit('freshData', params, this.type, this.editIndex) } else { params.gmtCreate = dayjs().format('YYYY-MM-DD HH:mm:ss') this.$emit('freshData', params, this.type) } this.resetFiled() this.dialogVisible = false console.log(isPass, 'isPass') }, // 选择员工 choseEmployeeList(val) { const { empList = [] } = val || {} let checkedKey = [] let checkedEmployee = [] let checkedEmployeeIds = [] if (empList && empList.length) { // 回显使用成员id checkedKey = checkedKey.concat(empList.map((x) => `_${x.id}`)) checkedEmployee = checkedEmployee.concat(empList.map((x) => x.qwUserId)) checkedEmployeeIds = checkedEmployeeIds.concat(empList.map((x) => x.id)) } this.defalutValue.employeeList = checkedKey this.customRuleForm.employeeList = checkedEmployee this.customRuleForm.employeeListIds = checkedEmployeeIds }, // 选择部门 choseDeptList(val) { const { deptList = [] } = val || {} let checkedKey = [] // 员工回显 if (deptList && deptList.length) { checkedKey = deptList.map((x) => x.nodeId) } this.defalutValue.deptList = checkedKey this.customRuleForm.deptList = checkedKey }, resetFiled() { this.ruleForm = { nameCn: '', description: '', } this.customRuleForm = { fromTypeList: null, toTypeList: null, msgTypeList: null, chatTypeList: null, roomOwnerIdList: null, roomOwnerDeptList: null, roomIdList: null, roomExcludeList: null, roomFocueList: null, employeeList: null, deptList: null, enableWhite: 0, textRegex: {}, employeeListIds: null, } this.defalutValue = { employeeList: [], deptList: [], } this.$refs.privateCloudMemberUse.reset() this.$refs.privateCloudDeptUse.reset() this.$refs.ruleFormRef.resetFields() this.$refs.customRuleFormRef.resetFields() this.ext = {} }, }, } </script> <style lang="scss" scoped> ::v-deep .el-form-item__label { line-height: 1; } .dialog-footer { display: flex; justify-content: flex-end; } .extra-info { display: flex; margin-bottom: 10px; .delete-icon { margin-left: 10px; } } ::v-deep .el-dialog { height: auto; margin-top: 8vh; .el-dialog__body { height: 60vh; overflow: auto; } } .custom-ruleForm { .el-form-item { width: 30%; .el-select { width: 100%; } } } ::v-deep a.jsoneditor-poweredBy { display: none; } .loading-text { padding: 4px 0; text-align: center; color: #999; font-size: 12px; } </style> el-select v-infinite-scroll不生效
10-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值