feat(aigc): add travel postcard AIGC feature
Add complete travel postcard AIGC creation workflow including: - New AIGC pages: template selection home, result detail, and history records - Reusable UI components: template card, flow steps, result preview, action buttons, record lists - Static assets including template images, fonts and styles - Updated TopNavBar component to support menu button alignment - Register new AIGC page routes in pages.json - Add mock data for templates, user records and result details
This commit is contained in:
@@ -4,8 +4,10 @@
|
||||
<view :style="{ height: statusBarHeight + 'px' }" v-if="!hideStatusBar"></view>
|
||||
|
||||
<!-- 导航栏内容 -->
|
||||
<view class="flex flex-items-center flex-justify-between border-box pl-8 pr-8"
|
||||
:style="{ height: navBarHeight + 'px' }">
|
||||
<view
|
||||
class="flex flex-items-center flex-justify-between border-box pl-8 pr-8"
|
||||
:style="navContentStyle"
|
||||
>
|
||||
<!-- 左侧返回按钮 -->
|
||||
<view class="nav-bar-left flex flex-items-center flex-justify-center" v-if="showBack" @click="handleBack">
|
||||
<uni-icons type="left" size="20" :color="backIconColor" />
|
||||
@@ -32,7 +34,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { computed, getCurrentInstance, onMounted, ref } from "vue";
|
||||
|
||||
// 定义props
|
||||
const props = defineProps({
|
||||
@@ -82,10 +84,15 @@ const props = defineProps({
|
||||
default: "center", // 'center' | 'left'
|
||||
validator: (value) => ["center", "left"].includes(value),
|
||||
},
|
||||
alignWithMenuButton: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
// 定义emits
|
||||
const emit = defineEmits(["back"]);
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
// 系统信息
|
||||
const statusBarHeight = ref(0);
|
||||
@@ -94,7 +101,8 @@ const navBarHeight = ref(44); // 默认导航栏高度
|
||||
// 获取系统信息
|
||||
onMounted(() => {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
statusBarHeight.value = systemInfo.statusBarHeight || 0;
|
||||
const systemStatusBarHeight = systemInfo.statusBarHeight || 0;
|
||||
statusBarHeight.value = systemStatusBarHeight;
|
||||
|
||||
// 根据平台设置导航栏高度
|
||||
if (systemInfo.platform === "ios") {
|
||||
@@ -102,6 +110,18 @@ onMounted(() => {
|
||||
} else {
|
||||
navBarHeight.value = 48;
|
||||
}
|
||||
|
||||
if (
|
||||
props.alignWithMenuButton &&
|
||||
typeof uni.getMenuButtonBoundingClientRect === "function"
|
||||
) {
|
||||
const menuButton = uni.getMenuButtonBoundingClientRect();
|
||||
|
||||
if (menuButton?.height && typeof menuButton.top === "number") {
|
||||
statusBarHeight.value = Math.max(menuButton.top, systemStatusBarHeight);
|
||||
navBarHeight.value = menuButton.height;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 计算导航栏样式类
|
||||
@@ -122,15 +142,27 @@ const navBarStyle = computed(() => {
|
||||
};
|
||||
});
|
||||
|
||||
const navContentStyle = computed(() => {
|
||||
return {
|
||||
height: navBarHeight.value + "px",
|
||||
};
|
||||
});
|
||||
|
||||
const hasBackListener = computed(() => {
|
||||
const vnodeProps = instance?.vnode?.props || {};
|
||||
return Boolean(vnodeProps.onBack);
|
||||
});
|
||||
|
||||
// 处理返回事件
|
||||
const handleBack = () => {
|
||||
emit("back");
|
||||
// 如果没有监听back事件,默认执行返回上一页
|
||||
if (!emit("back")) {
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
});
|
||||
if (hasBackListener.value) {
|
||||
emit("back");
|
||||
return;
|
||||
}
|
||||
// 如果没有监听back事件,默认执行返回上一页
|
||||
uni.navigateBack({
|
||||
delta: 1,
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user