OkkiShowlistModal.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <template>
  2. <BasicModal ref="modalRef" destroyOnClose wrapClassName="j-cgform-tab-modal" v-bind="$attrs" @register="registerModal" :width="800" @ok="handleSubmit">
  3. <!-- 子表单区域 -->
  4. <a-tabs v-model:activeKey="activeKey" animated @change="handleChangeTabs">
  5. <!--主表区域 -->
  6. <a-tab-pane tab="ShowList" :key="refKeys[0]" :forceRender="true" :style="tabsStyle">
  7. <BasicForm @register="registerForm" ref="formRef"/>
  8. </a-tab-pane>
  9. <!--子表单区域 -->
  10. <a-tab-pane tab="概览" key="okkiOverview" :forceRender="true" :style="tabsStyle">
  11. <OkkiOverviewForm ref="okkiOverviewForm" :disabled="formDisabled"></OkkiOverviewForm>
  12. </a-tab-pane>
  13. <a-tab-pane tab="产品" key="okkiProductList" :forceRender="true" :style="tabsStyle">
  14. <OkkiProductListForm ref="okkiProductListForm" :disabled="formDisabled"></OkkiProductListForm>
  15. </a-tab-pane>
  16. <a-tab-pane tab="优势" key="okkiAdvantage" :forceRender="true" :style="tabsStyle">
  17. <JVxeTable
  18. keep-source
  19. resizable
  20. ref="okkiAdvantage"
  21. :loading="okkiAdvantageTable.loading"
  22. :columns="okkiAdvantageTable.columns"
  23. :dataSource="okkiAdvantageTable.dataSource"
  24. :height="340"
  25. :disabled="formDisabled"
  26. :rowNumber="true"
  27. :rowSelection="true"
  28. :toolbar="true"
  29. />
  30. </a-tab-pane>
  31. <a-tab-pane tab="关键词" key="okkiKeywords" :forceRender="true" :style="tabsStyle">
  32. <JVxeTable
  33. keep-source
  34. resizable
  35. ref="okkiKeywords"
  36. :loading="okkiKeywordsTable.loading"
  37. :columns="okkiKeywordsTable.columns"
  38. :dataSource="okkiKeywordsTable.dataSource"
  39. :height="340"
  40. :disabled="formDisabled"
  41. :rowNumber="true"
  42. :rowSelection="true"
  43. :toolbar="true"
  44. />
  45. </a-tab-pane>
  46. <a-tab-pane tab="常见问题" key="okkiFaq" :forceRender="true" :style="tabsStyle">
  47. <JVxeTable
  48. keep-source
  49. resizable
  50. ref="okkiFaq"
  51. :loading="okkiFaqTable.loading"
  52. :columns="okkiFaqTable.columns"
  53. :dataSource="okkiFaqTable.dataSource"
  54. :height="340"
  55. :disabled="formDisabled"
  56. :rowNumber="true"
  57. :rowSelection="true"
  58. :toolbar="true"
  59. />
  60. </a-tab-pane>
  61. </a-tabs>
  62. </BasicModal>
  63. </template>
  64. <script lang="ts" setup>
  65. import {ref, computed, unref,reactive} from 'vue';
  66. import {BasicModal, useModalInner} from '/@/components/Modal';
  67. import {BasicForm, useForm} from '/@/components/Form/index';
  68. import { JVxeTable } from '/@/components/jeecg/JVxeTable'
  69. import { useJvxeMethod } from '/@/hooks/system/useJvxeMethods.ts'
  70. import OkkiOverviewForm from './OkkiOverviewForm.vue'
  71. import OkkiProductListForm from './OkkiProductListForm.vue'
  72. import {formSchema,okkiAdvantageColumns,okkiKeywordsColumns,okkiFaqColumns} from '../OkkiShowlist.data';
  73. import {saveOrUpdate,okkiOverviewList,okkiProductListList,okkiAdvantageList,okkiKeywordsList,okkiFaqList} from '../OkkiShowlist.api';
  74. import { VALIDATE_FAILED } from '/@/utils/common/vxeUtils'
  75. // Emits声明
  76. const emit = defineEmits(['register','success']);
  77. const isUpdate = ref(true);
  78. const formDisabled = ref(false);
  79. const modalRef = ref();
  80. const refKeys = ref(['okkiShowlist','okkiOverview', 'okkiProductList', 'okkiAdvantage', 'okkiKeywords', 'okkiFaq', ]);
  81. const activeKey = ref('okkiShowlist');
  82. const okkiOverviewForm = ref();
  83. const okkiProductListForm = ref();
  84. const okkiAdvantage = ref();
  85. const okkiKeywords = ref();
  86. const okkiFaq = ref();
  87. const tableRefs = {okkiAdvantage, okkiKeywords, okkiFaq, };
  88. const okkiAdvantageTable = reactive({
  89. loading: false,
  90. dataSource: [],
  91. columns:okkiAdvantageColumns
  92. })
  93. const okkiKeywordsTable = reactive({
  94. loading: false,
  95. dataSource: [],
  96. columns:okkiKeywordsColumns
  97. })
  98. const okkiFaqTable = reactive({
  99. loading: false,
  100. dataSource: [],
  101. columns:okkiFaqColumns
  102. })
  103. //表单配置
  104. const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
  105. //labelWidth: 150,
  106. schemas: formSchema,
  107. showActionButtonGroup: false,
  108. baseColProps: {span: 24}
  109. });
  110. //表单赋值
  111. const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
  112. //重置表单
  113. await reset();
  114. setModalProps({confirmLoading: false,showCancelBtn:data?.showFooter,showOkBtn:data?.showFooter});
  115. isUpdate.value = !!data?.isUpdate;
  116. formDisabled.value = !data?.showFooter;
  117. if (unref(isUpdate)) {
  118. //表单赋值
  119. await setFieldsValue({
  120. ...data.record,
  121. });
  122. okkiOverviewForm.value.initFormData(okkiOverviewList,data?.record?.id)
  123. okkiProductListForm.value.initFormData(okkiProductListList,data?.record?.id)
  124. requestSubTableData(okkiAdvantageList, {id:data?.record?.id}, okkiAdvantageTable)
  125. requestSubTableData(okkiKeywordsList, {id:data?.record?.id}, okkiKeywordsTable)
  126. requestSubTableData(okkiFaqList, {id:data?.record?.id}, okkiFaqTable)
  127. }
  128. // 隐藏底部时禁用整个表单
  129. setProps({ disabled: !data?.showFooter })
  130. });
  131. //方法配置
  132. const [handleChangeTabs,handleSubmit,requestSubTableData,formRef] = useJvxeMethod(requestAddOrEdit,classifyIntoFormData,tableRefs,activeKey,refKeys,validateSubForm);
  133. // 弹窗tabs滚动区域的高度
  134. const tabsStyle = computed(() => {
  135. let height: Nullable<string> = null
  136. let minHeight = '100px'
  137. let maxHeight: Nullable<string> = '500px'
  138. // 弹窗wrapper
  139. let modalWrapperRef = modalRef.value?.modalWrapperRef
  140. if (modalWrapperRef) {
  141. if (modalWrapperRef.fullScreen) {
  142. height = 'calc(' + modalWrapperRef.spinStyle.height + ' - 50px)';
  143. maxHeight = null
  144. }
  145. }
  146. let overflow = 'auto';
  147. return {height, minHeight, maxHeight, overflow};
  148. })
  149. async function reset(){
  150. await resetFields();
  151. activeKey.value = 'okkiShowlist';
  152. okkiOverviewForm.value.resetFields();
  153. okkiProductListForm.value.resetFields();
  154. okkiAdvantageTable.dataSource = [];
  155. okkiKeywordsTable.dataSource = [];
  156. okkiFaqTable.dataSource = [];
  157. }
  158. function classifyIntoFormData(allValues) {
  159. let main = Object.assign({}, allValues.formValue)
  160. return {
  161. ...main, // 展开
  162. okkiOverviewList: okkiOverviewForm.value.getFormData(),
  163. okkiProductListList: okkiProductListForm.value.getFormData(),
  164. okkiAdvantageList: allValues.tablesValue[0].tableData,
  165. okkiKeywordsList: allValues.tablesValue[1].tableData,
  166. okkiFaqList: allValues.tablesValue[2].tableData,
  167. }
  168. }
  169. //校验所有一对一子表表单
  170. function validateSubForm(allValues){
  171. return new Promise((resolve,reject)=>{
  172. Promise.all([
  173. okkiOverviewForm.value.validateForm(1),
  174. okkiProductListForm.value.validateForm(2),
  175. ]).then(() => {
  176. resolve(allValues)
  177. }).catch(e => {
  178. if (e.error === VALIDATE_FAILED) {
  179. // 如果有未通过表单验证的子表,就自动跳转到它所在的tab
  180. activeKey.value = e.index == null ? unref(activeKey) : refKeys.value[e.index]
  181. } else {
  182. console.error(e)
  183. }
  184. })
  185. })
  186. }
  187. //表单提交事件
  188. async function requestAddOrEdit(values) {
  189. try {
  190. setModalProps({confirmLoading: true});
  191. //提交表单
  192. await saveOrUpdate(values, isUpdate.value);
  193. //关闭弹窗
  194. closeModal();
  195. //刷新列表
  196. emit('success');
  197. } finally {
  198. setModalProps({confirmLoading: false});
  199. }
  200. }
  201. </script>
  202. <style lang="less" scoped>
  203. /** 时间和数字输入框样式 */
  204. :deep(.ant-input-number){
  205. width: 100%
  206. }
  207. :deep(.ant-calendar-picker){
  208. width: 100%
  209. }
  210. </style>
  211. <style lang="less">
  212. // Online表单Tab风格专属样式
  213. .j-cgform-tab-modal {
  214. .ant-modal-header {
  215. padding-top: 8px;
  216. padding-bottom: 8px;
  217. border-bottom: none !important;
  218. }
  219. .ant-modal .ant-modal-body > .scrollbar,
  220. .ant-tabs-nav .ant-tabs-tab {
  221. padding-top: 0;
  222. }
  223. .ant-tabs-top-bar {
  224. width: calc(100% - 55px);
  225. position: relative;
  226. left: -14px;
  227. }
  228. .ant-tabs .ant-tabs-top-content > .ant-tabs-tabpane {
  229. overflow: hidden auto;
  230. }
  231. }
  232. </style>