ExpressionDialog.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. <template>
  2. <el-dialog
  3. :close-on-click-modal="false"
  4. title="表达式"
  5. width="60%"
  6. :visible.sync="formVisible"
  7. :append-to-body="false"
  8. class="bs-dialog-wrap bs-el-dialog"
  9. >
  10. <div class="main-box">
  11. <div class="left-box">
  12. <el-tree
  13. ref="tree"
  14. :data="treeData"
  15. :indent="0"
  16. :props="{ label: 'label', children: 'children' }"
  17. :default-expand-all="true"
  18. :highlight-current="true"
  19. :expand-on-click-node="false"
  20. class="bs-el-tree tree-box"
  21. @node-click="handleNodeClick"
  22. />
  23. </div>
  24. <div class="right-box">
  25. <div class="codemirror-wrap">
  26. <codemirror
  27. ref="codemirrorRef"
  28. v-model="currentConfig.expression"
  29. class="codemirror-box"
  30. :options="codemirrorOption"
  31. @dragover.prevent
  32. />
  33. <el-button
  34. class="btn-box"
  35. type="primary"
  36. @click="executeScript"
  37. >
  38. 运行脚本
  39. </el-button>
  40. </div>
  41. <div class="script-content-box">
  42. {{ scriptContent }}
  43. </div>
  44. </div>
  45. </div>
  46. <div
  47. slot="footer"
  48. class="dialog-footer"
  49. >
  50. <el-button
  51. class="bs-el-button-default cancel"
  52. @click="cancel"
  53. >
  54. 取消
  55. </el-button>
  56. <el-button
  57. type="primary"
  58. @click="sure"
  59. >
  60. 确定
  61. </el-button>
  62. </div>
  63. </el-dialog>
  64. </template>
  65. <script>
  66. import { codemirror } from 'vue-codemirror'
  67. import 'codemirror/mode/javascript/javascript'
  68. import 'codemirror/lib/codemirror.css'
  69. import 'codemirror/theme/nord.css'
  70. import { mapMutations, mapState } from 'vuex'
  71. import cloneDeep from 'lodash/cloneDeep'
  72. export default {
  73. name: 'ExpressionDialog',
  74. components: {
  75. codemirror
  76. },
  77. props: {
  78. config: {
  79. type: Object,
  80. default: () => {
  81. }
  82. }
  83. },
  84. data () {
  85. return {
  86. scriptContent: '', // 脚本执行的内容
  87. expression: '123',
  88. formVisible: false,
  89. codemirrorOption: {
  90. mode: 'text/javascript',
  91. lineNumbers: true,
  92. lineWrapping: true,
  93. theme: 'nord',
  94. extraKey: { Ctrl: 'autocomplete' },
  95. hintOptions: {
  96. completeSingle: true
  97. }
  98. }
  99. }
  100. },
  101. computed: {
  102. ...mapState({
  103. dataset: state => state.bigScreen.dataset,
  104. computedDatas: state => state.bigScreen.computedDatas
  105. }),
  106. // 获取树节点数据
  107. treeData () {
  108. const list = []
  109. for (const item in this.dataset) {
  110. const fields = Object.keys(this.dataset[item][0])
  111. const children = fields.map((field) => {
  112. return {
  113. label: field,
  114. code: item,
  115. value: `dataset.${item}[0].${field}`
  116. }
  117. })
  118. list.push({
  119. label: item,
  120. code: item,
  121. value: `dataset.${item}`,
  122. children
  123. })
  124. }
  125. for (const item in this.computedDatas) {
  126. list.push({
  127. label: item,
  128. code: item,
  129. value: `computedDatas.${item}`
  130. })
  131. }
  132. return list
  133. },
  134. currentConfig () {
  135. return cloneDeep(this.config)
  136. }
  137. },
  138. watch: {},
  139. created () {},
  140. mounted () {},
  141. methods: {
  142. ...mapMutations({
  143. changeChartConfig: 'bigScreen/changeChartConfig'
  144. }),
  145. init () {
  146. this.formVisible = true
  147. },
  148. // 运行脚本
  149. executeScript () {
  150. // eslint-disable-next-line no-new-func
  151. const result = new Function('dataset', 'computedDatas', this.currentConfig.expression)
  152. this.scriptContent = result(this.dataset, this.computedDatas)
  153. },
  154. // 点击树节点将数据添加到脚本编辑器中
  155. handleNodeClick (node, data, nodeObj) {
  156. console.log(node, data, nodeObj)
  157. const str = node.value
  158. const code = node.code
  159. this.$refs.codemirrorRef.codemirror.setValue(this.currentConfig.expression + ' + ' + str)
  160. // 同时将点击的数据存在expressionCodes中
  161. if (this.currentConfig.expressionCodes && Array.isArray(this.currentConfig.expressionCodes)) {
  162. this.currentConfig.expressionCodes.push(code)
  163. }
  164. },
  165. cancel () {
  166. this.formVisible = false
  167. },
  168. sure () {
  169. this.formVisible = false
  170. this.changeChartConfig(this.currentConfig)
  171. }
  172. }
  173. }
  174. </script>
  175. <style scoped lang="scss">
  176. @import '../../assets/style/bsTheme.scss';
  177. .bs-dialog-wrap{
  178. ::v-deep.el-dialog__body{
  179. min-height: 500px;
  180. }
  181. }
  182. .main-box{
  183. width: 100%;
  184. height: 500px;
  185. display: flex;
  186. .left-box{
  187. flex: 1;
  188. height: 100%;
  189. .tree-box{
  190. height: 100%;
  191. overflow-y: auto;
  192. }
  193. }
  194. .right-box{;
  195. flex: 3 ;
  196. height: 100%;
  197. .codemirror-wrap{
  198. height: 50%;
  199. position: relative;
  200. .btn-box{
  201. position: absolute;
  202. right: 10px;
  203. bottom: 10px;
  204. }
  205. }
  206. .codemirror-box {
  207. height: 100% !important;
  208. ::v-deep .CodeMirror {
  209. height: 100% !important;
  210. font-family: Helvetica, Tahoma;
  211. }
  212. }
  213. .script-content-box{
  214. padding:10px
  215. }
  216. }
  217. }
  218. </style>