From 7c2cdcbc7f5585b96fba76a07b0e4417a09c4d7e Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 02 六月 2026 11:06:10 +0800
Subject: [PATCH] 新疆马铃薯 1.过程检验下载添加3个模版
---
src/views/officeProcessAutomation/AttendManage/overtime-apply/index.vue | 260 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 260 insertions(+), 0 deletions(-)
diff --git a/src/views/officeProcessAutomation/AttendManage/overtime-apply/index.vue b/src/views/officeProcessAutomation/AttendManage/overtime-apply/index.vue
new file mode 100644
index 0000000..9b3d91e
--- /dev/null
+++ b/src/views/officeProcessAutomation/AttendManage/overtime-apply/index.vue
@@ -0,0 +1,260 @@
+<!--OA妯″潡锛氬姞鐝敵璇�-->
+<template>
+ <div class="app-container">
+ <div class="search_form mb20">
+ <div>
+ <span class="search_title">瀹℃壒鍗曞彿锛�</span>
+ <el-input
+ v-model="searchForm.instanceNo"
+ style="width: 220px"
+ placeholder="璇疯緭鍏ュ鎵瑰崟鍙�"
+ clearable
+ @keyup.enter="onSearch"
+ />
+ <span class="search_title" style="margin-left: 12px">鐢宠浜猴細</span>
+ <el-input
+ v-model="searchForm.applicantKeyword"
+ style="width: 220px"
+ placeholder="濮撳悕鎴栫紪鍙�"
+ clearable
+ :prefix-icon="Search"
+ @keyup.enter="onSearch"
+ />
+ <el-button type="primary" style="margin-left: 10px" @click="onSearch">鎼滅储</el-button>
+ <el-button @click="resetSearch">閲嶇疆</el-button>
+ </div>
+ <div class="search_actions">
+ <el-button type="warning" plain @click="handleExport">瀵煎嚭</el-button>
+ <el-button type="primary" @click="openAddWithTemplate">鏂板鍔犵彮鐢宠</el-button>
+ </div>
+ </div>
+
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="false"
+ :tableLoading="tableLoading"
+ @pagination="onPagination"
+ :total="page.total"
+ />
+ </div>
+
+ <ApprovalInstanceSubmitDialog
+ v-model="submitDialog.visible"
+ :title="submitDialogTitle"
+ :form="submitForm"
+ :rules="submitFormRules"
+ :fields="submitFormFields"
+ :active-template="activeTemplate"
+ :user-options="flowUserOptions"
+ :is-edit="isSubmitEdit"
+ :saving="submitSaving"
+ :form-ref="submitFormRef"
+ flow-attachments-only
+ @submit="onSubmit"
+ >
+ <template #before="{ form, fields }">
+ <FormPayloadFields :fields="displayTemplateFields(fields)" :form-payload="form.formPayload" />
+ <el-row :gutter="24">
+ <el-col :span="12">
+ <el-form-item label="鍔犵彮鏃堕暱">
+ <el-input :model-value="overtimeHoursDisplay(form)" readonly placeholder="鏍规嵁妯℃澘涓姞鐝椂闂磋嚜鍔ㄨ绠�">
+ <template #append>灏忔椂</template>
+ </el-input>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ </template>
+ </ApprovalInstanceSubmitDialog>
+
+ <ApprovalTemplateBindDialog
+ v-model:visible="templateBindVisible"
+ :module-key="APPROVAL_MODULE_KEYS.OVERTIME"
+ skip-form-confirm
+ @confirm="onTemplateBound"
+ @closed="onTemplateBindClosed"
+ />
+
+ <ApprovalInstanceDetailDialog
+ v-model="detailDialog.visible"
+ title="鍔犵彮鐢宠璇︽儏"
+ :row="detailRow"
+ @edit="openEditFromDetail"
+ />
+ </div>
+</template>
+
+<script setup>
+import { Search } from "@element-plus/icons-vue";
+import dayjs from "dayjs";
+import { ElMessage } from "element-plus";
+import { getCurrentInstance, onMounted, reactive, ref } from "vue";
+import FormPayloadFields from "../../ApproveManage/approve-list/components/FormPayloadFields.vue";
+import ApprovalInstanceDetailDialog from "../../ApproveManage/approve-shared/components/ApprovalInstanceDetailDialog.vue";
+import ApprovalInstanceSubmitDialog from "../../ApproveManage/approve-shared/components/ApprovalInstanceSubmitDialog.vue";
+import ApprovalTemplateBindDialog from "../../ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue";
+import { buildInstanceTableColumns } from "../../ApproveManage/approve-shared/approvalInstanceFormConfigTable.js";
+import { APPROVAL_MODULE_KEYS } from "../../ApproveManage/approve-shared/approvalModuleRegistry.js";
+import { useApprovalInstanceModule } from "../../ApproveManage/approve-shared/useApprovalInstanceModule.js";
+import { useFlowUserOptions } from "../../ApproveManage/approve-shared/useFlowUserOptions.js";
+
+const OVERTIME_TYPE_OPTIONS = [
+ { label: "宸ヤ綔鏃ュ姞鐝�", value: "weekday" },
+ { label: "浼戞伅鏃ュ姞鐝�", value: "weekend" },
+ { label: "娉曞畾鑺傚亣鏃ュ姞鐝�", value: "holiday" },
+];
+
+function isOvertimeDurationField(field) {
+ const label = String(field?.label || "");
+ return label.includes("鍔犵彮鏃堕暱") || field?.key === "overtimeHours";
+}
+
+function displayTemplateFields(fields = []) {
+ return (fields || []).filter((f) => !isOvertimeDurationField(f));
+}
+
+function findOvertimeTimeTemplateField(fields = []) {
+ return (
+ fields.find((f) => f?.type === "datetimerange" && String(f?.label || "").includes("鍔犵彮鏃堕棿")) ||
+ fields.find((f) => f?.type === "datetimerange") ||
+ null
+ );
+}
+
+function resolveOvertimeTimeRange(payload, overtimeTimeField) {
+ if (!overtimeTimeField?.key) return { start: "", end: "" };
+ const val = payload?.[overtimeTimeField.key];
+ if (!Array.isArray(val) || val.length < 2) return { start: "", end: "" };
+ return { start: val[0] || "", end: val[1] || "" };
+}
+
+function computeOvertimeHours(startStr, endStr) {
+ if (!startStr || !endStr) return null;
+ const t0 = dayjs(startStr);
+ const t1 = dayjs(endStr);
+ if (!t0.isValid() || !t1.isValid() || !t1.isAfter(t0)) return null;
+ return Math.round((t1.diff(t0, "millisecond") / 3600000) * 100) / 100;
+}
+
+function overtimeHoursDisplay(form) {
+ const field = findOvertimeTimeTemplateField(form.formFieldDefs);
+ const { start, end } = resolveOvertimeTimeRange(form.formPayload, field);
+ const h = computeOvertimeHours(start, end);
+ return h == null ? "" : String(h);
+}
+
+const { proxy } = getCurrentInstance();
+
+const searchForm = reactive({
+ instanceNo: "",
+ applicantKeyword: "",
+});
+
+const mod = useApprovalInstanceModule({
+ moduleKey: APPROVAL_MODULE_KEYS.OVERTIME,
+ beforeSave: validateOvertimeBeforeSave,
+});
+
+const {
+ tableData,
+ tableLoading,
+ page,
+ detailDialog,
+ detailRow,
+ submitDialog,
+ submitForm,
+ submitFormRef,
+ submitSaving,
+ isSubmitEdit,
+ activeTemplate,
+ submitFormFields,
+ submitFormRules,
+ submitDialogTitle,
+ templateBindVisible,
+ handleQuery,
+ initModuleList,
+ pagination,
+ openAddWithTemplate,
+ onTemplateBound,
+ onTemplateBindClosed,
+ openEditFromDetail,
+ submitInstanceForm,
+ buildTableActions,
+} = mod;
+
+const { flowUserOptions, loadFlowUsers } = useFlowUserOptions();
+
+function validateOvertimeBeforeSave() {
+ const field = findOvertimeTimeTemplateField(submitForm.formFieldDefs);
+ const { start, end } = resolveOvertimeTimeRange(submitForm.formPayload, field);
+ if (computeOvertimeHours(start, end) == null) {
+ ElMessage.warning("璇锋鏌ユā鏉夸腑鐨勫姞鐝椂闂达紝缁撴潫鏃堕棿椤绘櫄浜庡紑濮嬫椂闂�");
+ throw new Error("invalid overtime time");
+ }
+}
+
+const tableColumn = buildInstanceTableColumns(tableData, buildTableActions, {
+ moduleKey: APPROVAL_MODULE_KEYS.OVERTIME,
+});
+
+function onSearch() {
+ handleQuery(searchForm);
+}
+
+function resetSearch() {
+ searchForm.instanceNo = "";
+ searchForm.applicantKeyword = "";
+ onSearch();
+}
+
+function onPagination(obj) {
+ pagination(obj, searchForm);
+}
+
+async function onSubmit() {
+ const ok = await submitInstanceForm({ skipValidate: true });
+ if (ok) ElMessage.success(isSubmitEdit.value ? "淇敼鎴愬姛" : "鎻愪氦鎴愬姛");
+}
+
+function handleExport() {
+ const data = tableData.value;
+ const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json;charset=utf-8" });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = `鍔犵彮鐢宠瀵煎嚭_${dayjs().format("YYYYMMDDHHmmss")}.json`;
+ a.click();
+ URL.revokeObjectURL(url);
+ proxy?.$modal?.msgSuccess?.(`宸插鍑� ${data.length} 鏉★紙褰撳墠椤靛垪琛ㄦ暟鎹級`);
+}
+
+onMounted(async () => {
+ loadFlowUsers();
+ await initModuleList(searchForm);
+});
+</script>
+
+<style scoped>
+.mb20 {
+ margin-bottom: 20px;
+}
+.search_form {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+.search_actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+.search_title {
+ font-size: 14px;
+ color: var(--el-text-color-regular);
+}
+</style>
--
Gitblit v1.9.3