@@ -51,6 +51,18 @@ const detail = ref({});
const formatDate = (v) => (v ? dayjs(v).format("YYYY-MM-DD") : "—");
+// 从签约日期到今天的使用年限,按"X年X天"展示
+const formatUsageYears = (signDate) => {
+ if (!signDate) return "—";
+ const start = dayjs(signDate);
+ const now = dayjs();
+ if (start.isAfter(now)) return "—";
+ const totalDays = now.diff(start, "day");
+ const years = Math.floor(totalDays / 365);
+ const days = totalDays - years * 365;
+ return `${years}年${days}天`;
+};
+
const loadDetail = async () => {
loading.value = true;
try {
diff --git a/src/views/admin/hospitals/edit.vue b/src/views/admin/hospitals/edit.vue
index cfb9596..8a504f0 100644
--- a/src/views/admin/hospitals/edit.vue
+++ b/src/views/admin/hospitals/edit.vue
@@ -7,7 +7,9 @@
class="page-header"
>
- {{ isEdit ? $t('modal.editHospital') : $t('modal.addHospital') }}
+ {{
+ isEdit ? $t("modal.editHospital") : $t("modal.addHospital")
+ }}
@@ -20,7 +22,10 @@
style="max-width: 800px"
>
-
+
-
-
-
+
+
+
@@ -66,7 +71,10 @@
-
+
- {{ $t('btn.upload') }}
+ {{ $t("btn.upload") }}
- {{ $t('label.acceptanceReportTip') }}
+
+ {{ $t("label.acceptanceReportTip") }}
+
@@ -110,9 +120,9 @@
- {{ isEdit ? $t('common.save') : $t('common.add') }}
+ {{ isEdit ? $t("common.save") : $t("common.add") }}
- {{ $t('common.cancel') }}
+ {{ $t("common.cancel") }}
@@ -157,19 +167,35 @@ const form = reactive({
});
const rules = {
- name: [{ required: true, message: () => $t('placeholder.hospital'), trigger: "blur" }],
+ name: [
+ {
+ required: true,
+ message: () => $t("placeholder.hospital"),
+ trigger: "blur",
+ },
+ ],
customerCategory: [
- { required: true, message: () => $t('label.category'), trigger: "change" },
+ { required: true, message: () => $t("label.category"), trigger: "change" },
+ ],
+ signDate: [
+ { required: true, message: () => $t("label.signDate"), trigger: "change" },
],
- signDate: [{ required: true, message: () => $t('label.signDate'), trigger: "change" }],
acceptDate: [
- { required: true, message: () => $t('label.acceptDate'), trigger: "change" },
+ {
+ required: true,
+ message: () => $t("label.acceptDate"),
+ trigger: "change",
+ },
],
contractYears: [
- { required: true, message: () => $t('label.years'), trigger: "blur" },
+ { required: true, message: () => $t("label.years"), trigger: "blur" },
],
maintenanceEnd: [
- { required: true, message: () => $t('label.maintenanceEndDate'), trigger: "change" },
+ {
+ required: true,
+ message: () => $t("label.maintenanceEndDate"),
+ trigger: "change",
+ },
],
};
@@ -187,7 +213,9 @@ const buildHospitalFormData = () => {
if (value === undefined || value === null || value === "") return;
fd.append(key, value);
});
- const file = (reportFileList.value || []).map((f) => f.raw).filter(Boolean)[0];
+ const file = (reportFileList.value || [])
+ .map((f) => f.raw)
+ .filter(Boolean)[0];
if (file) fd.append("files", file);
return fd;
};
@@ -216,7 +244,7 @@ const submit = async () => {
await formRef.value.validate(async (valid) => {
if (!valid) return;
if (!reportFileList.value?.length) {
- ElMessage.warning($t('label.acceptanceReport'));
+ ElMessage.warning($t("label.acceptanceReport"));
return;
}
submitting.value = true;
@@ -224,10 +252,10 @@ const submit = async () => {
const fd = buildHospitalFormData();
if (isEdit.value) {
await updateAdminHospital(route.params.id, fd);
- ElMessage.success($t('msg.hospitalEditSuccess'));
+ ElMessage.success($t("msg.hospitalEditSuccess"));
} else {
await createAdminHospital(fd);
- ElMessage.success($t('msg.hospitalAddSuccess'));
+ ElMessage.success($t("msg.hospitalAddSuccess"));
}
router.replace("/admin/hospitals");
} finally {
diff --git a/src/views/admin/hospitals/list.vue b/src/views/admin/hospitals/list.vue
index db55292..ed7c42f 100644
--- a/src/views/admin/hospitals/list.vue
+++ b/src/views/admin/hospitals/list.vue
@@ -2,7 +2,7 @@
-
+
-
-
-
+
+
+
@@ -41,7 +41,9 @@
-
+
+ {{ formatUsageYears(row.signDate) }}
+
(v ? dayjs(v).format("YYYY-MM-DD") : "—");
+// 从签约日期到今天的使用年限,按"X年X天"展示
+const formatUsageYears = (signDate) => {
+ if (!signDate) return "—";
+ const start = dayjs(signDate);
+ const now = dayjs();
+ if (start.isAfter(now)) return "—";
+ const totalDays = now.diff(start, "day");
+ const years = Math.floor(totalDays / 365);
+ const days = totalDays - years * 365;
+ return `${years}年${days}天`;
+};
+
const loadList = async () => {
loading.value = true;
try {
diff --git a/src/views/admin/orders/detail.vue b/src/views/admin/orders/detail.vue
index 029372f..610a98f 100644
--- a/src/views/admin/orders/detail.vue
+++ b/src/views/admin/orders/detail.vue
@@ -30,7 +30,7 @@
{{ detail.serviceType }}
{{ detail.submitter }}
{{ detail.department }}
- {{ detail.createdAt }}
+ {{ detail.createdAt?.split('T').join(' ') }}
@@ -42,16 +42,16 @@
{{ $t('label.attachment') }} ({{ (detail.attachments || []).length }})
-
{{ f.fileName }}
-
+
@@ -70,6 +70,21 @@
+
+
+
+
@@ -77,8 +92,8 @@
import { onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { ArrowLeft, Document } from "@element-plus/icons-vue";
-import { getAdminOrderDetail } from "@/service/modular/admin";
-import { getAttachmentUrl } from "@/service/modular/upload";
+import { ElMessage } from "element-plus";
+import { getAdminOrderDetail, getUploadFile } from "@/service/modular/admin";
const route = useRoute();
const router = useRouter();
@@ -101,6 +116,34 @@ const loadDetail = async () => {
const goBack = () => router.back();
const goProcess = () => router.push(`/admin/orders/process/${route.params.id}`);
+const previewVisible = ref(false);
+const previewUrl = ref("");
+
+const cleanupPreviewUrl = () => {
+ if (previewUrl.value) {
+ URL.revokeObjectURL(previewUrl.value);
+ previewUrl.value = "";
+ }
+};
+
+const closePreview = () => {
+ previewVisible.value = false;
+ cleanupPreviewUrl();
+};
+
+const viewReport = async (attachmentPath) => {
+ if (!attachmentPath) return;
+ const fileName = String(attachmentPath);
+ try {
+ const blob = await getUploadFile(fileName);
+ cleanupPreviewUrl();
+ previewUrl.value = URL.createObjectURL(blob);
+ previewVisible.value = true;
+ } catch (e) {
+ ElMessage.error(e?.message || $t('msg.failed'));
+ }
+};
+
onMounted(loadDetail);
@@ -157,4 +200,9 @@ onMounted(loadDetail);
margin-top: 4px;
}
}
+.preview-iframe {
+ width: 100%;
+ height: 80vh;
+ border: 0;
+}
diff --git a/src/views/admin/orders/list.vue b/src/views/admin/orders/list.vue
index a798f9f..9d9da8d 100644
--- a/src/views/admin/orders/list.vue
+++ b/src/views/admin/orders/list.vue
@@ -394,7 +394,7 @@ const filters = reactive({
const loadHospitals = async () => {
try {
const res = await getAdminHospitals({ page: 1, pageSize: 1000 });
- hospitals.value = res?.list.map || [];
+ hospitals.value = res?.list || [];
} catch (_) {
hospitals.value = [];
}