Ver código fonte

修改国际协调时间

吴sir 2 meses atrás
pai
commit
3017c23f62

+ 1 - 0
src/App.vue

@@ -34,6 +34,7 @@ async function getIpClient() {
     try {
         const response = await axios.get('https://ipinfo.io/json');
         systemStore.USER_IP = response.data
+        localStorage.setItem('IPCONFIG', JSON.stringify(response.data))
     } catch (error) {
         console.error(error);
     }

+ 226 - 34
src/components/Steps/index.vue

@@ -1,39 +1,231 @@
 <template>
-    <a-steps changeable :current="current" @change="setCurrent">
-        <a-step description="This is a description">Succeeded</a-step>
-        <a-step description="This is a description">Processing</a-step>
-        <a-step description="This is a description">Pending</a-step>
-    </a-steps>
-    <div :style="{
-        width: '100%',
-        height: '200px',
-        textAlign: 'center',
-        background: 'var(--color-bg-2)',
-        color: '#C2C7CC',
-    }">
-        <a-space size="large">
-            <a-button type="secondary" :disabled="current <= 1" @click="onPrev">
-                <IconLeft /> Back
+    <div>
+        <div class="header">
+            <a-button type="primary" @click="onCancel">
+                返回
             </a-button>
-            <a-button type="primary" :disabled="current >= 3" @click="onNext">
-                Next
-                <IconRight />
-            </a-button>
-        </a-space>
+        </div>
+        <a-steps changeable :current="current" @change="setCurrent" label-placement="vertical">
+            <!-- 数组格式 -->
+            <template v-if="isShowArray">
+                <a-step v-for="(step, index) in StepsData" :key="index">
+                    第{{ index + 1 }}步
+                    <template #icon v-if="submitShow && current == (maxStep)">
+                        <icon-loading />
+                    </template>
+                </a-step>
+            </template>
+
+            <a-step>结果</a-step>
+        </a-steps>
+
+        <!-- 动态渲染表单数据 -->
+        <template v-if="isShowArray">
+            <keep-alive>
+                <div class="steps-conter">
+                    <div>
+                        <div v-for="(item, index) in StepsData[current - 1]" :key="item.id || item.field">
+                            <div :style="{ width: width }" v-show="visibleShowMap[item.field]">
+                                <a-form-item :label="item.label" :rules="item.rules" :field="item.field"
+                                    :validate-trigger="rulesTagse(item?.rules)">
+                                    <!-- 使用 key 触发重新渲染 -->
+                                    <component :is="'a-' + item.type" v-model="formState[item.field]"
+                                        :placeholder="item.type === 'input' ? '请输入' : '请选择' + item.label" allow-clear
+                                        :style="{ width: item.width ? item.width + 'px' : '' }"
+                                        :key="formState[item.field]">
+                                        <template v-if="item.type === 'select'">
+                                            <a-option v-for="option in item.options" :key="option.value"
+                                                :value="option.value">
+                                                {{ option.label }}
+                                            </a-option>
+                                        </template>
+                                    </component>
+                                </a-form-item>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </keep-alive>
+        </template>
+
+        <!-- 如果 StepsData 不是数组的格式,渲染单个表单项 -->
+        <template v-if="!isShowArray">
+            <component :is="'a-' + StepsData.type" v-model="StepsData.value"
+                :placeholder="StepsData.type === 'input' ? '请输入' : '请选择' + StepsData.label" allow-clear
+                :style="{ width: StepsData.width ? StepsData.width + 'px' : '' }">
+                <template v-if="StepsData.type === 'select'">
+                    <a-option v-for="option in StepsData.options" :key="option.value" :value="option.value">
+                        {{ option.label }}
+                    </a-option>
+                </template>
+            </component>
+        </template>
+
+        <!-- 底部按钮 -->
+        <div class="step-footer">
+            <a-space size="large">
+                <template v-if="isShowArray">
+                    <a-button type="secondary" :disabled="current <= 1" @click="onPrev">
+                        <IconLeft /> 上一步
+                    </a-button>
+                    <a-button type="primary" :disabled="current >= maxStep" @click="onNext" v-if="maxStep !== current">
+                        下一步
+                        <IconRight />
+                    </a-button>
+
+                    <a-button type="primary" @click="onFinish" v-else>
+                        确认
+                    </a-button>
+                </template>
+
+                <template v-if="!isShowArray">
+                    <a-button type="primary" @click="onCancel">
+                        取消
+                    </a-button>
+                    <a-button type="primary" @click="onFinish">
+                        确认
+                    </a-button>
+                </template>
+            </a-space>
+        </div>
     </div>
 </template>
+
 <script setup>
-import { reactive } from 'vue'
-     const current = reactive(1)
-        onPrev() {
-            current = Math.max(1, this.current - 1)
-        }
-
-        onNext() {
-            current = Math.min(3, this.current + 1)
-        }
-
-        setCurrent(current) {
-            current = current
-        }
-</script>
+import { ref, defineProps, toRefs, computed, defineEmits } from 'vue';
+
+// const StepsData = [
+//   [
+//     { type: 'select', label: '姓名', field: 'name', value: '',options:[], isVisible:  (item, e) => {
+//       if(e.gender=='male'){
+//         item.options = [{ value: 'male', label: '男' }, { value: 'female', label: '女' }]
+//       }
+//       return e.gender=='male'
+//     } },
+//     { type: 'select', label: '性别', field: 'gender',value:"", options: [{ value: 'male', label: '男' }, { value: 'female', label: '女' }] },
+//   ],
+//   [
+//     { type: 'input', label: '年龄', field: 'age', value: '' },
+//     { type: 'input', label: '电话', field: 'phone', value: '' },
+//   ],
+]
+const props = defineProps({
+    StepsData: {
+        type: Array,
+        default: () => []  // 默认值设置为数组套数组
+    }, // 步骤条数据层
+    width: {
+        type: [String, Number],
+        default: "50vw"
+    }
+});
+
+const emit = defineEmits(['step-change', 'onCancel', 'onSubmit']);
+
+const { StepsData, width } = toRefs(props);
+
+// 判断当前是否是数组套数组
+const isShowArray = computed(() => Array.isArray(StepsData.value));
+
+// 初始化表单状态
+const formState = ref({});
+const current = ref(1);
+const submitShow = ref(false)
+// 计算最大步骤数
+const maxStep = computed(() => (isShowArray.value ? StepsData.value.length : 1));
+
+// 初始化 formState
+if (isShowArray.value) {
+    StepsData.value.forEach(step => {
+        step.forEach(item => {
+            if (item.field) {
+                formState.value[item.field] = item.value;
+            }
+        });
+    });
+} else if (StepsData.value && StepsData.value.value) {
+    formState.value = StepsData.value.value;
+}
+
+// 使用 computed 来动态计算每个表单项的可见性
+const visibleShowMap = computed(() => {
+    const visibilityMap = {};
+    // 遍历每个步骤,计算每个表单项的可见性
+    StepsData.value.forEach((step) => {
+        step.forEach((item) => {
+            if (item.field) {
+                if (item.isVisible) {
+                    if (typeof item.isVisible === 'function') {
+                        // 如果 isVisible 是函数,执行并设置结果
+                        visibilityMap[item.field] = item.isVisible(item, formState.value);
+                    } else {
+                        // 否则直接使用 isVisible 的值
+                        visibilityMap[item.field] = item.isVisible;
+                    }
+                } else {
+                    visibilityMap[item.field] = true;  // 默认可见
+                }
+            }
+        });
+    });
+
+    return visibilityMap;
+});
+
+// 表单验证方式
+const rulesTagse = (item) => {
+    if (!item) return ''
+    return item[0]?.trigger
+}
+
+// 上一步
+const onPrev = () => {
+    current.value = Math.max(1, current.value - 1);
+};
+
+// 下一步
+const onNext = () => {
+    current.value = Math.min(maxStep.value, current.value + 1);
+};
+
+// 点击步骤条
+const setCurrent = (e) => {
+    current.value = e;
+    emit('step-change', e); // Emit step change to parent
+};
+
+// 取消
+const onCancel = () => {
+    emit('onCancel', true)
+}
+
+// 确认
+const onFinish = () => {
+    emit('onSubmit', formState.value)
+    current.value = Math.min(maxStep.value+1, current.value + 1);
+    submitShow.value = true
+}
+</script>
+
+<style scoped>
+.step-footer {
+    width: 100%;
+    height: 200px;
+    text-align: center;
+    background: var(--color-bg-2);
+    color: #C2C7CC;
+    padding-top: 20px;
+}
+
+.steps-conter {
+    display: flex;
+    justify-content: center;
+    margin-top: 20px;
+}
+
+.header {
+    margin-bottom: 50px;
+    display: flex;
+    justify-content: end;
+}
+</style>

+ 1 - 1
src/store/modules/systemStore.js

@@ -11,7 +11,7 @@ const INITIALIZE = {
   menuSecondLongShow: false,
   user_login_information: "",
   stsClientInfo: {},
-  USER_IP:{}
+  USER_IP: {}
 };
 try {
   const SYSTEM_STORE = getLocalStorage("SYSTEM_STORE")

+ 54 - 14
src/utils/axios.js

@@ -108,27 +108,67 @@ axiosInstance.interceptors.response.use(
 function timeLoadTemeYear(value) {
   if (!value) return;
   const systemStore = useSystemStore();
-  const date = moment(value, moment.ISO_8601);
-  if (!date.isValid()) return null
-  // 使用用户所在时区转换时间
-  if (systemStore.getUserIp && systemStore.getUserIp.timezone) {
-    const localDate = date.tz(systemStore.getUserIp.timezone);
-    const time = localDate.format('YYYY-MM-DD HH:mm:ss');
-    return time;
-  } else {
-    return null;
+  const timezone = systemStore.getUserIp?.timezone || JSON.parse(localStorage.getItem('IPCONFIG'))?.timezone
+  if (timezone) {
+    // 转换 UTC 时间为用户的本地时间
+    let localDate = moment.utc(value).tz(timezone);
+
+    if (!localDate.isValid()) {
+      return null;  // 如果时间无效,返回 null
+    }
+
+    // 格式化并返回本地时间
+    const localTime = localDate.format('YYYY-MM-DD HH:mm:ss');
+    return localTime;
   }
+
+  return value
+
 }
 
+
+
+
 // 转换数据格式 
 function DataViewsProvider(data) {
-  if (!Array.isArray(data)) return data
+  if (!data) return data;
+
+  // 如果数据是对象并且包含 records 字段
+  if (data.records && Array.isArray(data.records)) {
+    return {
+      ...data,
+      records: data.records.map(item => {
+        const transformedItem = { ...item };
+
+        if (item.createdAt) transformedItem.createdAt = timeLoadTemeYear(item.createdAt);
+        if (item.updatedAt) transformedItem.updatedAt = timeLoadTemeYear(item.updatedAt);
+        if (item.endDate) transformedItem.endDate = timeLoadTemeYear(item.endDate);
+        if (item.activeTime) transformedItem.activeTime = timeLoadTemeYear(item.activeTime);
 
-  if (data && data.records) {
-    return { ...data, records: data.records.map(item => ({ ...item, createdAt: timeLoadTemeYear(item.createdAt || false), updatedAt: timeLoadTemeYear(item.updatedAt || false) ,endDate: timeLoadTemeYear(item.endDate || false) })) }
-  }else{
-    return data.map(item => ({...item, createdAt: timeLoadTemeYear(item.createdAt || false), updatedAt: timeLoadTemeYear(item.updatedAt || false) }))
+        return transformedItem;
+      })
+    };
   }
+
+  // 如果数据本身是数组
+  if (Array.isArray(data)) {
+    return data.map(item => {
+      const transformedItem = { ...item };
+
+      if (item.createdAt) transformedItem.createdAt = timeLoadTemeYear(item.createdAt);
+      if (item.updatedAt) transformedItem.updatedAt = timeLoadTemeYear(item.updatedAt);
+      if (item.endDate) transformedItem.endDate = timeLoadTemeYear(item.endDate);
+      if (item.activeTime) transformedItem.activeTime = timeLoadTemeYear(item.activeTime);
+
+      return transformedItem;
+    });
+  }
+
+  // 如果数据不是数组也不是包含 records 的对象,直接返回数据
+  return data;
 }
 
+
+
+
 export default axiosInstance;

+ 11 - 1
src/views/admin/order/CancelOrder/index.vue

@@ -23,9 +23,10 @@
       </template>
     </a-table>
 
-
+    
     <Status v-model:modelValue="showAudit" @submit="intData()" />
     <Detaile v-model:modelValue="showDetail" @submit="intData()" :FormDataList="FormDataList" />
+
   </div>
 </template>
 
@@ -67,6 +68,15 @@ const columns = [
   { title: '操作', slotName: 'operate', align: 'center', ellipsis: true }
 ];
 
+const StepsData = [
+  {
+    title: '创建',
+    status: 'process',
+    description: '2022-01-01 10:00:00',
+  },
+
+]
+
 // 查看订单详情
 const openDetail = (item) => {
   showDetail.value = true;