cascader.vue 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <template>
  2. <div>
  3. <el-form-item label="占位内容">
  4. <el-input v-model="data.placeholder"
  5. placeholder="占位内容"></el-input>
  6. </el-form-item>
  7. <el-form-item label="默认值">
  8. <el-input v-model="data.valueDefault"
  9. placeholder="默认值"></el-input>
  10. </el-form-item>
  11. <el-form-item label="字典配置"><br>
  12. <el-tabs v-model="data.dicOption"
  13. stretch
  14. @tab-click="handleTabClick">
  15. <el-tab-pane label="静态数据"
  16. name="static">
  17. <el-tree ref="tree"
  18. :data="data.dicData"
  19. default-expand-all
  20. draggable
  21. node-key="value"
  22. :expand-on-click-node="false">
  23. <span class="custom-tree-node"
  24. slot-scope="{ node, data }">
  25. <span>{{ node.label }}</span>
  26. <span>
  27. <el-button type="text"
  28. size="mini"
  29. icon="el-icon-plus"
  30. @click="handleNodeAdd(data)"></el-button>
  31. <!-- <el-button class="warning" type="text" size="mini" icon="el-icon-edit"-->
  32. <!-- @click="handleNodeEdit(data)"></el-button>-->
  33. <el-button class="danger"
  34. type="text"
  35. size="mini"
  36. icon="el-icon-delete"
  37. @click="handleNodeRemove(node, data)"></el-button>
  38. </span>
  39. </span>
  40. </el-tree>
  41. <div style="margin-left: 22px;">
  42. <el-button type="text"
  43. @click="handleParentNodeAdd">添加父级
  44. </el-button>
  45. </div>
  46. </el-tab-pane>
  47. <el-tab-pane label="远端数据"
  48. name="remote">
  49. 网址
  50. <el-input v-model="data.dicUrl"
  51. placeholder="远端数据字典网址"></el-input>
  52. 请求方法
  53. <el-select v-model="data.dicMethod"
  54. placeholder="请求方法"
  55. style="width: 100%;">
  56. <el-option label="POST"
  57. value="post"></el-option>
  58. <el-option label="GET"
  59. value="get"></el-option>
  60. </el-select>
  61. <p v-if="data.dicMethod == 'post'">
  62. 请求参数
  63. <avue-dynamic v-model="data.dicQuery"
  64. :children="option"></avue-dynamic>
  65. </p>
  66. </el-tab-pane>
  67. </el-tabs>
  68. </el-form-item>
  69. <el-form-item label="选项分隔符">
  70. <el-input v-model="data.separator"
  71. placeholder="选项分隔符"></el-input>
  72. </el-form-item>
  73. <el-form-item label="是否显示选中值的完整路径">
  74. <el-switch v-model="data.showAllLevels"></el-switch>
  75. </el-form-item>
  76. <el-form-item label="是否可清空">
  77. <el-switch v-model="data.clearable"></el-switch>
  78. </el-form-item>
  79. <el-form-item label="是否可搜索">
  80. <el-switch v-model="data.filterable"></el-switch>
  81. </el-form-item>
  82. <el-form-item label="是否禁用">
  83. <el-switch v-model="data.disabled"></el-switch>
  84. </el-form-item>
  85. <el-form-item label="是否可见">
  86. <el-switch v-model="data.display"></el-switch>
  87. </el-form-item>
  88. <el-form-item label="是否必填">
  89. <el-switch v-model="data.required"></el-switch>
  90. </el-form-item>
  91. <el-dialog :visible.sync="dialogVisible"
  92. :rules="dialogRules"
  93. :before-close="beforeClose">
  94. <el-form ref="dialogForm"
  95. :model="dialogForm"
  96. label-width="80px">
  97. <el-form-item label="label">
  98. <el-input v-model="dialogForm.label"
  99. placeholder="label"></el-input>
  100. </el-form-item>
  101. <el-form-item label="value">
  102. <el-input v-model="dialogForm.value"
  103. placeholder="value"
  104. :type="this.dialogInputType">
  105. <el-select v-model="dialogInputType"
  106. slot="append"
  107. placeholder="数据类型"
  108. style="width: 100px">
  109. <el-option label="String"
  110. value="text"></el-option>
  111. <el-option label="Number"
  112. value="number"></el-option>
  113. </el-select>
  114. </el-input>
  115. </el-form-item>
  116. </el-form>
  117. <span slot="footer"
  118. class="dialog-footer">
  119. <el-button @click="dialogVisible = false">取 消</el-button>
  120. <el-button type="primary"
  121. @click="handleDialogAdd"
  122. v-if="dialogStatus == 'add'">确 定</el-button>
  123. <!-- <el-button type="primary" @click="handleDialogUpdate" v-else>确 定</el-button>-->
  124. </span>
  125. </el-dialog>
  126. </div>
  127. </template>
  128. <script>
  129. export default {
  130. name: "config-cascader",
  131. props: ['data'],
  132. data () {
  133. return {
  134. validator: {
  135. type: null,
  136. required: null,
  137. pattern: null,
  138. length: null
  139. },
  140. dialogForm: {},
  141. dialogVisible: false,
  142. dialogRules: {
  143. label: { required: true, message: '请输入label' },
  144. value: { required: true, message: '请输入value' },
  145. },
  146. dialogStatus: 'add',
  147. selectData: undefined,
  148. dialogInputType: 'text',
  149. option: {
  150. column: [{
  151. type: 'input',
  152. prop: 'key',
  153. label: 'key'
  154. }, {
  155. type: 'input',
  156. prop: 'value',
  157. label: 'value'
  158. }]
  159. },
  160. }
  161. },
  162. methods: {
  163. generateRule () {
  164. const rules = [];
  165. Object.keys(this.validator).forEach(key => {
  166. if (this.validator[key]) rules.push(this.validator[key])
  167. })
  168. this.data.rules = rules
  169. },
  170. handleTabClick ({ name }) {
  171. if (name == 'remote' && !this.data.dicQuery) this.data.dicQuery = []
  172. },
  173. handleParentNodeAdd () {
  174. this.selectData = undefined
  175. this.dialogStatus = 'add';
  176. this.dialogVisible = true;
  177. },
  178. handleNodeAdd (data) {
  179. this.selectData = data;
  180. this.dialogStatus = 'add';
  181. this.dialogVisible = true;
  182. },
  183. handleNodeRemove (node, data) {
  184. const parent = node.parent;
  185. const children = parent.data.children || parent.data;
  186. const index = children.findIndex(d => d.id === data.id);
  187. children.splice(index, 1);
  188. },
  189. handleDialogAdd () {
  190. this.$refs.dialogForm.validate((valid) => {
  191. if (valid) {
  192. const { label, value } = this.dialogForm;
  193. const node = this.$refs.tree.getNode(value)
  194. if (node) this.$message.error("value重复")
  195. else {
  196. const data = this.selectData
  197. const newNode = {
  198. label,
  199. value: this.dialogInputType == 'number' ? Number(value) : value,
  200. }
  201. if (data) {
  202. if (!data.children) this.$set(data, 'children', [])
  203. data.children.push(newNode)
  204. } else {
  205. this.$set(this.data.dicData, this.data.dicData.length, newNode)
  206. }
  207. this.beforeClose()
  208. }
  209. }
  210. })
  211. },
  212. beforeClose () {
  213. this.$refs.dialogForm.clearValidate()
  214. this.dialogForm = {}
  215. this.dialogVisible = false
  216. }
  217. },
  218. watch: {
  219. 'data.required': function (val) {
  220. if (val) this.validator.required = { required: true, message: `请选择${this.data.label}` }
  221. else this.validator.required = null
  222. this.generateRule()
  223. }
  224. }
  225. }
  226. </script>
  227. <style lang="scss" scoped>
  228. .custom-tree-node {
  229. flex: 1;
  230. display: flex;
  231. align-items: center;
  232. justify-content: space-between;
  233. font-size: 14px;
  234. padding-right: 8px;
  235. }
  236. </style>