feat(web-admin): add mp webview sheet and list chrome styles.
Provide shared Bottom Sheet and filter/speed-dial/fab tokens for the transport plan mobile redesign. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
3795fa2b5a
commit
8c69a01e16
2 files changed
+284
No files matched your search
@@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<div v-show="modelValue" class="mp-sheet-mask" @click="close" />
|
||||
<div
|
||||
v-show="modelValue"
|
||||
class="mp-sheet"
|
||||
:class="{ 'mp-sheet--half': half }"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
>
|
||||
<div class="mp-sheet-handle" />
|
||||
<div class="mp-sheet-head">
|
||||
<h3>{{ title }}</h3>
|
||||
<button class="mp-sheet-close" type="button" @click="close">关闭</button>
|
||||
</div>
|
||||
<div v-if="searchable" class="mp-sheet-search">
|
||||
<input
|
||||
v-model="keyword"
|
||||
class="mp-sheet-search-input"
|
||||
type="search"
|
||||
:placeholder="searchPlaceholder"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</div>
|
||||
<div class="mp-sheet-body">
|
||||
<slot :keyword="keyword" />
|
||||
</div>
|
||||
<div v-if="$slots.footer" class="mp-sheet-foot">
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
modelValue: boolean
|
||||
title?: string
|
||||
searchable?: boolean
|
||||
searchPlaceholder?: string
|
||||
half?: boolean
|
||||
}>(),
|
||||
{
|
||||
title: '',
|
||||
searchable: false,
|
||||
searchPlaceholder: '搜索',
|
||||
half: false
|
||||
}
|
||||
)
|
||||
const emit = defineEmits<{ 'update:modelValue': [boolean] }>()
|
||||
const keyword = ref('')
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(open) => {
|
||||
if (open) keyword.value = ''
|
||||
}
|
||||
)
|
||||
|
||||
function close() {
|
||||
emit('update:modelValue', false)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mp-sheet-mask {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 2000;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
backdrop-filter: none;
|
||||
}
|
||||
.mp-sheet {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 2001;
|
||||
max-height: 78vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
border-radius: 16px 16px 0 0;
|
||||
padding-bottom: env(safe-area-inset-bottom, 0px);
|
||||
}
|
||||
.mp-sheet--half { max-height: 50vh; }
|
||||
.mp-sheet-handle {
|
||||
width: 36px;
|
||||
height: 4px;
|
||||
margin: 8px auto 0;
|
||||
border-radius: 999px;
|
||||
background: #dcebe4;
|
||||
}
|
||||
.mp-sheet-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 16px;
|
||||
}
|
||||
.mp-sheet-head h3 { margin: 0; font-size: 16px; }
|
||||
.mp-sheet-close {
|
||||
border: none;
|
||||
background: none;
|
||||
color: #0a9f6d;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.mp-sheet-search { padding: 0 16px 8px; }
|
||||
.mp-sheet-search-input {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid #dcebe4;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.mp-sheet-body {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
padding: 0 8px 12px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
.mp-sheet-foot {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 10px 16px;
|
||||
border-top: 1px solid #dcebe4;
|
||||
}
|
||||
</style>
|
||||
@@ -161,3 +161,155 @@
|
||||
border-radius: 12px;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* === redesign 2026-09-15 === */
|
||||
.mp-wv-filter-wrap {
|
||||
position: relative;
|
||||
z-index: 20;
|
||||
}
|
||||
.mp-wv-filter-bar {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 0;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #dcebe4;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
}
|
||||
.mp-wv-filter-trig {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
height: 40px;
|
||||
font-size: 13px;
|
||||
color: #1f2a26;
|
||||
background: #fff;
|
||||
border: none;
|
||||
border-right: 1px solid #dcebe4;
|
||||
cursor: pointer;
|
||||
}
|
||||
.mp-wv-filter-trig:last-child { border-right: none; }
|
||||
.mp-wv-filter-trig.open { color: #0a9f6d; font-weight: 600; }
|
||||
.mp-wv-filter-panel {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #dcebe4;
|
||||
max-height: 280px;
|
||||
overflow: auto;
|
||||
z-index: 21;
|
||||
}
|
||||
.mp-wv-filter-panel.open { display: block; }
|
||||
.mp-wv-filter-opt {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
background: #fff;
|
||||
border: none;
|
||||
border-bottom: 1px solid #eef4f1;
|
||||
cursor: pointer;
|
||||
}
|
||||
.mp-wv-filter-opt.active { color: #0a9f6d; font-weight: 600; }
|
||||
.mp-wv-filter-mask {
|
||||
display: none;
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.35);
|
||||
z-index: 19;
|
||||
}
|
||||
.mp-wv-filter-mask.open { display: block; }
|
||||
|
||||
.mp-wv-speed-dial {
|
||||
position: fixed;
|
||||
right: 16px;
|
||||
bottom: calc(16px + env(safe-area-inset-bottom, 0px));
|
||||
z-index: 30;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
.mp-wv-speed-main {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
background: #0a9f6d;
|
||||
color: #fff;
|
||||
font-size: 28px;
|
||||
line-height: 1;
|
||||
box-shadow: 0 8px 20px rgba(10, 159, 109, 0.35);
|
||||
cursor: pointer;
|
||||
}
|
||||
.mp-wv-speed-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid #dcebe4;
|
||||
background: #fff;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.mp-wv-speed-item.primary {
|
||||
background: #0a9f6d;
|
||||
border-color: #0a9f6d;
|
||||
color: #fff;
|
||||
}
|
||||
.mp-wv-speed-menu { display: none; flex-direction: column; gap: 8px; align-items: flex-end; }
|
||||
.mp-wv-speed-dial.open .mp-wv-speed-menu { display: flex; }
|
||||
.mp-wv-speed-mask {
|
||||
display: none;
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
z-index: 29;
|
||||
}
|
||||
.mp-wv-speed-mask.open { display: block; }
|
||||
|
||||
.mp-wv-fab-bar {
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px));
|
||||
background: #fff;
|
||||
border-top: 1px solid #dcebe4;
|
||||
z-index: 15;
|
||||
}
|
||||
.mp-wv-fab-bar .mp-wv-btn { flex: 1; }
|
||||
.mp-wv-fab-bar .mp-wv-btn-more { flex: 0 0 44px; }
|
||||
|
||||
.mp-wv-section {
|
||||
margin: 0 0 12px;
|
||||
padding: 12px;
|
||||
background: #fff;
|
||||
border: 1px solid #dcebe4;
|
||||
border-radius: 14px;
|
||||
}
|
||||
.mp-wv-section h3 {
|
||||
margin: 0 0 10px;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #087f57;
|
||||
}
|
||||
.mp-wv-kv {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 6px 0;
|
||||
font-size: 13px;
|
||||
border-bottom: 1px solid #eef4f1;
|
||||
}
|
||||
.mp-wv-kv span:first-child { color: #6b7b74; flex-shrink: 0; }
|
||||
.mp-wv-kv span:last-child { text-align: right; word-break: break-all; }
|
||||
|
||||
.mp-wv-pad-speed { padding-bottom: 88px; }
|
||||
Reference in new issue
Block a user