|
@@ -0,0 +1,172 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <Teleport to="body">
|
|
|
|
|
+ <transition name="fade">
|
|
|
|
|
+ <div v-if="visible" class="modal-mask" @click="closeModal"></div>
|
|
|
|
|
+ </transition>
|
|
|
|
|
+
|
|
|
|
|
+ <transition name="slide-up">
|
|
|
|
|
+ <div v-if="visible" class="modal-panel">
|
|
|
|
|
+ <div class="panel-handle-wrap">
|
|
|
|
|
+ <div class="panel-handle"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="panel-title">订单时效</div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="option-list">
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-for="item in options"
|
|
|
|
|
+ :key="item.value"
|
|
|
|
|
+ class="option-item"
|
|
|
|
|
+ @click="selectOption(item.value)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <span :class="{ 'active-text': modelValue === item.value }">
|
|
|
|
|
+ {{ item.label }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+
|
|
|
|
|
+ <div v-if="modelValue === item.value" class="check-icon">
|
|
|
|
|
+ <svg viewBox="0 0 1024 1024" width="16" height="16">
|
|
|
|
|
+ <path d="M512 0C229.23 0 0 229.23 0 512s229.23 512 512 512 512-229.23 512-512S794.77 0 512 0z" fill="#E03C3C"/>
|
|
|
|
|
+ <path d="M426.67 725.33L213.33 512l60.33-60.33L426.67 604.67 750.33 281l60.34 60.33-384 384z" fill="#FFFFFF"/>
|
|
|
|
|
+ </svg>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="safe-area-bottom"></div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </transition>
|
|
|
|
|
+ </Teleport>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup>
|
|
|
|
|
+import { defineProps, defineEmits } from 'vue';
|
|
|
|
|
+
|
|
|
|
|
+// 定义接收的属性
|
|
|
|
|
+const props = defineProps({
|
|
|
|
|
+ visible: {
|
|
|
|
|
+ type: Boolean,
|
|
|
|
|
+ default: false
|
|
|
|
|
+ },
|
|
|
|
|
+ modelValue: {
|
|
|
|
|
+ type: String,
|
|
|
|
|
+ default: ''
|
|
|
|
|
+ }
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 定义抛出的事件
|
|
|
|
|
+const emit = defineEmits(['update:visible', 'update:modelValue']);
|
|
|
|
|
+
|
|
|
|
|
+// 选项数据 (模拟设计稿内容)
|
|
|
|
|
+const options = [
|
|
|
|
|
+ { label: 'GTC(一直有效直到取消)', value: 'GTC' },
|
|
|
|
|
+ { label: 'IOC(立即成交否则取消)', value: 'IOC' },
|
|
|
|
|
+ { label: 'FOK(全部成交否则取消)', value: 'FOK' }
|
|
|
|
|
+];
|
|
|
|
|
+
|
|
|
|
|
+// 选择逻辑
|
|
|
|
|
+const selectOption = (value) => {
|
|
|
|
|
+ emit('update:modelValue', value); // 带回选中的值
|
|
|
|
|
+ closeModal(); // 关闭弹窗
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 关闭逻辑
|
|
|
|
|
+const closeModal = () => {
|
|
|
|
|
+ emit('update:visible', false);
|
|
|
|
|
+};
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+/* 遮罩层样式 */
|
|
|
|
|
+.modal-mask {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ width: 100vw;
|
|
|
|
|
+ height: 100vh;
|
|
|
|
|
+ background-color: rgba(0, 0, 0, 0.5);
|
|
|
|
|
+ z-index: 1000;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 弹窗主体样式 */
|
|
|
|
|
+.modal-panel {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ background: white;
|
|
|
|
|
+ border-radius: 16px 16px 0 0;
|
|
|
|
|
+ padding: 10px 0 0 0;
|
|
|
|
|
+ z-index: 1001;
|
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
+ /* 模拟手机最大宽度,防止在PC上太宽 */
|
|
|
|
|
+ max-width: 600px;
|
|
|
|
|
+ left: 50%;
|
|
|
|
|
+ transform: translateX(-50%);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 顶部小灰条 */
|
|
|
|
|
+.panel-handle-wrap {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ padding-bottom: 20px;
|
|
|
|
|
+}
|
|
|
|
|
+.panel-handle {
|
|
|
|
|
+ width: 36px;
|
|
|
|
|
+ height: 4px;
|
|
|
|
|
+ background: #E0E0E0;
|
|
|
|
|
+ border-radius: 2px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 标题 */
|
|
|
|
|
+.panel-title {
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ padding: 0 20px 20px 20px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 列表项 */
|
|
|
|
|
+.option-list {
|
|
|
|
|
+ padding: 0 20px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.option-item {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ padding: 16px 0;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ color: #999; /* 未选中默认为灰色 */
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* 选中时的文字颜色 */
|
|
|
|
|
+.active-text {
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.check-icon {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.safe-area-bottom {
|
|
|
|
|
+ height: 30px; /* 简单的安全区预留 */
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* Vue 动画过渡类 */
|
|
|
|
|
+.fade-enter-active, .fade-leave-active {
|
|
|
|
|
+ transition: opacity 0.3s ease;
|
|
|
|
|
+}
|
|
|
|
|
+.fade-enter-from, .fade-leave-to {
|
|
|
|
|
+ opacity: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.slide-up-enter-active, .slide-up-leave-active {
|
|
|
|
|
+ transition: transform 0.3s ease;
|
|
|
|
|
+}
|
|
|
|
|
+.slide-up-enter-from, .slide-up-leave-to {
|
|
|
|
|
+ transform: translate(-50%, 100%); /* 从底部滑出 */
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|