form.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. <template>
  2. <!-- 表单 -->
  3. <div class="about main-background main-background-type0">
  4. <div class="nav-placeholder"></div>
  5. <!-- 表单 -->
  6. <section class="main-section small-h">
  7. <div class="content">
  8. <div class="title left-right small">
  9. <a-button :icon="h(ArrowLeftOutlined)" @click="handleBack">返回主页</a-button>
  10. <h2>{{ title }}</h2>
  11. <div class="button-placeholder"></div>
  12. </div>
  13. <a-spin v-if="loadingData" class="w-100 h-100" />
  14. <template v-else>
  15. <a-tabs centered>
  16. <a-tab-pane key="1" :tab="basicTabText">
  17. <ScrollRect scroll="vertical" style="height: 70vh">
  18. <DynamicForm
  19. ref="formBase"
  20. :model="(formModel as any)"
  21. :options="formOptions"
  22. />
  23. </ScrollRect>
  24. <div class="d-flex flex-column mt-3">
  25. <div class="d-flex flex-row w-100 align-items-center justify-content-between">
  26. <span>
  27. <ExclamationCircleOutlined class="me-3" />
  28. 提示:上传文件时请勿离开页面防止上传失败,在关闭页面之前请提交您的修改以防丢失。
  29. </span>
  30. <a-button size="small" type="primary" @click="showHistory = true">历史版本</a-button>
  31. </div>
  32. <a-button
  33. type="primary"
  34. block
  35. :loading="loading" class="mt-3"
  36. @click="handleSubmitBase"
  37. >
  38. 提交
  39. </a-button>
  40. </div>
  41. </a-tab-pane>
  42. <a-tab-pane v-if="extendFormOptions" key="2" tab="扩展信息">
  43. <DynamicForm
  44. ref="formExtend"
  45. :model="(extendFormModel as any)"
  46. :options="extendFormOptions"
  47. />
  48. <a-button
  49. type="primary"
  50. block
  51. :loading="loading" class="mt-3"
  52. @click="handleSubmitExtend"
  53. >
  54. 提交
  55. </a-button>
  56. </a-tab-pane>
  57. </a-tabs>
  58. </template>
  59. </div>
  60. </section>
  61. <a-drawer
  62. v-model:open="showHistory"
  63. title="历史版本"
  64. placement="right"
  65. :width="showHistoryModel ? '90%' : '50%'"
  66. >
  67. <div v-if="showHistoryModel">
  68. <div class="d-flex flex-row justify-content-between">
  69. <a-button :icon="h(ArrowLeftOutlined)" @click="showHistoryModel = null">返回</a-button>
  70. <span>您正在查看 {{ showHistoryModel.desc }} 保存的版本</span>
  71. </div>
  72. <a-spin v-if="showHistoryLoading" class="w-100 h-100" />
  73. <DynamicForm
  74. v-else
  75. :model="(showHistoryModel as any)"
  76. :options="{
  77. ...formOptions,
  78. disabled: true,
  79. }"
  80. />
  81. </div>
  82. <CommonListBlock
  83. v-else
  84. :showTotal="true"
  85. :showSearch="false"
  86. :rowCount="1"
  87. :rowType="6"
  88. :load="(page: number, pageSize: number, _, searchText: string, dropDownValues: number[]) => loadHistoryData(page, pageSize, dropDownValues, searchText)"
  89. detailsPage="none"
  90. >
  91. <template #itemRight="{ item }">
  92. <a-button type="link" @click.stop="handleShowHistory(item)">查看</a-button>
  93. </template>
  94. </CommonListBlock>
  95. </a-drawer>
  96. </div>
  97. </template>
  98. <script setup lang="ts" generic="T extends DataModel, U extends DataModel">
  99. import { onMounted, ref, toRefs, type PropType, h, watch } from 'vue';
  100. import { useRoute, useRouter } from 'vue-router';
  101. import { useWindowOnUnLoadConfirm } from '@/composeable/WindowOnUnLoad';
  102. import { DynamicForm, type IDynamicFormOptions, type IDynamicFormRef } from '@imengyu/vue-dynamic-form';
  103. import { message, Modal, type FormInstance } from 'ant-design-vue';
  104. import { ArrowLeftOutlined, ExclamationCircleOutlined } from '@ant-design/icons-vue';
  105. import { ScrollRect } from '@imengyu/vue-scroll-rect';
  106. import { useAuthStore } from '@/stores/auth';
  107. import type { DataModel } from '@imengyu/js-request-transform';
  108. import InheritorContent from '@/api/inheritor/InheritorContent';
  109. import CommonListBlock from '@/components/content/CommonListBlock.vue';
  110. import { DateUtils, waitTimeOut } from '@imengyu/imengyu-utils';
  111. const props = defineProps({
  112. title: {
  113. type: String,
  114. default: '非遗数字化资源信息校对'
  115. },
  116. basicTabText: {
  117. type: String,
  118. default: '基础信息'
  119. },
  120. formModel: {
  121. type: Object as PropType<T>,
  122. required: true
  123. },
  124. formOptions: {
  125. type: Object as PropType<IDynamicFormOptions>,
  126. required: true
  127. },
  128. extendFormModel: {
  129. type: Object as PropType<U>,
  130. default: null
  131. },
  132. extendFormOptions: {
  133. type: Object as PropType<IDynamicFormOptions>,
  134. default: null
  135. },
  136. model: {
  137. type: Object as PropType<new () => DataModel>,
  138. required: true
  139. },
  140. load: {
  141. type: Function as PropType<(id: number|undefined) => Promise<void>>,
  142. default: () => Promise.resolve()
  143. },
  144. save: {
  145. type: Function as PropType<(model: T) => Promise<void>>,
  146. default: () => Promise.resolve()
  147. },
  148. saveExtend: {
  149. type: Function as PropType<(model: U) => Promise<void>>,
  150. default: () => Promise.resolve()
  151. },
  152. })
  153. const { formModel, formOptions, extendFormOptions, load } = toRefs(props);
  154. const formBase = ref<IDynamicFormRef>();
  155. const formExtend = ref<IDynamicFormRef>();
  156. const authStore = useAuthStore();
  157. const router = useRouter();
  158. const route = useRoute();
  159. const loading = ref(false);
  160. const loadingData = ref(false);
  161. const readonly = ref(false);
  162. const showHistory = ref(false);
  163. const showHistoryLoading = ref(false);
  164. const showHistoryModel = ref<any>(null);
  165. watch(readonly, (newValue) => {
  166. formOptions.value.disabled = newValue;
  167. extendFormOptions.value.disabled = newValue;
  168. })
  169. useWindowOnUnLoadConfirm();
  170. async function handleSubmitBase() {
  171. loading.value = true;
  172. const ref = (formBase.value?.getFormRef() as FormInstance);
  173. try {
  174. await ref.validate();
  175. } catch (e) {
  176. message.warn('请填写完整信息');
  177. loading.value = false;
  178. if ((e as any).errorFields)
  179. ref.scrollToField((e as any).errorFields[0].name, { block: 'center' })
  180. return;
  181. }
  182. try {
  183. const result = await InheritorContent.saveBaseInfo(formModel.value);
  184. await props.save(formModel.value);
  185. Modal.success({
  186. title: '提交成功',
  187. content: result.message,
  188. onOk() {
  189. router.back();
  190. },
  191. });
  192. } catch (error) {
  193. Modal.error({
  194. title: '提交失败',
  195. content: '' + error,
  196. });
  197. } finally {
  198. loading.value = false;
  199. }
  200. }
  201. async function handleSubmitExtend() {
  202. loading.value = true;
  203. const ref = (formExtend.value?.getFormRef() as FormInstance);
  204. try {
  205. await ref.validate();
  206. } catch (e) {
  207. message.warn('请填写完整信息');
  208. loading.value = false;
  209. if ((e as any).errorFields)
  210. ref.scrollToField((e as any).errorFields[0].name, { block: 'center' })
  211. return;
  212. }
  213. try {
  214. const result = await InheritorContent.saveExpandInfo(formModel.value);
  215. await props.save(formModel.value);
  216. Modal.success({
  217. title: '提交成功',
  218. content: result.message,
  219. onOk() {
  220. router.back();
  221. },
  222. });
  223. } catch (error) {
  224. Modal.error({
  225. title: '提交失败',
  226. content: '' + error,
  227. });
  228. } finally {
  229. loading.value = false;
  230. }
  231. }
  232. async function loadData() {
  233. loadingData.value = true;
  234. readonly.value = Boolean(route.query.readonly);
  235. try {
  236. await load.value(route.query.id ? Number(route.query.id) : undefined);
  237. } catch (error) {
  238. console.log(error);
  239. message.error('加载失败 ' + error);
  240. } finally {
  241. loadingData.value = false;
  242. }
  243. }
  244. async function loadHistoryData(page: number, pageSize: number, dropDownValues: number[], searchText: string) {
  245. const res = (await InheritorContent.getCollectList(props.model, {
  246. contentId: Number(route.query.id || formModel.value.contentId),
  247. collectType: 'content',
  248. modelId: 2,
  249. userId: authStore.userInfo?.id,
  250. page,
  251. pageSize
  252. }))
  253. return {
  254. page,
  255. total: res.total,
  256. data: res.data.map((p) => {
  257. p.title = `提交人:${p.nickname}`;
  258. p.desc = `提交时间:${p.updatedAt}`;
  259. return p;
  260. }),
  261. };
  262. }
  263. async function handleShowHistory(item: any) {
  264. showHistoryLoading.value = true;
  265. showHistory.value = true;
  266. await waitTimeOut(100);
  267. // showHistoryModel.value = await InheritorContent.getCollectListInfo(props.model, item.id);
  268. showHistoryModel.value = item;
  269. showHistoryLoading.value = false;
  270. }
  271. function handleBack() {
  272. Modal.confirm({
  273. title: '确定返回吗?',
  274. content: '返回后将丢失当未提交的信息,若有修改请先提交哦!',
  275. okText: '确定',
  276. okType: 'danger',
  277. onOk() {
  278. router.back();
  279. },
  280. });
  281. }
  282. onMounted(async () => {
  283. await loadData();
  284. })
  285. defineExpose({
  286. getFormRef() {
  287. return formBase.value;
  288. },
  289. getExtraFormRef() {
  290. return formExtend.value;
  291. },
  292. })
  293. </script>