cascadeSelection.vue 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. <template>
  2. <div class='cascadeSelection'>
  3. <!-- 框框 -->
  4. <div ref="focusDiv" tabindex="0" :class="`input ${size} ${disabled ? 'inputDisabled' : ''}`"
  5. :style="`width: ${width}`" @focus="handleFocus" @blur="handleBlur">
  6. <!-- 默认提示文字 -->
  7. <span class="placeholderColor" v-if="resultText.length == 0">请选择</span>
  8. <!-- 选中数据 -->
  9. <div v-if="resultText.length > 0" class="textEllipsisNowrap">
  10. <template v-for="(item, index) in resultText[0]">
  11. <TranslationOpenDataText type='departmentName' :openid='item'></TranslationOpenDataText>
  12. <span v-if="index < resultText[0].length - 1" class="textSpan">/</span>
  13. </template>
  14. </div>
  15. <i v-if="resultText.length > 0" class="el-icon-circle-close iostu" @click.stop="clearDelete"></i>
  16. <!-- 级联面板 -->
  17. <div class="absoluteWeight" v-if="isFocused" :style="`top: ${sizeTop[size]}`">
  18. <el-cascader-panel v-model="modelValue" ref="cascaderPanelRef" :options="options" :props="props"
  19. @change="panelChange">
  20. <template slot-scope="{ node, data }">
  21. <TranslationOpenDataText type='departmentName' :openid='data.label'></TranslationOpenDataText>
  22. </template>
  23. </el-cascader-panel>
  24. </div>
  25. </div>
  26. </div>
  27. </template>
  28. <script>
  29. export default {
  30. name: '',
  31. components: {},
  32. props: {
  33. modelValue: {
  34. type: Array,
  35. default: () => []
  36. },
  37. size: {
  38. type: String,
  39. default: 'default',
  40. },
  41. width: {
  42. type: String,
  43. default: '100%',
  44. },
  45. options: {
  46. type: Array,
  47. default: () => [],
  48. },
  49. props: {
  50. type: Object,
  51. default: () => {
  52. return { checkStrictly: true, expandTrigger: 'hover' }
  53. }
  54. },
  55. disabled: {
  56. type: Boolean,
  57. default: false
  58. }
  59. },
  60. data() {
  61. return {
  62. isFocused: false,
  63. resultText: [],
  64. sizeTop: {
  65. default: '40px',
  66. medium: '36px',
  67. small: '32px',
  68. mini: '24px'
  69. }
  70. }
  71. },
  72. computed: {},
  73. watch: {},
  74. created() { },
  75. mounted() {
  76. setTimeout(() => {
  77. if ((this.modelValue || []).length > 0) {
  78. this.resultText = this.findDepartmentNames(this.options, this.props.multiple ? this.modelValue : [this.modelValue]);
  79. }
  80. }, 500)
  81. },
  82. model: {
  83. prop: 'modelValue',
  84. event: 'getValue'
  85. },
  86. methods: {
  87. panelChange(val) {
  88. this.resultText = this.findDepartmentNames(this.options, this.props.multiple ? val : [val]);
  89. this.updateModelValue()
  90. },
  91. findDepartmentNames(data, values) {
  92. const findLabels = (valueList) => {
  93. return valueList.map(value => {
  94. const findLabel = (data, value) => {
  95. for (let item of data) {
  96. if (item.value === value) {
  97. return item.label;
  98. }
  99. if (item.children) {
  100. const label = findLabel(item.children, value);
  101. if (label) return label;
  102. }
  103. }
  104. return null;
  105. };
  106. return findLabel(data, value);
  107. }).filter(label => label !== null);
  108. };
  109. return values.map(valueList => findLabels(valueList));
  110. },
  111. handleFocus() {
  112. if(this.disabled) {
  113. return
  114. }
  115. this.isFocused = true
  116. this.$refs.focusDiv.classList.add('focused');
  117. },
  118. handleBlur(event) {
  119. if(this.disabled) {
  120. return
  121. }
  122. if (this.$refs.focusDiv.contains(event.relatedTarget)) {
  123. this.$refs.focusDiv.focus();
  124. event.preventDefault();
  125. return;
  126. }
  127. this.isFocused = false
  128. this.$refs.focusDiv.classList.remove('focused');
  129. },
  130. clearDelete() {
  131. this.$refs.focusDiv.blur()
  132. this.resultText = [];
  133. this.$emit('getValue', []);
  134. this.$emit('change', []);
  135. },
  136. updateModelValue() {
  137. this.$emit('getValue', this.modelValue);
  138. this.$emit('change', this.modelValue);
  139. }
  140. },
  141. }
  142. </script>
  143. <style scoped lang='scss'>
  144. @import "../assets/scss/handle";
  145. .cascadeSelection {
  146. position: relative;
  147. max-height: 40px;
  148. .default {
  149. height: 40px;
  150. line-height: 40px;
  151. }
  152. .medium {
  153. height: 36px;
  154. line-height: 36px;
  155. }
  156. .small {
  157. height: 32px;
  158. line-height: 32px;
  159. }
  160. .mini {
  161. height: 28px;
  162. line-height: 28px;
  163. }
  164. .input {
  165. position: relative;
  166. font-size: 14px;
  167. background-color: #FFF;
  168. background-image: none;
  169. border-radius: 4px;
  170. border: 1px solid #DCDFE6;
  171. box-sizing: border-box;
  172. color: #606266;
  173. display: inline-block;
  174. outline: 0;
  175. padding: 0 15px;
  176. -webkit-transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
  177. transition: border-color .2s cubic-bezier(.645, .045, .355, 1);
  178. width: 100%;
  179. }
  180. .input:focus {
  181. @include border_color("border_color");
  182. }
  183. .placeholderColor {
  184. color: #C0C4CC;
  185. }
  186. .absoluteWeight {
  187. position: absolute;
  188. z-index: 99;
  189. background: #fff;
  190. left: 0;
  191. }
  192. .textSpan {
  193. display: inline-block;
  194. padding: 0 3px
  195. }
  196. .textEllipsisNowrap {
  197. width: 100%;
  198. overflow: hidden;
  199. text-overflow: ellipsis;
  200. white-space: nowrap;
  201. }
  202. .iostu {
  203. position: absolute;
  204. top: 50%;
  205. margin-top: -4px;
  206. right: 8px;
  207. color: #C0C4CC;
  208. transition: All 0.2s ease-in-out;
  209. }
  210. .iostuHover {
  211. transform: rotate(-180deg);
  212. }
  213. .inputDisabled {
  214. background-color: #f5f7fa !important;
  215. border-color: #e4e7ed !important;
  216. color: #c0c4cc !important;
  217. cursor: not-allowed !important;
  218. }
  219. }
  220. </style>