zhb 2 ماه پیش
والد
کامیت
c748650dbe
4فایلهای تغییر یافته به همراه118 افزوده شده و 86 حذف شده
  1. 60 64
      components/cwg-detail-popup.vue
  2. 33 18
      components/cwg-tabel.vue
  3. 4 4
      pages/customer/recording-history.vue
  4. 21 0
      utils/noteHelper.ts

+ 60 - 64
components/cwg-detail-popup.vue

@@ -1,75 +1,85 @@
 <template>
-    <uni-popup ref="popupRef" type="center" @change="handlePopupChange">
-        <view class="cwg-dialog">
-            <!-- 弹窗头部 -->
-            <view class="dialog-header">
-                <text class="dialog-title">{{ title || t('Tips.DeleteAccount') }}</text>
-                <uni-icons type="closeempty" size="20" color="#999" @click="closeDialog" />
-            </view>
-
-            <!-- 弹窗内容 -->
-            <view class="dialog-content">
-                <view class="lines">
+    <cwg-popup v-model:visible="visible" type="center" :mask-click="false" :showFooters="true" :title="t('Btn.Detail')">
+        <view class="popup-content">
+            <view class="lines">
+                <template v-if="items && items.length">
                     <cwg-label-line-value v-for="(item, index) in items" :key="index" :label="item.label"
                         :value="item.value" />
-                </view>
+                </template>
+
+                <template v-else-if="row && columns && columns.length">
+                    <cwg-label-line-value v-for="(item, index) in columns" :key="index" :label="item.label">
+                        <template #operation1>
+                            <slot :name="`cell-${item.prop}`" :row="row" :column="item" :index="index">
+                                <text>{{ formatCellValue(row[item.prop], item, row) }}</text>
+                            </slot>
+                        </template>
+
+                    </cwg-label-line-value>
+                </template>
 
-            </view>
-            <view class="dialog-footer">
-                <button class="single-btn" :class="singleBtnType" @click="closeDialog" v-t="'Ib.Custom.Close'" />
             </view>
         </view>
-    </uni-popup>
+        <template #footer>
+            <button class="single-btn default" @click="visible = false" v-t="'Home.msg.item3'" />
+        </template>
+    </cwg-popup>
 </template>
 
+
 <script setup>
-import { ref, watch, computed } from 'vue'
+import { ref, computed } from 'vue'
 import { useI18n } from 'vue-i18n'
 
 const { t } = useI18n()
 
 const props = defineProps({
-    // 是否显示弹窗
-    visible: {
-        type: Boolean,
-        default: false
-    },
+    visible: { type: Boolean, default: false },
     title: { type: String, default: '详情' },
-    items: { type: Array, default: () => [] }
+    // 旧方式
+    items: { type: Array, default: () => [] },
+    // 新方式
+    row: { type: Object, default: null },
+    columns: { type: Array, default: () => [] }
 })
 
-const emit = defineEmits(['update:visible', 'confirm', 'close', 'single-click'])
-
-// 弹窗引用
-const popupRef = ref(null)
-
-// 监听 visible 变化
-watch(() => props.visible, (val) => {
-    if (val) {
-        popupRef.value?.open()
-    } else {
-        popupRef.value?.close()
+const emit = defineEmits(['update:visible', 'close'])
+// Watch for changes in visible prop and emit update event
+const visible = computed({
+    get: () => props.visible,
+    set: (value) => emit('update:visible', value)
+});
+// 格式化单元格值(与表格组件保持一致的逻辑,可以提取成公共工具函数)
+const formatCellValue = (value, column, row) => {
+    if (column.formatter) {
+        return column.formatter({ value, row })
     }
-}, { immediate: true })
-
-// 弹窗状态变化
-const handlePopupChange = (e) => {
-    if (!e.show) {
-        emit('update:visible', false)
-        emit('close')
+    if (column.type === 'date' && value) {
+        return formatDate(value, column.dateFormat || 'YYYY-MM-DD HH:mm:ss')
     }
+    if (value === null || value === undefined) {
+        return '-'
+    }
+    return value
 }
 
-// 关闭弹窗
-const closeDialog = () => {
-    popupRef.value?.close()
+const formatDate = (date, format) => {
+    if (!date) return '-'
+    const d = new Date(date)
+    const year = d.getFullYear()
+    const month = String(d.getMonth() + 1).padStart(2, '0')
+    const day = String(d.getDate()).padStart(2, '0')
+    const hour = String(d.getHours()).padStart(2, '0')
+    const minute = String(d.getMinutes()).padStart(2, '0')
+    const second = String(d.getSeconds()).padStart(2, '0')
+    return format
+        .replace('YYYY', year)
+        .replace('MM', month)
+        .replace('DD', day)
+        .replace('HH', hour)
+        .replace('mm', minute)
+        .replace('ss', second)
 }
-
-// 暴露方法给父组件
-defineExpose({
-    close: closeDialog,
-    open: () => popupRef.value?.open()
-})
 </script>
 
 <style scoped lang="scss">
@@ -79,20 +89,6 @@ defineExpose({
     z-index: 101;
 }
 
-.cwg-dialog {
-    background-color: var(--color-white);
-    border-radius: px2rpx(8);
-    overflow: hidden;
-    width: px2rpx(600);
-    max-width: 90vw;
-}
-
-@media (min-width: 768px) {
-    :deep(.cwg-dialog) {
-        width: px2rpx(600) !important;
-    }
-}
-
 
 .dialog-header {
     display: flex;

+ 33 - 18
components/cwg-tabel.vue

@@ -34,6 +34,9 @@
                             <view v-else-if="column.type === 'file'">
                                 <cwg-file :path="row[column.prop]" />
                             </view>
+                            <view v-else-if="column.type === 'note'">
+                                <text>{{ getNoteText(row, locale, userStore) }}</text>
+                            </view>
                             <cwg-icon v-else-if="column.type === 'more'" name="crm-chevron-down"
                                 class="crm-chevron-down" :size="16" color="#007" />
                             <template v-else>
@@ -55,8 +58,9 @@
 
                 <!-- 总计行 -->
                 <uni-tr v-if="showSummary" class="summary-row">
-                    <uni-td v-for="(column, index) in displayColumns" :key="'summary-' + column.prop" :align="column.align || 'center'"
-                        class="summary-cell" :style="getCellStyle(column, currentSummaryData)">
+                    <uni-td v-for="(column, index) in displayColumns" :key="'summary-' + column.prop"
+                        :align="column.align || 'center'" class="summary-cell"
+                        :style="getCellStyle(column, currentSummaryData)">
                         <!-- 当有 summaryMethod 时,按照返回的数组直接渲染 -->
                         <template v-if="props.summaryMethod">
                             <text>{{ computedSummaryRow[index] !== undefined ? computedSummaryRow[index] : '' }}</text>
@@ -64,17 +68,21 @@
                         <template v-else>
                             <!-- 特定列的总计自定义插槽,例如 #summary-volume="{ row }" -->
                             <template v-if="$slots['summary-' + column.prop]">
-                                <slot :name="'summary-' + column.prop" :row="currentSummaryData" :column="column" :index="index"></slot>
+                                <slot :name="'summary-' + column.prop" :row="currentSummaryData" :column="column"
+                                    :index="index"></slot>
                             </template>
                             <!-- 如果没有特定插槽,尝试常规渲染 -->
                             <template v-else>
-                                <template v-if="currentSummaryData && currentSummaryData[column.prop] !== undefined && currentSummaryData[column.prop] !== null">
+                                <template
+                                    v-if="currentSummaryData && currentSummaryData[column.prop] !== undefined && currentSummaryData[column.prop] !== null">
                                     <!-- 如果有常规插槽,并且总计数据里有该字段的值,则复用常规插槽渲染 -->
-                                    <slot v-if="column.slot" :name="column.slot" :row="currentSummaryData" :column="column" :index="index">
+                                    <slot v-if="column.slot" :name="column.slot" :row="currentSummaryData"
+                                        :column="column" :index="index">
                                         {{ currentSummaryData[column.prop] }}
                                     </slot>
                                     <!-- 否则使用格式化函数 -->
-                                    <text v-else>{{ formatCellValue(currentSummaryData[column.prop], column, currentSummaryData) }}</text>
+                                    <text v-else>{{ formatCellValue(currentSummaryData[column.prop], column,
+                                        currentSummaryData) }}</text>
                                 </template>
                                 <!-- 如果总计数据里没有该字段的值,第一列显示总计文本,其他留空 -->
                                 <text v-else>{{ index === 0 ? summaryText : '' }}</text>
@@ -121,13 +129,22 @@
             </view>
         </view>
         <!-- 移动端详情弹窗 -->
-        <cwg-detail-popup v-model:visible="detailVisible" title="详情" :items="detailItems" />
+        <!-- <cwg-detail-popup v-model:visible="detailVisible" title="详情" :items="detailItems" /> -->
+        <cwg-detail-popup v-model:visible="detailVisible" title="详情" :row="detailRow" :columns="detailColumns">
+            <template v-for="col in detailColumns" :key="col.prop" #[`cell-${col.prop}`]="{ row, column }">
+                <slot v-if="col.slot" :name="col.slot" :row="row" :column="column" :index="0" />
+            </template>
+        </cwg-detail-popup>
     </view>
 </template>
 
 <script setup>
 import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
-
+import { getNoteText } from '@/utils/noteHelper';
+import useUserStore from "@/stores/use-user-store";
+import { useI18n } from "vue-i18n";
+const userStore = useUserStore();
+const { locale } = useI18n();
 const props = defineProps({
     /**
      * 表格列配置(columns 数组中每一项是一个列配置对象)
@@ -193,7 +210,6 @@ const props = defineProps({
     // 总计行第一列的默认文本
     summaryText: { type: String, default: '总计' },
 })
-
 const emit = defineEmits([
     'selection-change',
     'action-click',
@@ -209,6 +225,9 @@ const tableData = ref([])
 const selectedItems = ref([])
 const detailVisible = ref(false)
 const detailItems = ref([])
+// 替换原来的 detailItems 相关定义
+const detailRow = ref(null)
+const detailColumns = ref([])
 const pagination = ref({
     current: 1,
     pageSize: props.defaultPageSize,
@@ -444,20 +463,16 @@ const toggleRowExpand = (rowIndex) => {
     emit('expand-change', { rowIndex, expanded: expandedRows.value[key] })
 }
 // 打开详情弹窗(移动端使用)
+// 修改 openRowDetail
 const openRowDetail = (row) => {
-
     if (props.isPages) {
         emit('go-pages', row)
     } else {
-        detailItems.value = props.columns
-            .filter((column) => column && column.prop && column.label)
-            .map((column) => ({
-                label: column.label,
-                value: String(formatCellValue(row[column.prop], column, row))
-            }))
+        // 保存当前行和需要显示的列(有 prop 且有 label)
+        detailRow.value = { ...row, note: getNoteText(row, locale.value, userStore) }
+        detailColumns.value = props.columns.filter(col => col && col.prop && col.label)
         detailVisible.value = true
     }
-
 }
 
 // ========== 数据加载 ==========
@@ -678,7 +693,7 @@ defineExpose({
         .summary-row {
             background-color: #fafafa;
             font-weight: 600;
-            
+
             .uni-table-td {
                 border-top: 1px solid #ebeef5 !important;
                 position: sticky;

+ 4 - 4
pages/customer/recording-history.vue

@@ -110,7 +110,7 @@ const getColumnsByType = (type: number) => {
                 {
                     prop: 'note',
                     label: t('Custom.Recording.Note'),
-                    formatter: ({ row }) => row.note || '--',
+                    type: 'note',
                     align: 'left'
                 }
             ]
@@ -150,7 +150,7 @@ const getColumnsByType = (type: number) => {
                 {
                     prop: 'note',
                     label: t('Custom.Recording.Note'),
-                    formatter: ({ row }) => row.note || '--',
+                    type: 'note',
                     align: 'left'
                 }
             ]
@@ -197,7 +197,7 @@ const getColumnsByType = (type: number) => {
                 {
                     prop: 'note',
                     label: t('Custom.Recording.Note'),
-                    formatter: ({ row }) => row.note || '--',
+                    type: 'note',
                     align: 'left'
                 }
             ]
@@ -237,7 +237,7 @@ const getColumnsByType = (type: number) => {
                 {
                     prop: 'note',
                     label: t('Custom.Recording.Note'),
-                    formatter: ({ row }) => row.note || '--',
+                    type: 'note',
                     align: 'left'
                 }
             ]

+ 21 - 0
utils/noteHelper.ts

@@ -0,0 +1,21 @@
+
+/**
+ * 获取备注文本(同步纯函数)
+ */
+export function getNoteText(row: any, locale: string ,userStore: any): string {
+    console.log('row', row);
+    if (!row) return '--';
+    if (row.remark) return row.remark;
+    if (row.note) return row.note;
+
+    if (row.approveDesc) {
+
+        const option = userStore.reasonsOptions?.[row.approveDesc];
+        if (option) {
+            return locale === 'cn' || locale === 'zhHant'
+                ? option.content
+                : option.enContent;
+        }
+    }
+    return '--';
+}