PatientTagEdit.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <script setup lang="ts">
  2. import { useForm, useRequest } from 'alova/client';
  3. import type { VxeFormListeners, VxeFormProps } from 'vxe-pc-ui';
  4. import { getPatientTagsMethod, searchTagsFromSelectableMethod, updatePatientTagMethod } from '@/request/api/patient.api';
  5. import type { PatientTagVO } from '@/model';
  6. import { list2Groups } from '@/tools/data';
  7. import { message as Message } from 'ant-design-vue';
  8. interface FormModel {
  9. tags: string[];
  10. }
  11. const props = defineProps<{
  12. id: string;
  13. tags?: PatientTagVO[];
  14. }>();
  15. const emits = defineEmits<{
  16. destroy: [refreshValue?: PatientTagVO[]];
  17. }>();
  18. const {
  19. form,
  20. send: submit,
  21. loading: submitting,
  22. } = useForm((model) => updatePatientTagMethod(props.id, model.tags), {
  23. initialForm: {
  24. selected: [],
  25. tags: props.tags ? [...props.tags] : [],
  26. },
  27. }).onSuccess(({ data }) => {
  28. Message.success(`标签更新成功`);
  29. emits('destroy', data);
  30. });
  31. const {
  32. data: patientTags,
  33. loading,
  34. send: loadPatientTags,
  35. } = useRequest(() => getPatientTagsMethod(props.id), {
  36. initialData: props.tags ? [...props.tags] : [],
  37. immediate: false,
  38. }).onSuccess(({ data: tags }) => {
  39. form.value.tags = [...tags];
  40. });
  41. onMounted(() => {
  42. if (!patientTags.value.length) loadPatientTags();
  43. });
  44. const { data: searchTags, loading: tagsLoading } = useRequest(searchTagsFromSelectableMethod, {
  45. initialData: [],
  46. });
  47. const selected = computed(() => form.value.tags.map((item) => item.id));
  48. const formProps = reactive<VxeFormProps<FormModel>>({
  49. titleWidth: 0,
  50. titleAlign: 'right',
  51. titleColon: true,
  52. items: [
  53. {
  54. field: 'selected',
  55. title: '',
  56. span: 24,
  57. itemRender: {
  58. name: 'VxeSelect',
  59. props: {
  60. loading: tagsLoading,
  61. optionGroups: computed(() =>
  62. list2Groups(
  63. searchTags.value.filter((tag) => !(tag.disabled || selected.value.includes(tag.id))),
  64. 'category',
  65. (key) => ({ 1: '系统标签', 2: '个人标签' })[key]!
  66. )
  67. ),
  68. optionProps: { value: 'id', label: 'name' },
  69. optionGroupProps: { options: 'groups' },
  70. multiple: true,
  71. clearable: true,
  72. filterable: true,
  73. },
  74. events: {
  75. visibleChange(ref, { visible }) {
  76. if (!visible) ref.data.selected?.forEach(appendTag);
  77. },
  78. },
  79. },
  80. },
  81. { align: 'center', span: 24, slots: { default: 'active' } },
  82. ],
  83. rules: {},
  84. });
  85. const formEmits: VxeFormListeners<FormModel> = {
  86. submit({ data }) {
  87. submit(data);
  88. },
  89. reset() {
  90. form.value = { tags: [...patientTags.value], selected: [] };
  91. },
  92. };
  93. function appendTag(id: PatientTagVO['id']) {
  94. const tag = searchTags.value.find((tag) => tag.id === id);
  95. if (tag) form.value.tags.push(tag);
  96. form.value.selected = [];
  97. }
  98. function remove(tag: PatientTagVO, index: number) {
  99. form.value.tags.splice(index, 1);
  100. }
  101. const getTagColor = (tag: PatientTagVO) => {
  102. return { 1: 'pink', 2: 'blue' }[tag.category];
  103. };
  104. </script>
  105. <template>
  106. <a-spin :spinning="loading">
  107. <div class="flex flex-wrap mt--2">
  108. <a-tag class="mt-2" v-for="(item, index) in form.tags" :key="item.id" :color="getTagColor(item)" :closable="!submitting" @close="remove(item, index)">
  109. {{ item.name }}
  110. </a-tag>
  111. </div>
  112. <vxe-form :data="form" v-bind="formProps" v-on="formEmits">
  113. <template #active>
  114. <vxe-button type="submit" status="primary" content="提交" :loading="submitting"></vxe-button>
  115. <vxe-button type="reset" content="重置" :disabled="submitting"></vxe-button>
  116. </template>
  117. </vxe-form>
  118. </a-spin>
  119. </template>
  120. <style scoped lang="scss"></style>