From a9d97b150701e634bdb751eab277696abd136cca Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 16 六月 2026 14:39:47 +0800
Subject: [PATCH] 君歌app 1.依照web端功能修改
---
src/pages/oa/ReimburseManage/_components/ReimburseExpenseDetailSheet.vue | 315 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 315 insertions(+), 0 deletions(-)
diff --git a/src/pages/oa/ReimburseManage/_components/ReimburseExpenseDetailSheet.vue b/src/pages/oa/ReimburseManage/_components/ReimburseExpenseDetailSheet.vue
new file mode 100644
index 0000000..a0b25f0
--- /dev/null
+++ b/src/pages/oa/ReimburseManage/_components/ReimburseExpenseDetailSheet.vue
@@ -0,0 +1,315 @@
+<!--
+ 鎶ラ攢鏄庣粏鍗曟潯缂栬緫锛堝簳閮ㄥ脊灞傦級
+-->
+<template>
+ <up-popup :show="show"
+ mode="bottom"
+ round="16"
+ :safe-area-inset-bottom="true"
+ @close="close">
+ <view class="detail-sheet">
+ <view class="sheet-handle" />
+ <view class="sheet-head">
+ <text class="sheet-cancel"
+ @click="close">鍙栨秷</text>
+ <text class="sheet-title">{{ title }}</text>
+ <text class="sheet-confirm"
+ @click="confirm">淇濆瓨</text>
+ </view>
+
+ <scroll-view scroll-y
+ class="sheet-body"
+ :show-scrollbar="false">
+ <view class="sheet-group">
+ <view class="sheet-cell sheet-cell--tap"
+ @click="showDatePicker = true">
+ <text class="sheet-label required">鍙戠エ鏃ユ湡</text>
+ <view class="sheet-value-wrap">
+ <text class="sheet-value"
+ :class="{ placeholder: !draft.invoiceDate }">
+ {{ draft.invoiceDate || '璇烽�夋嫨' }}
+ </text>
+ <up-icon name="calendar"
+ size="18"
+ color="#c0c4cc" />
+ </view>
+ </view>
+ <view class="sheet-cell sheet-cell--tap"
+ @click="showSubjectSheet = true">
+ <text class="sheet-label required">璐圭敤绉戠洰</text>
+ <view class="sheet-value-wrap">
+ <text class="sheet-value"
+ :class="{ placeholder: !draft.expenseSubject }">
+ {{ subjectText }}
+ </text>
+ <up-icon name="arrow-right"
+ size="14"
+ color="#c0c4cc" />
+ </view>
+ </view>
+ <view class="sheet-cell">
+ <text class="sheet-label required">閲戦</text>
+ <view class="sheet-input-wrap">
+ <up-input v-model="draft.amount"
+ type="digit"
+ placeholder="0.00"
+ border="none"
+ input-align="right" />
+ <text class="sheet-unit">鍏�</text>
+ </view>
+ </view>
+ <view class="sheet-cell sheet-cell--col">
+ <text class="sheet-label">鎻忚堪</text>
+ <view class="sheet-textarea-wrap">
+ <up-textarea v-model="draft.description"
+ placeholder="璐圭敤璇存槑锛堥�夊~锛�"
+ maxlength="200"
+ border="none"
+ height="64" />
+ </view>
+ </view>
+ </view>
+
+ <view v-if="showDelete"
+ class="sheet-delete"
+ @click="emit('delete')">
+ 鍒犻櫎鏈潯鏄庣粏
+ </view>
+ </scroll-view>
+ </view>
+
+ <up-action-sheet :show="showSubjectSheet"
+ title="璐圭敤绉戠洰"
+ :actions="subjectActions"
+ @select="onSubjectSelect"
+ @close="showSubjectSheet = false" />
+
+ <up-popup :show="showDatePicker"
+ mode="bottom"
+ round="16"
+ @close="showDatePicker = false">
+ <up-datetime-picker :show="true"
+ v-model="datePickerTs"
+ mode="date"
+ @confirm="onDateConfirm"
+ @cancel="showDatePicker = false" />
+ </up-popup>
+ </up-popup>
+</template>
+
+<script setup>
+ import { computed, reactive, ref, watch } from "vue";
+ import { parseTime } from "@/utils/ruoyi";
+ import { expenseSubjectLabel as costSubjectLabel } from "../_utils/costReimburseUtils.js";
+ import { expenseSubjectLabel as travelSubjectLabel } from "../_utils/travelReimburseUtils.js";
+
+ const props = defineProps({
+ show: { type: Boolean, default: false },
+ modelValue: { type: Object, default: () => ({}) },
+ index: { type: Number, default: 0 },
+ isTravel: { type: Boolean, default: true },
+ subjectOptions: { type: Array, default: () => [] },
+ showDelete: { type: Boolean, default: true },
+ });
+
+ const emit = defineEmits(["update:show", "update:modelValue", "confirm", "delete"]);
+
+ const draft = reactive({
+ invoiceDate: "",
+ expenseSubject: "",
+ amount: "",
+ description: "",
+ });
+
+ const showDatePicker = ref(false);
+ const showSubjectSheet = ref(false);
+ const datePickerTs = ref(Date.now());
+
+ const title = computed(() => `鏄庣粏 ${props.index + 1}`);
+
+ const subjectActions = computed(() =>
+ (props.subjectOptions || []).map(x => ({ name: x.label, value: x.value }))
+ );
+
+ const subjectText = computed(() => resolveSubjectLabel(draft.expenseSubject));
+
+ function resolveSubjectLabel(v) {
+ if (!v) return "璇烽�夋嫨";
+ const labelFn = props.isTravel ? travelSubjectLabel : costSubjectLabel;
+ const t = labelFn(v);
+ if (t && t !== "鈥�") return t;
+ const hit = (props.subjectOptions || []).find(x => x.value === v || x.label === v);
+ return hit?.label || v;
+ }
+
+ watch(
+ () => props.show,
+ v => {
+ if (v && props.modelValue) {
+ Object.assign(draft, {
+ invoiceDate: "",
+ expenseSubject: "",
+ amount: "",
+ description: "",
+ ...JSON.parse(JSON.stringify(props.modelValue)),
+ });
+ }
+ }
+ );
+
+ function close() {
+ emit("update:show", false);
+ }
+
+ function confirm() {
+ if (!draft.invoiceDate) {
+ uni.showToast({ title: "璇烽�夋嫨鍙戠エ鏃ユ湡", icon: "none" });
+ return;
+ }
+ if (!draft.expenseSubject) {
+ uni.showToast({ title: "璇烽�夋嫨璐圭敤绉戠洰", icon: "none" });
+ return;
+ }
+ if (draft.amount === "" || draft.amount == null) {
+ uni.showToast({ title: "璇峰~鍐欓噾棰�", icon: "none" });
+ return;
+ }
+ emit("update:modelValue", { ...draft });
+ emit("confirm", { ...draft });
+ emit("update:show", false);
+ }
+
+ function onSubjectSelect(action) {
+ draft.expenseSubject = action.value;
+ showSubjectSheet.value = false;
+ }
+
+ function onDateConfirm(e) {
+ const ts = e?.value ?? datePickerTs.value;
+ draft.invoiceDate = parseTime(ts, "{y}-{m}-{d}");
+ showDatePicker.value = false;
+ }
+</script>
+
+<style scoped lang="scss">
+ .detail-sheet {
+ background: #fff;
+ border-radius: 16px 16px 0 0;
+ max-height: 85vh;
+ display: flex;
+ flex-direction: column;
+ }
+ .sheet-handle {
+ width: 36px;
+ height: 4px;
+ background: #e4e7ed;
+ border-radius: 2px;
+ margin: 8px auto 4px;
+ }
+ .sheet-head {
+ display: flex;
+ align-items: center;
+ padding: 8px 16px 12px;
+ border-bottom: 1px solid #f0f2f5;
+ }
+ .sheet-cancel {
+ font-size: 15px;
+ color: #909399;
+ min-width: 48px;
+ }
+ .sheet-title {
+ flex: 1;
+ text-align: center;
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ }
+ .sheet-confirm {
+ font-size: 15px;
+ color: #2979ff;
+ font-weight: 600;
+ min-width: 48px;
+ text-align: right;
+ }
+ .sheet-body {
+ max-height: 70vh;
+ padding-bottom: env(safe-area-inset-bottom);
+ }
+ .sheet-group {
+ margin: 12px 16px;
+ background: #f8f9fb;
+ border-radius: 12px;
+ overflow: hidden;
+ }
+ .sheet-cell {
+ display: flex;
+ align-items: center;
+ min-height: 52px;
+ padding: 12px 14px;
+ background: #fff;
+ border-bottom: 1px solid #f5f6f8;
+ &--col {
+ flex-direction: column;
+ align-items: stretch;
+ }
+ &--tap:active {
+ background: #fafbfc;
+ }
+ &:last-child {
+ border-bottom: none;
+ }
+ }
+ .sheet-label {
+ width: 80px;
+ font-size: 15px;
+ color: #303133;
+ flex-shrink: 0;
+ &.required::before {
+ content: "*";
+ color: #f56c6c;
+ margin-right: 2px;
+ }
+ }
+ .sheet-value-wrap {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ gap: 4px;
+ }
+ .sheet-value {
+ font-size: 15px;
+ color: #303133;
+ &.placeholder {
+ color: #c0c4cc;
+ }
+ }
+ .sheet-input-wrap {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ }
+ .sheet-unit {
+ font-size: 14px;
+ color: #909399;
+ margin-left: 4px;
+ }
+ .sheet-textarea-wrap {
+ width: 100%;
+ margin-top: 8px;
+ background: #f5f7fa;
+ border-radius: 8px;
+ padding: 4px 8px;
+ }
+ .sheet-delete {
+ margin: 16px;
+ text-align: center;
+ font-size: 15px;
+ color: #f56c6c;
+ padding: 14px;
+ background: #fff;
+ border-radius: 12px;
+ border: 1px solid #fde2e2;
+ }
+</style>
--
Gitblit v1.9.3