ComponentProps.vue 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <!--
  2. * @Description: 组件属性控件
  3. -->
  4. <template>
  5. <div class="properties-content">
  6. <div class="properties-body" v-if="formConfig.currentItem">
  7. <Empty class="hint-box" v-if="!formConfig.currentItem.key" description="未选择组件" />
  8. <Form label-align="left" layout="vertical">
  9. <!-- 循环遍历渲染组件属性 -->
  10. <div v-if="formConfig.currentItem && formConfig.currentItem.componentProps">
  11. <FormItem v-for="item in inputOptions" :key="item.name" :label="item.label">
  12. <!-- 处理数组属性,placeholder -->
  13. <div v-if="item.children">
  14. <component
  15. v-for="(child, index) of item.children"
  16. :key="index"
  17. v-bind="child.componentProps"
  18. :is="child.component"
  19. v-model:value="formConfig.currentItem.componentProps[item.name][index]"
  20. />
  21. </div>
  22. <!-- 如果不是数组,则正常处理属性值 -->
  23. <component
  24. v-else
  25. class="component-prop"
  26. v-bind="item.componentProps"
  27. :is="item.component"
  28. v-model:value="formConfig.currentItem.componentProps[item.name]"
  29. />
  30. </FormItem>
  31. <FormItem label="控制属性">
  32. <Col v-for="item in controlOptions" :key="item.name">
  33. <Checkbox
  34. v-if="showControlAttrs(item.includes)"
  35. v-bind="item.componentProps"
  36. v-model:checked="formConfig.currentItem.componentProps[item.name]"
  37. >
  38. {{ item.label }}
  39. </Checkbox>
  40. </Col>
  41. </FormItem>
  42. </div>
  43. <FormItem label="关联字段">
  44. <Select
  45. mode="multiple"
  46. v-model:value="formConfig.currentItem['link']"
  47. :options="linkOptions"
  48. />
  49. </FormItem>
  50. <FormItem
  51. label="选项"
  52. v-if="
  53. [
  54. 'Select',
  55. 'CheckboxGroup',
  56. 'RadioGroup',
  57. 'TreeSelect',
  58. 'Cascader',
  59. 'AutoComplete',
  60. ].includes(formConfig.currentItem.component)
  61. "
  62. >
  63. <FormOptions />
  64. </FormItem>
  65. <FormItem label="栅格" v-if="['Grid'].includes(formConfig.currentItem.component)">
  66. <FormOptions />
  67. </FormItem>
  68. </Form>
  69. </div>
  70. </div>
  71. </template>
  72. <script lang="ts">
  73. import {
  74. Empty,
  75. Input,
  76. Form,
  77. FormItem,
  78. Switch,
  79. Checkbox,
  80. Select,
  81. InputNumber,
  82. RadioGroup,
  83. } from 'ant-design-vue';
  84. import RadioButtonGroup from '/@/components/Form/src/components/RadioButtonGroup.vue';
  85. import { Col, Row } from 'ant-design-vue';
  86. import { computed, defineComponent, ref, watch } from 'vue';
  87. import { useFormDesignState } from '../../../hooks/useFormDesignState';
  88. import {
  89. baseComponentControlAttrs,
  90. baseComponentAttrs,
  91. baseComponentCommonAttrs,
  92. componentPropsFuncs,
  93. } from '../../VFormDesign/config/componentPropsConfig';
  94. import FormOptions from './FormOptions.vue';
  95. import { formItemsForEach, remove } from '../../../utils';
  96. import { IBaseFormAttrs } from '../config/formItemPropsConfig';
  97. export default defineComponent({
  98. name: 'ComponentProps',
  99. components: {
  100. FormOptions,
  101. Empty,
  102. Input,
  103. Form,
  104. FormItem,
  105. Switch,
  106. Checkbox,
  107. Select,
  108. InputNumber,
  109. RadioGroup,
  110. RadioButtonGroup,
  111. Col,
  112. Row,
  113. },
  114. setup() {
  115. // 让compuated属性自动更新
  116. const allOptions = ref([] as Omit<IBaseFormAttrs, 'tag'>[]);
  117. const showControlAttrs = (includes: string[] | undefined) => {
  118. if (!includes) return true;
  119. return includes.includes(formConfig.value.currentItem!.component);
  120. };
  121. const { formConfig } = useFormDesignState();
  122. if (formConfig.value.currentItem) {
  123. formConfig.value.currentItem.componentProps =
  124. formConfig.value.currentItem.componentProps || {};
  125. }
  126. watch(
  127. () => formConfig.value.currentItem?.field,
  128. (_newValue, oldValue) => {
  129. formConfig.value.schemas &&
  130. formItemsForEach(formConfig.value.schemas, (item) => {
  131. if (item.link) {
  132. const index = item.link.findIndex((linkItem) => linkItem === oldValue);
  133. index !== -1 && remove(item.link, index);
  134. }
  135. });
  136. },
  137. );
  138. watch(
  139. () => formConfig.value.currentItem && formConfig.value.currentItem.component,
  140. () => {
  141. allOptions.value = [];
  142. baseComponentControlAttrs.forEach((item) => {
  143. item.category = 'control';
  144. if (!item.includes) {
  145. // 如果属性没有include,所有的控件都适用
  146. allOptions.value.push(item);
  147. } else if (item.includes.includes(formConfig.value.currentItem!.component)) {
  148. // 如果有include,检查是否包含了当前控件类型
  149. allOptions.value.push(item);
  150. }
  151. });
  152. baseComponentCommonAttrs.forEach((item) => {
  153. item.category = 'input';
  154. if (item.includes) {
  155. if (item.includes.includes(formConfig.value.currentItem!.component)) {
  156. allOptions.value.push(item);
  157. }
  158. } else if (item.exclude) {
  159. if (!item.exclude.includes(formConfig.value.currentItem!.component)) {
  160. allOptions.value.push(item);
  161. }
  162. } else {
  163. allOptions.value.push(item);
  164. }
  165. });
  166. baseComponentAttrs[formConfig.value.currentItem!.component] &&
  167. baseComponentAttrs[formConfig.value.currentItem!.component].forEach(async (item) => {
  168. if (item.component) {
  169. if (['Switch', 'Checkbox', 'Radio'].includes(item.component)) {
  170. item.category = 'control';
  171. allOptions.value.push(item);
  172. } else {
  173. item.category = 'input';
  174. allOptions.value.push(item);
  175. }
  176. }
  177. });
  178. },
  179. {
  180. immediate: true,
  181. },
  182. );
  183. // 控制性的选项
  184. const controlOptions = computed(() => {
  185. return allOptions.value.filter((item) => {
  186. return item.category == 'control';
  187. });
  188. });
  189. // 非控制性选择
  190. const inputOptions = computed(() => {
  191. return allOptions.value.filter((item) => {
  192. return item.category == 'input';
  193. });
  194. });
  195. watch(
  196. () => formConfig.value.currentItem!.componentProps,
  197. () => {
  198. const func = componentPropsFuncs[formConfig.value.currentItem!.component];
  199. if (func) {
  200. func(formConfig.value.currentItem!.componentProps, allOptions.value);
  201. }
  202. },
  203. {
  204. immediate: true,
  205. deep: true,
  206. },
  207. );
  208. const linkOptions = computed(() => {
  209. return (
  210. formConfig.value.schemas &&
  211. formConfig.value.schemas
  212. .filter((item) => item.key !== formConfig.value.currentItem!.key)
  213. .map(({ label, field }) => ({ label: label + '/' + field, value: field }))
  214. );
  215. });
  216. return {
  217. formConfig,
  218. showControlAttrs,
  219. linkOptions,
  220. controlOptions,
  221. inputOptions,
  222. };
  223. },
  224. });
  225. </script>