index.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. <!--
  2. * @description: 设置组件关联的公共组件
  3. * @Date: 2023-01-04 14:42:51
  4. * @Author: xing.heng
  5. * @LastEditors: wujian
  6. * @LastEditTime: 2023-06-02 15:35:43
  7. -->
  8. <template>
  9. <div>
  10. <div class="data-setting-data-box">
  11. <div class="lc-field-head">
  12. <div class="lc-field-title">
  13. 组件联动
  14. </div>
  15. </div>
  16. <div class="lc-field-body">
  17. <div class="select-item select-item-title">
  18. <span class="input-wrap">目标组件</span>
  19. <span class="input-wrap">操作</span>
  20. </div>
  21. <div
  22. v-for="(field, index) in config.linkage.components"
  23. :key="index"
  24. class="select-item"
  25. :class="{ 'select-item-active': field.componentKey === activeCode }"
  26. @mouseenter="chooseComponent(field)"
  27. >
  28. <div class="input-wrap">
  29. <el-form-item
  30. label-width="0px"
  31. >
  32. <el-select
  33. v-model="field.componentKey"
  34. popper-class="bs-el-select"
  35. class="bs-el-select"
  36. size="mini"
  37. @change="changeComponent(...arguments, index)"
  38. >
  39. <el-option
  40. v-for="item in allComponentsExpectSelf(config.code)"
  41. :key="item.componentKey"
  42. :label="item.name"
  43. :value="item.componentKey"
  44. :disabled="currentLinkComponentKey.includes(item.componentKey)"
  45. />
  46. </el-select>
  47. </el-form-item>
  48. </div>
  49. <div class="input-wrap">
  50. <div
  51. class="select-line-icon option-add"
  52. @click="setRelation(field)"
  53. >
  54. <el-tooltip
  55. effect="dark"
  56. content="组件联动设置"
  57. placement="top"
  58. >
  59. <i class="el-icon-setting" />
  60. </el-tooltip>
  61. </div>
  62. <div
  63. class="select-line-icon option-delete"
  64. @click="deleteLinkComponents(index)"
  65. >
  66. <i class="el-icon-remove-outline" />
  67. </div>
  68. </div>
  69. </div>
  70. <el-button
  71. v-block
  72. type="primary"
  73. @click="addLinkComponents"
  74. >
  75. 新增联动组件
  76. </el-button>
  77. </div>
  78. </div>
  79. <RelationSetting
  80. :setting-visible.sync="settingVisible"
  81. :config-map="configMap"
  82. :source-field-list="sourceFieldList"
  83. :target-field-list="targetFieldList"
  84. @updateConfig="updateConfig"
  85. />
  86. </div>
  87. </template>
  88. <script>
  89. import RelationSetting from './RelationSetting.vue'
  90. import { cloneDeep } from 'lodash'
  91. import { mapState } from 'vuex'
  92. export default {
  93. name: 'ComponentRelation',
  94. components: {
  95. RelationSetting
  96. },
  97. directives: {
  98. block: {
  99. bind (el, binding) {
  100. el.style.width = binding.value || '100%'
  101. }
  102. }
  103. },
  104. props: {
  105. config: {
  106. type: Object,
  107. default: () => {}
  108. },
  109. // 当前组件的联动字段
  110. sourceFieldList: {
  111. type: Array,
  112. default: () => [
  113. // {
  114. // label: '字段1',
  115. // value: 'field1'
  116. // }
  117. ]
  118. }
  119. },
  120. data () {
  121. return {
  122. // 关联设置弹窗
  123. settingVisible: false,
  124. cloneDeepConfig: cloneDeep(this.config),
  125. configMap: {},
  126. targetFieldList: [],
  127. activeCode: null
  128. }
  129. },
  130. computed: {
  131. ...mapState({
  132. chartList: state => state.bigScreen.pageInfo.chartList
  133. }),
  134. // 当前已经关联的组件key
  135. currentLinkComponentKey () {
  136. return this.config.linkage.components?.map(item => item.componentKey) || []
  137. }
  138. },
  139. mounted () {
  140. },
  141. beforeDestroy () {
  142. },
  143. methods: {
  144. /**
  145. * @description: 获取除自己之外的所有组件
  146. */
  147. allComponentsExpectSelf (code) {
  148. let layouts = cloneDeep(this.chartList)
  149. const tabComponents = []
  150. layouts?.map((ly) => {
  151. if (ly.type === 'Tabs') {
  152. ly?.tabList?.map(com => {
  153. tabComponents.push(com.chart)
  154. })
  155. }
  156. })
  157. layouts = layouts?.filter(item => item.code !== code && item?.option?.displayOption?.dataAllocation?.enable)
  158. layouts = [...layouts, ...tabComponents]?.map(item => ({
  159. name: item.title,
  160. componentKey: item.code
  161. }))
  162. return layouts
  163. },
  164. /**
  165. * @description: 添加关联组件
  166. */
  167. addLinkComponents () {
  168. this.config.linkage.components.push({
  169. componentKey: '',
  170. maps: []
  171. })
  172. },
  173. /**
  174. * @description: 删除关联组件
  175. */
  176. deleteLinkComponents (index) {
  177. this.config.linkage.components.splice(index, 1)
  178. },
  179. /**
  180. * @description: 改变关联组件
  181. */
  182. changeComponent (componentKey, index) {
  183. this.$set(
  184. this.config.linkage.components,
  185. index,
  186. {
  187. componentKey,
  188. maps: []
  189. }
  190. )
  191. },
  192. /**
  193. * @description: 设置关联弹窗打开
  194. */
  195. setRelation (configMap) {
  196. this.settingVisible = true
  197. // 如果是tab页内部组件,先平铺
  198. let layouts = cloneDeep(this.chartList)
  199. const tabComponents = []
  200. layouts?.map((ly) => {
  201. if (ly.type === 'Tabs') {
  202. ly?.tabList?.map(com => {
  203. tabComponents.push(com.chart)
  204. })
  205. }
  206. })
  207. layouts = layouts?.filter(item => item?.option?.displayOption?.dataAllocation?.enable)
  208. layouts = [...layouts, ...tabComponents]
  209. this.targetFieldList = layouts.find(
  210. item => item.code === configMap.componentKey
  211. )?.inParams?.map(item => ({
  212. label: item.name,
  213. value: item.code
  214. }))
  215. this.configMap = cloneDeep(configMap)
  216. },
  217. /**
  218. * @description: 更新关联配置
  219. */
  220. updateConfig (configMapConfig) {
  221. const index = this.config.linkage.components?.findIndex(
  222. item => item.componentKey === configMapConfig.componentKey
  223. )
  224. this.$set(
  225. this.config.linkage.components,
  226. index,
  227. configMapConfig
  228. )
  229. },
  230. /**
  231. * @description: 选择组件
  232. */
  233. chooseComponent (field) {
  234. this.activeCode = field?.componentKey
  235. }
  236. }
  237. }
  238. </script>
  239. <style scoped lang="scss">
  240. ::v-deep .el-tabs__nav-scroll {
  241. display: flex;
  242. justify-content: center;
  243. }
  244. ::v-deep .el-tabs__nav-wrap::after {
  245. height: 0;
  246. }
  247. ::v-deep .el-collapse-item__header {
  248. background: #f2f3f5;
  249. height: 32px;
  250. padding: 0 12px;
  251. }
  252. ::v-deep .el-collapse-item__content {
  253. padding-bottom: 0;
  254. }
  255. .lc-field-body {
  256. padding: 12px;
  257. }
  258. ::v-deep .el-tabs__nav-scroll {
  259. display: flex;
  260. justify-content: center;
  261. }
  262. ::v-deep .el-tabs__nav-wrap::after {
  263. height: 0;
  264. }
  265. .design-tab-warp {
  266. padding: 10px;
  267. }
  268. ::v-deep.el-tabs--top {
  269. height: 100%;
  270. }
  271. ::v-deep .el-tabs__content {
  272. height: calc(100% - 40px);
  273. overflow-y: auto;
  274. }
  275. .setting-body {
  276. height: 100%;
  277. }
  278. // 筛选条件的按钮样式
  279. .add-filter-box {
  280. position: relative;
  281. .add-filter {
  282. margin-left: 90px;
  283. margin-bottom: 10px;
  284. }
  285. .add-filter-btn {
  286. position: absolute;
  287. top: 0;
  288. }
  289. }
  290. .select-item {
  291. display: flex;
  292. margin-bottom: 8px;
  293. cursor: pointer;
  294. align-items: center;
  295. border: 1px solid #fff;
  296. padding: 4px;
  297. .input-wrap {
  298. flex: 1;
  299. display: flex;
  300. justify-content: center;
  301. margin-right: 2px;
  302. ::v-deep.el-form-item {
  303. margin-bottom: 0 !important;
  304. }
  305. .el-input-number--mini {
  306. width: 90px !important;
  307. }
  308. }
  309. .input-wrap_left {
  310. flex: 1;
  311. display: flex;
  312. align-items: center;
  313. justify-content: left;
  314. }
  315. .select-line-icon {
  316. width: 30px;
  317. font-size: 18px;
  318. cursor: pointer;
  319. text-align: center;
  320. }
  321. .option-delete {
  322. color: #f56c6c;
  323. }
  324. }
  325. .select-item-active {
  326. border: 1px solid var(--bs-el-color-primary);
  327. background: var(--bs-el-background-3);
  328. }
  329. // 修改设置面板样式
  330. .data-setting-box{
  331. .data-setting-data-box{
  332. .lc-field-head{
  333. height: 30px;
  334. .lc-field-title{
  335. position: relative;
  336. padding-left: 12px;
  337. line-height: 30px;
  338. height: 30px;
  339. &:after{
  340. position: absolute;
  341. left: 0;
  342. top: 50%;
  343. transform: translateY(-50%);
  344. content: '';
  345. width: 4px;
  346. height: 14px;
  347. background-color: var(--bs-el-color-primary);
  348. }
  349. }
  350. }
  351. }
  352. }
  353. </style>