|
|
@@ -45,6 +45,30 @@
|
|
|
@update:modelValue="setCheckedItem(item as CheckItemInfo, child as CheckItemInfo, $event)"
|
|
|
/>
|
|
|
</FlexCol>
|
|
|
+ <FlexCol gap="gap.sm">
|
|
|
+ <Text
|
|
|
+ fontConfig="subText"
|
|
|
+ color="text.second"
|
|
|
+ :text="readonly ? '佐证资料' : '佐证材料上传'"
|
|
|
+ />
|
|
|
+ <Text
|
|
|
+ v-if="!currentForm.id"
|
|
|
+ fontConfig="subText"
|
|
|
+ color="text.second"
|
|
|
+ text="请先保存评估表后再上传佐证资料"
|
|
|
+ />
|
|
|
+ <Uploader
|
|
|
+ v-else
|
|
|
+ :ref="(el) => bindUploaderRef(item.id, el)"
|
|
|
+ :upload="getAnnexUpload(item.id)"
|
|
|
+ :max-upload-count="100"
|
|
|
+ :max-file-size="20 * 1024 * 1024"
|
|
|
+ :group-type="true"
|
|
|
+ chooseType="file"
|
|
|
+ list-type="list"
|
|
|
+ :readonly="readonly"
|
|
|
+ />
|
|
|
+ </FlexCol>
|
|
|
</FlexCol>
|
|
|
</FlexCol>
|
|
|
</FlexCol>
|
|
|
@@ -54,7 +78,7 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { computed, ref } from 'vue';
|
|
|
+import { computed, ref, watch } from 'vue';
|
|
|
import DynamicForm from '@/components/dynamic/DynamicForm.vue';
|
|
|
import FlexCol from '@/components/layout/FlexCol.vue';
|
|
|
import H3 from '@/components/typography/H3.vue';
|
|
|
@@ -62,12 +86,16 @@ import Text from '@/components/basic/Text.vue';
|
|
|
import FlexRow from '@/components/layout/FlexRow.vue';
|
|
|
import CheckBox from '@/components/form/CheckBox.vue';
|
|
|
import Stepper from '@/components/form/Stepper.vue';
|
|
|
-import { SelfAssessmentCheckItemAnswer, type CheckItemInfo, type SelfAssessmentDetail } from '@/api/collect/AssessmentContent';
|
|
|
+import Uploader, { type UploaderInstance } from '@/components/form/Uploader.vue';
|
|
|
+import AssessmentContentApi, { getCheckAnnexType, SelfAssessmentCheckItemAnswer, type CheckItemInfo, type SelfAssessmentDetail } from '@/api/collect/AssessmentContent';
|
|
|
import type { IDynamicFormOptions, IDynamicFormRef } from '@/components/dynamic';
|
|
|
import { ArrayUtils } from '@imengyu/imengyu-utils';
|
|
|
import Tag from '@/components/display/Tag.vue';
|
|
|
import Divider from '@/components/display/Divider.vue';
|
|
|
import Height from '@/components/layout/space/Height.vue';
|
|
|
+import { useAliOssUploadCo } from '@/common/components/upload/AliOssUploadCo';
|
|
|
+import { getMimeType } from '@/common/components/upload/mimes';
|
|
|
+import { stringUrlToUploaderItem, type UploaderAction } from '@/components/form/Uploader';
|
|
|
|
|
|
const props = withDefaults(defineProps<{
|
|
|
currentForm: SelfAssessmentDetail;
|
|
|
@@ -81,6 +109,8 @@ const props = withDefaults(defineProps<{
|
|
|
});
|
|
|
|
|
|
const formRef = ref<IDynamicFormRef | null>(null);
|
|
|
+const uploaderRefMap = new Map<number, UploaderInstance | null>();
|
|
|
+const uploadCoMap = new Map<number, (action: UploaderAction) => (() => void)>();
|
|
|
|
|
|
const mergedFormOptions = computed<IDynamicFormOptions>(() => ({
|
|
|
...props.formOptions,
|
|
|
@@ -142,11 +172,69 @@ function setCheckedItem(checkItem: CheckItemInfo, childItem: CheckItemInfo, coun
|
|
|
ArrayUtils.remove(props.currentFormCheckItems, item);
|
|
|
}
|
|
|
|
|
|
+function bindUploaderRef(itemId: number, el: unknown) {
|
|
|
+ uploaderRefMap.set(itemId, (el as UploaderInstance | null) || null);
|
|
|
+ if (el)
|
|
|
+ loadAnnexListByItem(itemId);
|
|
|
+}
|
|
|
+
|
|
|
+function getAnnexUpload(itemId: number) {
|
|
|
+ const cached = uploadCoMap.get(itemId);
|
|
|
+ if (cached)
|
|
|
+ return cached;
|
|
|
+ const uploadCo = useAliOssUploadCo('assessment/annex', async (res, item) => {
|
|
|
+ const formId = props.currentForm.id;
|
|
|
+ if (!formId)
|
|
|
+ return;
|
|
|
+ const mimetype = getMimeType(item.filePath);
|
|
|
+ await AssessmentContentApi.saveAnnex({
|
|
|
+ name: item.name,
|
|
|
+ formId,
|
|
|
+ itemId,
|
|
|
+ url: res,
|
|
|
+ type: getCheckAnnexType(mimetype),
|
|
|
+ mimetype,
|
|
|
+ fileSize: item.size
|
|
|
+ ? Math.max(1, Math.ceil(item.size / 1024))
|
|
|
+ : undefined,
|
|
|
+ });
|
|
|
+ await loadAnnexListByItem(itemId);
|
|
|
+ });
|
|
|
+ uploadCoMap.set(itemId, uploadCo);
|
|
|
+ return uploadCo;
|
|
|
+}
|
|
|
+
|
|
|
+async function loadAnnexListByItem(itemId: number) {
|
|
|
+ const formId = props.currentForm.id;
|
|
|
+ const uploaderRef = uploaderRefMap.get(itemId);
|
|
|
+ if (!uploaderRef)
|
|
|
+ return;
|
|
|
+ if (!formId) {
|
|
|
+ uploaderRef.setList([]);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const annexList = await AssessmentContentApi.getAnnexList(formId, itemId);
|
|
|
+ uploaderRef.setList(annexList.data.map((item) => stringUrlToUploaderItem(item.url, item.name)));
|
|
|
+}
|
|
|
+
|
|
|
+async function reloadAllAnnexList() {
|
|
|
+ const itemIds = props.checkItemList.map((item) => item.id);
|
|
|
+ await Promise.all(itemIds.map(loadAnnexListByItem));
|
|
|
+}
|
|
|
+
|
|
|
async function validate() {
|
|
|
if (props.readonly)
|
|
|
return;
|
|
|
await formRef.value?.validate();
|
|
|
}
|
|
|
|
|
|
+watch(
|
|
|
+ () => [props.currentForm.id, props.checkItemList.map((item) => item.id).join(',')],
|
|
|
+ () => {
|
|
|
+ reloadAllAnnexList();
|
|
|
+ },
|
|
|
+ { immediate: true },
|
|
|
+);
|
|
|
+
|
|
|
defineExpose({ validate });
|
|
|
</script>
|