yuanhua_001

This commit is contained in:
doudou201703
2026-08-08 20:07:39 +08:00
commit 0e998fe330
47 changed files with 11537 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
*.local
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
+3
View File
@@ -0,0 +1,3 @@
strict-peer-dependencies=false
auto-install-peers=true
shamefully-hoist=true
+15
View File
@@ -0,0 +1,15 @@
{
"recommendations": [
"vue.volar",
"mrmaoddxxaa.create-uniapp-view",
"uni-helper.uni-helper-vscode",
"uni-helper.uni-app-schemas-vscode",
"uni-helper.uni-highlight-vscode",
"uni-helper.uni-ui-snippets-vscode",
"uni-helper.uni-app-snippets-vscode",
"uni-helper.uni-cloud-snippets-vscode",
"yoavbls.pretty-ts-errors",
"johnsoncodehk.vscode-tsconfig-helper",
"wot-ui.wot-ui-intellisense"
]
}
+6
View File
@@ -0,0 +1,6 @@
{
"files.associations": {
"pages.json": "jsonc",
"manifest.json": "jsonc"
}
}
+18
View File
@@ -0,0 +1,18 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// Generated by vite-plugin-uni-components
// Read more: https://github.com/vuejs/core/pull/3399
export {}
declare module 'vue' {
export interface GlobalComponents {
ChildComScroll: typeof import('./src/components/ChildComScroll.vue')['default']
WdConfigProvider: typeof import('wot-design-uni/components/wd-config-provider/wd-config-provider.vue')['default']
WdIcon: typeof import('wot-design-uni/components/wd-icon/wd-icon.vue')['default']
WdImg: typeof import('wot-design-uni/components/wd-img/wd-img.vue')['default']
WdLoading: typeof import('wot-design-uni/components/wd-loading/wd-loading.vue')['default']
WdMessageBox: typeof import('wot-design-uni/components/wd-message-box/wd-message-box.vue')['default']
WdToast: typeof import('wot-design-uni/components/wd-toast/wd-toast.vue')['default']
}
}
+21
View File
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<link rel="icon" href="static/logo.svg">
<script>
const coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)')
|| CSS.supports('top: constant(a)'))
document.write(
`<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0${
coverSupport ? ', viewport-fit=cover' : ''}" />`)
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
+61
View File
@@ -0,0 +1,61 @@
{
"name": "appyanhua",
"type": "module",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "unh dev",
"build": "unh build",
"about": "unh info",
"type-check": "vue-tsc --noEmit"
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-5000720260410001",
"@dcloudio/uni-app-harmony": "3.0.0-5000720260410001",
"@dcloudio/uni-app-plus": "3.0.0-5000720260410001",
"@dcloudio/uni-components": "3.0.0-5000720260410001",
"@dcloudio/uni-h5": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-alipay": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-baidu": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-harmony": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-jd": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-kuaishou": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-lark": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-qq": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-toutiao": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-weixin": "3.0.0-5000720260410001",
"@dcloudio/uni-mp-xhs": "3.0.0-5000720260410001",
"@dcloudio/uni-quickapp-webview": "3.0.0-5000720260410001",
"@dcloudio/uni-ui": "^1.5.12",
"@uni-helper/axios-adapter": "^1.16.1",
"@uni-helper/uni-use": "^0.19.17",
"@vueuse/core": "9.13.0",
"axios": "^1.16.1",
"pinia": "^3.0.4",
"pinia-plugin-persistedstate": "^4.7.1",
"vue": "3.4.21",
"vue-i18n": "9.6.2",
"vue-router": "4.5.1",
"wot-design-uni": "^1.14.0"
},
"devDependencies": {
"@dcloudio/types": "3.4.28",
"@dcloudio/uni-automator": "3.0.0-5000720260410001",
"@dcloudio/uni-cli-shared": "3.0.0-5000720260410001",
"@dcloudio/uni-stacktracey": "3.0.0-5000720260410001",
"@dcloudio/vite-plugin-uni": "3.0.0-5000720260410001",
"@mini-types/alipay": "^3.0.14",
"@types/node": "^25.6.0",
"@uni-helper/plugin-uni": "0.1.0",
"@uni-helper/unh": "^0.3.1",
"@uni-helper/uni-types": "^1.0.0-alpha.8",
"@uni-helper/vite-plugin-uni-components": "^0.2.10",
"@vue/runtime-core": "3.4.21",
"@vue/tsconfig": "^0.9.1",
"miniprogram-api-typings": "^5.1.2",
"sass": "1.64.2",
"typescript": "5.9.3",
"vite": "5.2.8",
"vue-tsc": "^3.2.7"
}
}
+21
View File
@@ -0,0 +1,21 @@
<script lang="ts" setup>
import {onHide, onLaunch} from "@dcloudio/uni-app";
// 监听 socket 消息的回调
onLaunch(() => {
});
onHide(() => {
});
</script>
<!--<style>-->
<!--@import "@/assets/fontCss.css";-->
<!--</style>-->
<style lang="scss">
@import "uni.scss";
</style>
+66
View File
@@ -0,0 +1,66 @@
$xiao-text-font-size: 26rpx;
$xiao-text-font-color: #999999;
$xiao-text-font-green: #00c250;
$xiao-text-font-line-height: 44rpx;
@mixin phone-screen($pxScreenHeight,$pxWindowHeight,$defaultTopHeight,$statusHeight,$meunHeight,$xiaoHeight) {
height: $pxScreenHeight;
box-sizing: border-box;
::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
color: transparent;
}
.root-container {
box-sizing: border-box;
position: relative;
height: $pxWindowHeight;
.status-wifi-nav {
/*状态栏的高度 这里的值不能动*/
height: $statusHeight;
box-sizing: border-box;
width: 750rpx;
.default-view-slot {
//height: calc(v-bind(meunHeight));
height: $meunHeight;
text-align: center;
font-size: $xiao-text-font-size;
line-height: $meunHeight;
}
}
.scrollTopHeigh {
/*在滚动区域内的, 可以自定义的高度*/
height: $defaultTopHeight;
}
.scrollViewHeigh {
height: $xiaoHeight;
box-sizing: border-box;
}
.scrollBottomHeigh {
width: 750rpx;
height: 1px;
border-bottom: #F55726 1px dashed;
}
}
}
@mixin mixin-box-default($min-height: 100rpx,) {
width: 686rpx;
margin: 0 auto;
background-color: rgba(255, 255, 255, 0.1);
min-height: $min-height;
//max-height: $max-height;
border-radius: 20rpx;
}
%xiao {
border: 1px red solid;
background-color: purple;
}
+70
View File
@@ -0,0 +1,70 @@
@font-face {
font-family: "xiao"; /* Project id 4434647 */
src: url('//at.alicdn.com/t/c/font_4434647_c2d037e27ru.woff2?t=1765904045208') format('woff2'),
url('//at.alicdn.com/t/c/font_4434647_c2d037e27ru.woff?t=1765904045208') format('woff'),
url('//at.alicdn.com/t/c/font_4434647_c2d037e27ru.ttf?t=1765904045208') format('truetype');
}
.xiao {
font-family: "xiao", sans-serif !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.xiao-tuijianyouli:before {
content: "\e7e2";
}
.xiao-kefuzhongxin:before {
content: "\e64d";
}
.xiao-lingquanzhongxin:before {
content: "\e8e7";
}
.xiao-shezhi:before {
content: "\e631";
}
.xiao-yijianfankui:before {
content: "\e7d7";
}
.xiao-money:before {
content: "\e66f";
}
.xiao-zuijinliulan:before {
content: "\e795";
}
.xiao-dizhiguanli:before {
content: "\e650";
}
.xiao-daipingjia:before {
content: "\e630";
}
.xiao-31daifahuo:before {
content: "\e600";
}
.xiao-fahuo:before {
content: "\e6d5";
}
.xiao-daifukuan:before {
content: "\e615";
}
.xiao-huangjinhuiyuan:before {
content: "\e65e";
}
.xiao-houtui:before {
content: "\e61d";
}
+338
View File
@@ -0,0 +1,338 @@
<style lang="scss" scoped>
.iconClass {
text-align: center;
//height: v-bind(menuButtonHeight);
display: flex;
justify-content: center;
align-items: center;
}
.phoneCom {
position: fixed;
width: 750rpx;
top: 0;
left: 0;
background-color: transparent;
z-index: v-bind(zIndex);
.phone-wifi {
height: v-bind(wifi_px);
//background-color: #F55726;
}
.phone-nav {
// background-color: #007aff;
height: v-bind(nav_px_height);
box-sizing: border-box;
display: flex;
align-items: center;
.meun-height {
height: v-bind(meun_px_height);
width: 750rpx;
display: flex;
.uniui-left {
width: v-bind(rpxLeftWidth);
display: flex;
height: v-bind(meun_px_height);;
}
.meun-widht-left {
width: v-bind(divMeunWidht);
height: v-bind(meun_px_height);
display: flex;
justify-content: center;
align-items: center;
:deep(.customClass-icon) {
height: v-bind(meun_px_height);
text-align: center;
line-height: v-bind(meun_px_height);
}
.meun-widht-rightimage_item {
height: v-bind(imgWidthHeight);
width: v-bind(imgWidthHeight);
}
}
.meun-widht-middle {
width: v-bind(divMeunWidhtMiddle);
background-color: rgba(255, 255, 255, 0.1);
height: v-bind(flexMeunHeight);
align-self: center;
}
.meun-widht-right {
width: v-bind(divMeunWidht);
height: v-bind(meun_px_height);;
display: flex;
justify-content: center;
align-items: center;
:deep(.customClass-icon) {
height: v-bind(meun_px_height);
text-align: center;
line-height: v-bind(meun_px_height);
}
.meun-widht-rightimage_item {
height: v-bind(imgWidthHeight);
width: v-bind(imgWidthHeight);
}
}
.FlexTitleWidth {
width: v-bind(rpxFlexTitleWidth);
text-align: center;
display: flex;
align-items: center;
height: v-bind(meun_px_height);
.flex-title-text {
font-weight: 600;
width: v-bind(rpxFlexTitleWidth);
height: v-bind(meun_px_height);
line-height: v-bind(meun_px_height);
}
.flex-title-slot {
width: v-bind(rpxFlexTitleWidth);
height: v-bind(meun_px_height);
}
}
}
}
}
</style>
<template>
<view class="phoneCom">
<view class="phone-wifi">
<view class="status-wifi"></view>
</view>
<view v-if="navShow" class="phone-nav">
<view class="meun-height">
<view class="uniui-left"></view>
<view class="meun-widht-left" @click="emit('homeLeft')">
<wd-icon v-if="modelValue?.isShowLeft.showCom==='icon'"
:classPrefix="modelValue?.isShowLeft.iconTextLeft.classPrefix"
:name="modelValue?.isShowLeft.iconTextLeft.name"
:size="modelValue?.isShowLeft.iconTextLeft.size"
custom-class="customClass-icon"
></wd-icon>
<image v-if="modelValue?.isShowLeft.showCom==='img'" :src="modelValue.isShowLeft.img.imgLeft"
class="meun-widht-rightimage_item"
mode="scaleToFill" webp></image>
</view>
<view class="meun-widht-middle"></view>
<view class="meun-widht-right" @click="emit('homeRight')">
<!-- <wd-icon custom-class="customClass-icon" name="thin-arrow-left" size="18px"></wd-icon>-->
<wd-icon v-if="modelValue?.isShowRight.showCom==='icon'"
:classPrefix="modelValue?.isShowRight.iconTextRight.classPrefix"
:name="modelValue?.isShowRight.iconTextRight.name"
:size="modelValue?.isShowRight.iconTextRight.size"
custom-class="customClass-icon"
></wd-icon>
<image v-if="modelValue?.isShowRight.showCom==='img'" :src="modelValue.isShowRight.img.imgRight"
class="meun-widht-rightimage_item"
mode="scaleToFill" webp></image>
</view>
<view class="FlexTitleWidth">
<view v-if="titleViewShow" class="flex-title-text">{{ modelValue?.title_text }}</view>
<view v-if="slotViewShow" class="flex-title-slot">
<slot name="default"></slot>
</view>
</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import {computed, ref, watchEffect} from "vue";
import type {GlobelsChildPropsType} from "@/stores/requestFile";
import {onShow} from "@dcloudio/uni-app";
defineOptions({
options: {
styleIsolation: "shared",
virtualHost: true,
},
});
const emit = defineEmits<{
(eventName: "update:pxWindowHeight", value: string): void
(eventName: "update:pxScrollHeight", value: string): void
(eventName: "update:pxScreenHeight", value: string): void
(eventName: "update:pxWifiNavHeight", value: string): void
(eventName: "update:statusHeight", value: string): void
(eventName: "update:meunHeight", value: string): void
(eventName: "homeRight"): void
(eventName: "homeLeft"): void
}>();
//
interface definePropsType {
modelValue: GlobelsChildPropsType, //跟v-model=值没有关系
zIndex?: number
}
const props = withDefaults(defineProps<definePropsType>(), {
zIndex: () => (100),
});
const info_window = uni.getWindowInfo();
let pxToRpxScale = 750 / info_window.windowWidth;
let meun = uni.getMenuButtonBoundingClientRect();
let meun_px_height = computed(() => {
return meun.height - 2 + "px";
});
// 计算当前 wifi的高度
let wifiHeing = computed(() => {
// 当前wifi的高度 也是分为两种情况下 为负数的时候 小于0 的时候我们就需要减少 wifi的高度,这样才能正确留空
if (meun.top - info_window.statusBarHeight < 0) {
let num = meun.top - info_window.statusBarHeight;
return info_window.statusBarHeight - Math.abs(num) * 2;
}
return info_window.statusBarHeight;
});
// 默认的一些宽度
let rpxLeftWidth = computed(() => {
return (info_window.windowWidth - meun.right) * pxToRpxScale + "rpx";
});
let pxMeunHeight = computed(() => {
return meun.height + "px";
});
let rpxFlexTitleWidth = computed(() => {
return (meun.left - meun.width - (info_window.windowWidth - meun.right)) * pxToRpxScale + "rpx";
});
let divMeunWidht = computed(() => {
// 胶囊的一半宽度
const halfWidth = Math.ceil(meun.width / 2) - 1;
return halfWidth * pxToRpxScale + "rpx";
});
let flexMeunHeight = computed(() => {
return Math.ceil(meun.height) * 0.6 + "px";
});
let divMeunWidhtMiddle = computed(() => {
return 2 * pxToRpxScale + "rpx";
});
let imgWidthHeight = computed(() => {
return Math.ceil(meun.height * 0.7 * pxToRpxScale) + "rpx";
});
let wifi_px = computed(() => {
return wifiHeing.value + "px";
});
// 计算当前导航栏的高度
let navHeight = computed(() => {
// 导航栏高度 = 胶囊高度 + (胶囊顶部距离 - wifi高度)*2
// 这里逻辑也得分二种情况第一情况,减下来值小0 和大于0
if (meun.top - info_window.statusBarHeight > 0) {
return meun.height + (meun.top - info_window.statusBarHeight) * 2;
}
if (meun.top - info_window.statusBarHeight <= 0) {
return meun.height + Math.abs(meun.top - info_window.statusBarHeight) * 2;
}
return meun.height + (meun.top - info_window.statusBarHeight) * 2;
});
let nav_px_height = computed(() => {
return navHeight.value + "px";
});
// 计算可视区域的高度
let windowHeight = computed(() => {
// 可视区高度 = 屏幕高度 - 可视区域的高度 还需要判断 二 种情况, 一种是有tab, 一种是没有tab的情况
// 没有tab栏的情况
if (info_window.screenHeight - info_window.windowHeight === 0) {
if (info_window.safeAreaInsets.bottom > 0) {
// 这是苹果手机的状态(直接返回高度就可以了)
return info_window.screenHeight - info_window.safeAreaInsets.bottom;
}
if (info_window.safeAreaInsets.bottom === 0) {
// 这是没有底部安全栏高度时的(华为手机,苹果5678o)
return info_window.screenHeight - 34;
}
}
if (info_window.screenHeight - info_window.windowHeight > 0) {
return info_window.windowHeight;
}
return info_window.windowHeight;
});
// 实时给出高度
let wifiShow = ref(true);
let navShow = ref(true);
let titleViewShow = ref(true);
let slotViewShow = ref(false);
onShow(() => {
emit("update:meunHeight", pxMeunHeight.value);
});
watchEffect(() => {
emit("update:pxScreenHeight", info_window.screenHeight + "px");
if (props.modelValue?.navIsShow === "default") {
// 此时的导航栏高度 = wifi+nav的高度
let staus = computed(() => {
return (wifiHeing.value + navHeight.value) + "px";
});
let pxScrollHeight = computed(() => {
return windowHeight.value + "px";
});
emit("update:statusHeight", staus.value);
emit("update:pxWindowHeight", staus.value);
emit("update:pxScrollHeight", pxScrollHeight.value);
emit("update:pxWindowHeight", pxScrollHeight.value);
}
if (props.modelValue?.navIsShow === "wifi") {
// 此时的导航栏高度 = wifi+nav的高度
navShow.value = false;
let staus = computed(() => {
return (wifiHeing.value) + "px";
});
let pxScrollHeight = computed(() => {
// 当值为wifi时,则表明,只想显示一个wifi的状态, 不想显示na的状态
return windowHeight.value + "px";
});
emit("update:statusHeight", staus.value);
emit("update:pxWindowHeight", staus.value);
emit("update:pxScrollHeight", pxScrollHeight.value);
emit("update:pxWindowHeight", pxScrollHeight.value);
}
if (props.modelValue?.navIsShow === "none") {
navShow.value = true;
wifiShow.value = false;
// 此时的导航栏高度 = wifi+nav的高度
let staus = computed(() => {
return "0px";
});
let pxScrollHeight = computed(() => {
// 当值为wifi时,则表明,只想显示一个wifi的状态, 不想显示na的状态
return windowHeight.value + "px";
});
emit("update:statusHeight", staus.value);
emit("update:pxWindowHeight", staus.value);
emit("update:pxScrollHeight", pxScrollHeight.value);
emit("update:pxWindowHeight", pxScrollHeight.value);
}
if (props.modelValue?.navIsShow === "slot") {
slotViewShow.value = true;
titleViewShow.value = false;
// 此时的导航栏高度 = wifi+nav的高度
let staus = computed(() => {
return (wifiHeing.value + navHeight.value) + "px";
});
let pxScrollHeight = computed(() => {
// 当值为wifi时,则表明,只想显示一个wifi的状态, 不想显示na的状态
return windowHeight.value + "px";
});
emit("update:statusHeight", staus.value);
emit("update:pxWindowHeight", staus.value);
emit("update:pxScrollHeight", pxScrollHeight.value);
emit("update:pxWindowHeight", pxScrollHeight.value);
}
});
</script>
+12
View File
@@ -0,0 +1,12 @@
import { createSSRApp } from "vue";
import App from "./App.vue";
import { pinia } from "@/stores/piniaPro";
export function createApp() {
const app = createSSRApp( App );
app.use( pinia );
return {
app,
};
}
+103
View File
@@ -0,0 +1,103 @@
{
"name": "",
"appid": "",
"description": "",
"versionName": "1.0.0",
"versionCode": "100",
"transformPx": false,
"app-plus": {
"usingComponents": true,
"nvueStyleCompiler": "uni-app",
"compilerVersion": 3,
"splashscreen": {
"alwaysShowBeforeRender": true,
"waiting": true,
"autoclose": true,
"delay": 0
},
"modules": {},
"distribute": {
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
"ios": {},
"sdkConfigs": {}
}
},
"app-harmony": {
"distribute": {}
},
"mp-harmony": {
"distribute": {}
},
"quickapp": {},
"mp-weixin": {
"appid": "wx6568a3691dc93023",
"setting": {
"urlCheck": false,
"condition": false,
"minifyWXML": true,
"minifyWXSS": true,
"minified": true,
"enhance": false,
"postcss": true,
"uglifyFileName": true,
"bigPackageSizeSupport": true,
"skylineRenderEnable": true,
"compileHotReLoad": true
},
"usingComponents": true,
"lazyCodeLoading": "requiredComponents",
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
},
"requiredPrivateInfos": [
"chooseAddress",
"getLocation"
],
"optimization": {
"subPackages": true
},
"darkmode": true,
"themeLocation": "theme.json",
"requiredBackgroundModes": [
"audio",
"location"
]
},
"mp-alipay": {
"usingComponents": true
},
"mp-baidu": {
"usingComponents": true
},
"mp-toutiao": {
"usingComponents": true
},
"uniStatistics": {
"enable": false
},
"vueVersion": "3",
"h5": {
"darkmode": true,
"themeLocation": "theme.json"
}
}
@@ -0,0 +1,604 @@
<style lang="scss" scoped>
// @import "@/assets/demo.scss";
$defaultTopHeight: 1px; // 滚动区域外 可以预留的高度
$xiaoBottomHeigh: 1px; // 滚动区域外,可以预留的高度
$leftWidth: 180rpx; /* 浅色模式 */
$rightWidth: 570rpx; /* 浅色模式 */
$heightImage: 285rpx;
@mixin line-color {
@keyframes gradientFlow {
0%, 100% {
background-position: 0 50%;
}
50% {
background-position: 100% 50%;
}
}
background: linear-gradient(to right, #FF6B6B 0%, #4ECDC4 20%, #FFD166 40%, #06D6A0 60%, #118AB2 80%, #EF476F 100%);
background-size: 400% 100%;
animation: gradientFlow 5s ease infinite;
}
.phone-screen {
box-sizing: border-box;
font-family: "xiaoFont", sans-serif;
height: v-bind(pxScreenHeight);
font-size: 26rpx;
// background-image: url("https://hudie.xiao.band/wechatbackimg.png");
// background-size: 750rpx;
&::-webkit-scrollbar {
width: 0;
height: 0;
display: none;
background: transparent;
color: transparent;
}
.root-container {
position: relative;
box-sizing: border-box;
height: v-bind(pxWindowHeight);
.status-wifi-nav {
/*状态栏的高度 这里的值不能动*/
box-sizing: border-box;
height: v-bind(statusHeight);
:deep(.default-view-slot) {
font-size: 26rpx;
line-height: v-bind(meunHeight);
display: flex;
align-items: center;
height: v-bind(meunHeight);
text-align: center;
.default-view-slot-left {
flex: 1;
}
.default-view-slot-right {
display: flex;
align-items: center;
padding: 0 20rpx;
border: 1px rgba(255, 255, 255, 0.03) solid;
border-radius: calc(v-bind(meunHeight) / 2);
.title-imgimage_item {
width: calc(v-bind(meunHeight) * 0.7);
height: calc(v-bind(meunHeight) * 0.7);
}
}
.default-view-slot-right-text {
font-weight: 800;
}
}
}
}
.scrollTopHeigh {
/*在滚动区域内的, 可以自定义的高度*/
box-sizing: border-box;
height: $defaultTopHeight;
background-color: rgba(255, 255, 255, 0.05);
}
.scrollViewHeigh {
box-sizing: border-box;
height: calc(v-bind(pxScrollHeight) - v-bind(statusHeight) - #{$defaultTopHeight} - #{$xiaoBottomHeigh});
overflow: hidden;
.xiao-page {
display: flex;
height: 100%;
.left-page {
width: $leftWidth;
height: 100%;
.left-page-top {
height: 0;
}
.left-pagescrollViewHeigh {
height: 100%;
.page-xiao-page-left {
display: grid;
width: $leftWidth;
height: 100%;
grid-auto-rows: 100rpx;
grid-template-columns: 1fr;
grid-gap: 10rpx;
box-sizing: border-box;
.page-xiao-page-left-items {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
&.tag--active {
color: #EF476F;
background-color: white;
font-size: 32rpx;
font-weight: 600;
}
}
}
}
}
.right-page {
width: $rightWidth;
display: flex;
flex-direction: column;
.right-page-top {
height: 20%;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
justify-items: center;
justify-content: center;
align-items: center;
.right-page-top-items {
padding: 8rpx 8rpx;
// margin: 12rpx;
font-size: 24rpx;
color: #d35400; /* 橙红色文字 */
background: #fff7ed; /* 极淡的橙色背景 */
border: 1rpx solid #fbbd08; /* 金黄色边框 */
border-radius: 12rpx; /* 小圆角 */
box-shadow: 0 2rpx 4rpx rgba(251, 189, 8, 0.2); /* 微微的金色阴影 */
// 选中时的状态样式
&.tag-firework-active {
color: #fff;
background: linear-gradient(to right, #e67e22, #f1c40f); /* 橙黄渐变 */
border-color: #d35400;
box-shadow: 0 4rpx 8rpx rgba(230, 126, 34, 0.4);
}
}
}
.right-pagescrollViewHeigh {
height: 80%;
.page-xiao-page-rightpage {
display: grid;
grid-auto-rows: 1fr;
grid-auto-columns: 1fr;
grid-gap: 7rpx;
.goods-items {
display: flex;
height: $heightImage;
.goods-items-left {
width: 50%;
overflow: hidden;
position: relative;
height: $heightImage;
.brand-tag {
position: absolute;
top: 12rpx;
left: 12rpx;
padding: 6rpx 16rpx;
background-color: rgba(229, 57, 53, 0.9);
color: #fff;
font-size: 20rpx;
border-radius: 20rpx;
font-weight: 500;
z-index: 100;
}
:deep(.customClassRoot) {
box-sizing: border-box;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
.customImage {
width: 100%;
height: 100%;
}
.error-wrap {
width: 100%;
height: 100%;
background-color: red;
color: white;
line-height: 100px;
text-align: center;
}
.loading-wrap {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
}
.goods-items-right {
width: 50%;
background-color: #007aff;
}
.goods-content {
flex: 1;
width: 50%;
padding: 24rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
overflow: hidden;
.goods-header {
margin-bottom: 16rpx;
}
.goods-name {
display: block;
font-size: 32rpx;
font-weight: 500;
line-height: 1.4;
margin-bottom: 8rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.goods-id {
font-size: 24rpx;
}
.goods-meta {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
}
.category-tag {
padding: 6rpx 16rpx;
// background-color: #f0f0f0;
font-size: 22rpx;
border-radius: 8rpx;
}
.create-time {
font-size: 22rpx;
}
.goods-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.price {
font-size: 36rpx;
color: #e53935;
font-weight: bold;
}
.action-buttons {
display: flex;
gap: 16rpx;
}
.btn-detail {
padding: 12rpx 24rpx;
background-color: #e53935;
font-size: 24rpx;
border-radius: 8rpx;
font-weight: 500;
}
}
}
}
}
}
}
}
.scrollBottomHeigh {
box-sizing: border-box;
height: $xiaoBottomHeigh;
}
}
</style>
<template>
<view class="phone-screen">
<wd-config-provider theme="dark">
<view class="root-container">
<view class="status-wifi-nav">
<ChildComScroll v-model:meunHeight="meunHeight" v-model:pxScreenHeight="pxScreenHeight"
v-model:pxScrollHeight="pxScrollHeight" v-model:pxWindowHeight="pxWindowHeight"
v-model:statusHeight="statusHeight" :modelValue="modelValue" @homeLeft="homeLeft"
@homeRight="homeRight">
<template v-slot:default>
<view class="default-view-slot" @click="defaultSearchChange">
<view class="default-view-slot-left"></view>
<view class="default-view-slot-right">
<image :lazy-load="true" class="title-imgimage_item" mode="scaleToFill"
src="https://oss.jpyanhua.site/%E7%83%9F%E8%8A%B1%E9%A1%B9%E7%9B%AE/search.png" webp/>
<view class="default-view-slot-right-text">搜索</view>
</view>
<view class="line-widht-number" style="width: 30rpx"></view>
</view>
</template>
</ChildComScroll>
</view>
<!--分隔线,上面的是子组件-->
<view class="scrollTopHeigh"><!--预留的空间高度--></view>
<!-- 滚动区域开始-->
<view class="scrollViewHeigh">
<view class="xiao-page">
<view class="left-page">
<view class="left-page-top">
</view>
<scroll-view :enableBackToTop="true" :enhanced="true" :scroll-y="true" :showScrollbar="false"
class="left-pagescrollViewHeigh">
<view class="page-xiao-page-left">
<view class="page-xiao-page-left-items" v-bind:class="{'tag--active':colorCurrent===index}"
v-for="(value,index) in 品牌列表" v-bind:key="index"
v-on:click="选中品牌事件(index)">
{{ value.goods_商品品牌 }}
</view>
</view>
</scroll-view>
</view>
<view class="right-page">
<view class="right-page-top">
<view class="right-page-top-items" v-for="(value,index) in type_goods_data"
v-bind:key="index" v-on:click="选中类型事件(value,index)" v-bind:class="{'tag-firework-active':index===defautl默认选中的类别}">
{{ value.goods_商品类别 }}
</view>
</view>
<scroll-view :enableBackToTop="true" :enhanced="true" :scroll-y="true" :showScrollbar="false"
class="right-pagescrollViewHeigh">
<view class="page-xiao-page-rightpage">
<view class="goods-items" v-for="(value,index) in view_goods_list" v-bind:key="index">
<view class="goods-items-left">
<view class="brand-tag">{{ value.goods_商品品牌 }}</view>
<wd-img v-bind:src="value.goods_商品图片.at(0)" mode="widthFix" :lazy-load="true"
custom-class="customClassRoot" custom-image="customImage">
<template #error>
<view class="error-wrap">加载失败</view>
</template>
<template #loading>
<view class="loading-wrap">
<wd-loading color="#fff" type="spinner" :size="20"/>
</view>
</template>
</wd-img>
</view>
<view class="goods-content">
<view class="goods-header">
<view class="goods-name">{{ value.goods_商品名称 }}</view>
<view class="goods-id">ID:</view>
</view>
<view class="goods-meta">
<text class="category-tag">{{ value.goods_商品类别 }}</text>
<text class="create-time"></text>
</view>
<view class="goods-footer">
<text class="price">¥ --</text>
<view class="action-buttons">
<view class="btn-detail" v-on:click="进入商品详情页面(value)">查看详情</view>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</view>
</view>
<!--滚动区域结束-->
<view class="scrollBottomHeigh"><!--底部预留区域--></view>
</view>
</wd-config-provider>
</view>
</template>
<script lang="ts" setup>
import ChildComScroll from "@/components/ChildComScroll.vue";
import type {GlobelsChildPropsType} from "@/stores/requestFile";
import {computed, ref} from "vue";
import {tryOnLoad, usePage, useStorage} from "@uni-helper/uni-use";
import {instance, 查询所有的商品信息} from "@/stores/请求基础文件";
import {useMainXiaoStore} from "@/stores/piniaPro/miniChatStore";
import type {typeGoodsItem, 商品列表类型} from "@/stores/types/烟花商品类型";
import {onAddToFavorites, onLoad, onShareAppMessage, onShareTimeline, onTabItemTap} from "@dcloudio/uni-app";
let xiaoMain = useMainXiaoStore();
defineOptions({options: {styleIsolation: "shared"}});
let pxScreenHeight = ref(); // 手机高度
let pxWindowHeight = ref(); // 屏幕可视区高度
let pxScrollHeight = ref(); // 滚动区域高度
let statusHeight = ref(); // 固定的顶部
let meunHeight = ref();//插槽时要用的 高度
let colorCurrent = ref(0);
let defautl默认选中的类别 = ref(-1);
let view_goods_list = ref<商品列表类型>(); // 当前需要展示的 商品列表
let type_goods_data = ref<商品列表类型>();
let 品牌列表 = ref(
[
{
"goods_商品品牌": "全部",
},
{
"goods_商品品牌": "中洲",
},
{
"goods_商品品牌": "君子",
},
{
"goods_商品品牌": "山枣",
},
{
"goods_商品品牌": "庆泰",
},
{
"goods_商品品牌": "恒达",
},
{
"goods_商品品牌": "戴氏",
},
{
"goods_商品品牌": "星视界",
},
{
"goods_商品品牌": "牛石",
},
{
"goods_商品品牌": "花火汇",
},
{
"goods_商品品牌": "花炮连锁",
},
{
"goods_商品品牌": "魔法视界",
},
{
"goods_商品品牌": "其它品牌",
},
],
);
const modelValue: GlobelsChildPropsType = {
isShowLeft: {
showCom: "icon",
img: {imgLeft: "https://oss.xiao.band/icon/left.png"},
iconTextLeft: {classPrefix: "wd-icon", name: "view-list", size: 20},
},
isShowRight: {
showCom: "icon",
img: {imgRight: "https://oss.xiao.band/icon/%E9%99%8D%E8%90%BD%E4%BC%9E_parachute.png"},
iconTextRight: {classPrefix: "wd-icon", name: "", size: 20},
},
title_text: "盛世花开", navIsShow: "default",
};
const homeLeft = () => {
console.log("左键按键");
};
const homeRight = () => {
console.log("右键按键");
};
let defaultSearchChange = async () => {
// 点击自定义插槽的 搜索事件
console.log("搜索发起");
uni.navigateTo({url: "/subPackages/homeSubPages/搜索页面/搜索页面"}).then().catch(() => uni.navigateTo({url: ""}));
};
const goods_list_data = useStorage("authorization", []);
tryOnLoad(async () => {
try {
let data = await instance.post(查询所有的商品信息, {});
xiaoMain.goods_list_data = data.data;
goods_list_data.value = data.data;
view_goods_list.value = data.data;
type_goods_data.value = view_goods_list.value?.filter((item, index, self) =>
index === self.findIndex(t => t.goods_商品类别 === item.goods_商品类别),
);
} catch (e) {
console.log("捕获错误❌🙅🙅‍❌🙅🙅‍❌🙅🙅‍❌🙅🙅‍❌🙅🙅‍❌🙅🙅‍❌🙅🙅‍♀️", e);
view_goods_list.value = goods_list_data.value;
type_goods_data.value = view_goods_list.value?.filter((item, index, self) =>
index === self.findIndex(t => t.goods_商品类别 === item.goods_商品类别),
);
}
});
let goods_当前品牌 = ref("全部");
async function 选中品牌事件(index: number): Promise<void> {
console.log("选中品牌事件", index);
wx.vibrateShort({type: "light"});
colorCurrent.value = index;
let brid = 品牌列表.value.at(index);
goods_当前品牌.value = <string>brid?.goods_商品品牌;
console.log(brid, brid?.goods_商品品牌);
if (brid?.goods_商品品牌 === "全部") {
view_goods_list.value = xiaoMain.goods_list_data;
type_goods_data.value = view_goods_list.value?.filter((item, index, self) =>
index === self.findIndex(t => t.goods_商品类别 === item.goods_商品类别),
);
} else {
view_goods_list.value = xiaoMain.goods_list_data?.filter((value) => {
return value.goods_商品品牌 === brid?.goods_商品品牌;
});
type_goods_data.value = view_goods_list.value?.filter((item, index, self) =>
index === self.findIndex(t => t.goods_商品类别 === item.goods_商品类别),
);
console.log(type_goods_data.value, "==============");
}
}
async function 进入商品详情页面(good_item: typeGoodsItem): Promise<void> {
wx.vibrateShort({type: "light"});
uni.navigateTo({url: "/subPackages/homeSubPages/商品详情页面/商品详情页面"}).then(() => {
xiaoMain.goodsCurrentData = good_item;
}).catch(() => uni.navigateTo({url: ""}));
}
async function 选中类型事件(item: typeGoodsItem, indexNumber: number): Promise<void> {
console.log("选中事件", item, "当前的品牌", item.goods_商品品牌, goods_当前品牌.value);
defautl默认选中的类别.value = indexNumber;
wx.vibrateShort({type: "light"});
if (goods_当前品牌.value === "全部") {
console.log("判断生效了吗");
view_goods_list.value = xiaoMain.goods_list_data?.filter((value, index, array) => {
return value.goods_商品类别 === item.goods_商品类别;
});
} else {
let zizi = xiaoMain.goods_list_data?.filter((value) => {
return value.goods_商品品牌 === item.goods_商品品牌;
});
view_goods_list.value = zizi?.filter((good) => {
return good.goods_商品类别 === item.goods_商品类别;
});
}
}
onTabItemTap(() => {
wx.vibrateShort({type: "light"});
});
</script>
@@ -0,0 +1,199 @@
<style lang="scss" scoped>
// @import "@/assets/demo.scss";
$defaultTopHeight: 1px; // 滚动区域外 可以预留的高度
$xiaoBottomHeigh: 1px; // 滚动区域外,可以预留的高度
@mixin line-color {
@keyframes gradientFlow {
0%, 100% {
background-position: 0 50%;
}
50% {
background-position: 100% 50%;
}
}
background: linear-gradient(to right, #FF6B6B 0%, #4ECDC4 20%, #FFD166 40%, #06D6A0 60%, #118AB2 80%, #EF476F 100%);
background-size: 400% 100%;
animation: gradientFlow 5s ease infinite;
}
.phone-screen {
box-sizing: border-box;
font-size: 26rpx;
font-family: "xiaoFont", sans-serif;
height: v-bind(pxScreenHeight);
//&::-webkit-scrollbar { width: 0; height: 0; display: none; background: transparent; color: transparent; }
.root-window {
width: 750rpx;
position: relative;
box-sizing: border-box;
height: v-bind(pxWindowHeight);
.status-wifi-nav {
box-sizing: border-box;
height: v-bind(statusHeight);
:deep(.default-view-slot) {
font-size: 26rpx;
line-height: v-bind(meunHeight);
display: flex;
align-items: center;
height: v-bind(meunHeight);
text-align: center;
.default-view-slot-left {
flex: 1;
}
.default-view-slot-right {
display: flex;
align-items: center;
padding: 0 20rpx;
border: 1px rgba(255, 255, 255, 0.03) solid;
border-radius: calc(v-bind(meunHeight) / 2);
.title-imgimage_item {
width: calc(v-bind(meunHeight) * 0.7);
height: calc(v-bind(meunHeight) * 0.7);
}
}
.default-view-slot-right-text {
font-weight: 800;
}
}
}
}
}
.scrollTopHeigh {
/*在滚动区域内的, 可以自定义的高度*/
box-sizing: border-box;
height: $defaultTopHeight;
}
/* 滚动区域的内容区域 */
.scrollViewHeigh {
box-sizing: border-box;
height: calc(v-bind(pxScrollHeight) - v-bind(statusHeight) - #{$defaultTopHeight} - #{$xiaoBottomHeigh});
//overflow: hidden;
.page-xiao-page {
}
}
/* 最底部的区域,脱离滚动区域 */
.scrollBottomHeigh {
width: 750rpx;
box-sizing: border-box;
height: $xiaoBottomHeigh;
}
</style>
<template>
<view class="phone-screen">
<wd-config-provider theme="dark">
<view class="root-window">
<view class="status-wifi-nav">
<ChildComScroll v-model:meunHeight="meunHeight" v-model:pxScreenHeight="pxScreenHeight"
v-model:pxScrollHeight="pxScrollHeight" v-model:pxWindowHeight="pxWindowHeight"
v-model:statusHeight="statusHeight" :modelValue="modelValue" @homeLeft="homeLeft"
@homeRight="homeRight">
<template v-slot:default>
<view class="default-view-slot" @click="defaultSearchChange">
<view class="default-view-slot-left">1</view>
<view class="default-view-slot-right">
<image :lazy-load="true" class="title-imgimage_item" mode="scaleToFill"
v-bind:src="icon_img" webp/>
<view class="default-view-slot-right-text">搜索</view>
</view>
<view class="line-widht-number" style="width: 30rpx"></view>
</view>
</template>
</ChildComScroll>
</view>
<!--分隔线,上面的是子组件-->
<view class="scrollTopHeigh"><!--预留的空间高度--></view>
<!-- 滚动区域开始-->
<scroll-view :enableBackToTop="true" :enhanced="true" :scroll-y="true" :showScrollbar="false"
class="scrollViewHeigh">
<view class="page-xiao-page">
这里是我的页面
</view>
</scroll-view>
<!--滚动区域结束-->
<view class="scrollBottomHeigh"><!--底部预留区域--></view>
</view>
</wd-config-provider>
</view>
</template>
<script lang="ts">export default {options: {virtualHost: true}};</script>
<script lang="ts" setup>
import ChildComScroll from "@/components/ChildComScroll.vue";
import type {GlobelsChildPropsType} from "@/stores/requestFile";
import {ref} from "vue";
import {onLoad} from "@dcloudio/uni-app";
import {useMainXiaoStore} from "@/stores/piniaPro/miniChatStore";
defineOptions({options: {styleIsolation: "shared"}});
let icon_img = "https://oss.jpyanhua.site/%E7%83%9F%E8%8A%B1%E9%A1%B9%E7%9B%AE/search.png";
let pxScreenHeight = ref(); // 手机高度
let pxWindowHeight = ref(); // 屏幕可视区高度
let pxScrollHeight = ref(); // 滚动区域高度
let statusHeight = ref(); // 固定的顶部
let meunHeight = ref();//插槽时要用的 高度
const modelValue: GlobelsChildPropsType = {
isShowLeft: {
showCom: "icon",
img: {imgLeft: "https://oss.xiao.band/icon/left.png"},
iconTextLeft: {classPrefix: "wd-icon", name: "user-circle", size: 22},
},
isShowRight: {
showCom: "icon",
img: {imgRight: "https://oss.xiao.band/icon/%E9%99%8D%E8%90%BD%E4%BC%9E_parachute.png"},
iconTextRight: {classPrefix: "wd-icon", name: "", size: 20},
},
title_text: "我的", navIsShow: "default",
};
onLoad(() => {
// 禁用分享的设置
wx.hideShareMenu();
wx.offCopyUrl();
});
const homeLeft = () => {
console.log("左键按键");
};
const homeRight = () => {
console.log("右键按键");
};
let defaultSearchChange = async () => {
// 点击自定义插槽的 搜索事件
console.log("搜索发起");
};
let xiaoMain = useMainXiaoStore();
async function demoFunc(): Promise<void> {
const xiaozizi = xiaoMain.goods_list_data?.filter((value, index, array) => {
let find_index = array.findIndex((item, index, self) => {
return item.goods_商品类别 === value.goods_商品类别;
});
return index === find_index;
});
console.log(xiaozizi);
}
</script>
@@ -0,0 +1,449 @@
<style lang="scss" scoped>
// @import "@/assets/demo.scss";
$defaultTopHeight: 1px; // 滚动区域外 可以预留的高度
$xiaoBottomHeigh: 1px; // 滚动区域外,可以预留的高度
/* 暗黑模式变量定义 */
$bg-color: #121212; // 整体深黑背景
$card-bg: #1e1e1e; // 卡片深灰背景
$text-primary: #e0e0e0; // 主文字浅灰白
$text-secondary: #ff6b00; // 次要文字灰色
$border-color: #333333; // 边框极深灰
$accent-color: #07c160; // 微信绿点缀
$accent-bg: rgba(7, 193, 96, 0.15); // 微信绿半透明背景
/* 浅色模式 */
//@media (prefers-color-scheme: light) {
// .phone-screen {
// color: white;
// background: #181818;
// }
//}
//
///* 深色模式 */
//@media (prefers-color-scheme: dark) {
// .phone-screen {
// color: white;
// background: #1a1a1a;
// }
//}
//
@mixin line-color {
@keyframes gradientFlow {
0%, 100% {
background-position: 0 50%;
}
50% {
background-position: 100% 50%;
}
}
background: linear-gradient(to right, #FF6B6B 0%, #4ECDC4 20%, #FFD166 40%, #06D6A0 60%, #118AB2 80%, #EF476F 100%);
background-size: 400% 100%;
animation: gradientFlow 5s ease infinite;
}
.phone-screen {
box-sizing: border-box;
font-family: "xiaoFont", sans-serif;
height: v-bind(pxScreenHeight);
&::-webkit-scrollbar {
width: 0;
height: 0;
display: none;
background: transparent;
color: transparent;
}
.root-container {
position: relative;
box-sizing: border-box;
height: v-bind(pxWindowHeight);
.status-wifi-nav {
/*状态栏的高度 这里的值不能动*/
box-sizing: border-box;
height: v-bind(statusHeight);
:deep(.default-view-slot) {
font-size: 26rpx;
line-height: v-bind(meunHeight);
display: flex;
align-items: center;
height: v-bind(meunHeight);
text-align: center;
.default-view-slot-left {
flex: 1;
}
.default-view-slot-right {
display: flex;
align-items: center;
padding: 0 20rpx;
border: 1px rgba(255, 255, 255, 0.03) solid;
border-radius: calc(v-bind(meunHeight) / 2);
.title-imgimage_item {
width: calc(v-bind(meunHeight) * 0.7);
height: calc(v-bind(meunHeight) * 0.7);
}
}
.default-view-slot-right-text {
font-weight: 800;
}
}
}
}
.scrollTopHeigh {
/*在滚动区域内的, 可以自定义的高度*/
box-sizing: border-box;
height: $defaultTopHeight;
background-color: rgba(255, 255, 255, 0.05);
}
.scrollViewHeigh {
box-sizing: border-box;
height: calc(v-bind(pxScrollHeight) - v-bind(statusHeight) - #{$defaultTopHeight} - #{$xiaoBottomHeigh});
overflow: hidden;
.container {
// background-color: $bg-color;
display: flex;
flex-direction: column;
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, sans-serif;
}
.status-bar {
height: var(--status-bar-height, 44px);
width: 100%;
// background-color: $bg-color; // 状态栏与背景同色
}
.main-content {
flex: 1;
padding: 30rpx 40rpx;
display: flex;
flex-direction: column;
gap: 40rpx;
overflow-y: auto;
}
/* 卡片通用样式 */
.card {
// background: $card-bg;
border-radius: 20rpx;
padding: 40rpx;
// box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.3); // 加深阴影适应暗色背景
}
/* 顶部公告 */
.section-notice {
margin-top: 10rpx;
}
.card-header {
display: flex;
align-items: center;
margin-bottom: 20rpx;
border-bottom: 1rpx solid $border-color;
padding-bottom: 20rpx;
}
.icon {
font-size: 40rpx;
margin-right: 15rpx;
}
.title {
font-size: 36rpx;
font-weight: bold;
// color: $text-primary;
}
.notice-text {
font-size: 28rpx;
color: $text-secondary;
line-height: 1.6;
text-align: justify;
}
/* 中部联系方式 */
.section-contact {
display: flex;
flex-direction: column;
gap: 30rpx;
.contact-item {
// background: $card-bg;
border-radius: 20rpx;
padding: 40rpx;
box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.3);
transition: transform 0.1s;
&:active {
transform: scale(0.98);
}
}
/* 二维码专属样式 */
.qr-card {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
.qr-header {
margin-bottom: 30rpx;
.label {
display: block;
font-size: 32rpx;
font-weight: bold;
// color: $text-primary;
margin-bottom: 8rpx;
}
.sub-label {
font-size: 24rpx;
color: $text-secondary;
}
}
.qr-wrapper {
width: 100%;
height: 400rpx;
// background-color: #2a2a2a; // 二维码区域比卡片稍亮一点,形成层次
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 30rpx;
border: 1rpx dashed $border-color;
}
.qr-image {
width: 100%;
height: 100%;
border-radius: 12rpx;
}
.qr-footer {
font-size: 26rpx;
color: $accent-color;
// background: $accent-bg;
padding: 15rpx 30rpx;
border-radius: 30rpx;
}
}
/* 电话项样式 */
.contact-item:not(.qr-card) {
display: flex;
justify-content: space-between;
align-items: center;
.left {
display: flex;
flex-direction: column;
justify-content: center;
}
.label {
font-size: 32rpx;
font-weight: bold;
// color: $text-primary;
margin-bottom: 8rpx;
}
.sub-label {
font-size: 24rpx;
color: $text-secondary;
}
.right {
display: flex;
align-items: center;
gap: 15rpx;
}
.value {
font-size: 30rpx;
// color: $text-primary;
font-family: monospace;
font-weight: 500;
}
.call-icon {
font-size: 24rpx;
// background: #2a2a2a;
padding: 10rpx 20rpx;
border-radius: 10rpx;
color: $accent-color;
}
}
}
}
.scrollBottomHeigh {
box-sizing: border-box;
height: $xiaoBottomHeigh;
}
}
</style>
<template>
<view class="phone-screen">
<wd-config-provider theme="dark">
<view class="root-container">
<view class="status-wifi-nav">
<ChildComScroll v-model:meunHeight="meunHeight" v-model:pxScreenHeight="pxScreenHeight"
v-model:pxScrollHeight="pxScrollHeight" v-model:pxWindowHeight="pxWindowHeight"
v-model:statusHeight="statusHeight" :modelValue="modelValue" @homeLeft="homeLeft"
@homeRight="homeRight">
<template v-slot:default>
<view class="default-view-slot" @click="defaultSearchChange">
<view class="default-view-slot-left">1</view>
<view class="default-view-slot-right">
<image :lazy-load="true" class="title-imgimage_item" mode="scaleToFill"
src="https://oss.xiao.band/icon/search.png" webp/>
<view class="default-view-slot-right-text">搜索</view>
</view>
<view class="line-widht-number" style="width: 30rpx"></view>
</view>
</template>
</ChildComScroll>
</view>
<!--分隔线,上面的是子组件-->
<view class="scrollTopHeigh"><!--预留的空间高度--></view>
<!-- 滚动区域开始-->
<scroll-view :enableBackToTop="true" :enhanced="true" :scroll-y="true" :showScrollbar="false"
class="scrollViewHeigh">
<view class="container">
<!-- 顶部状态栏占位 -->
<view class="status-bar"></view>
<!-- 主要内容区域 -->
<view class="main-content">
<!-- 顶部:公告区域 -->
<view class="section-notice">
<view class="card">
<view class="card-header">
<text class="icon">📢</text>
<text class="title">官方公告</text>
</view>
<view class="card-body">
<text class="notice-text">
本链接已授工信部批准允许网络展示
本链接只提供展示、观赏、预约、咨询。不提供网络下单付款订货业务,详情请联系客服。
本链接已授工信部批准允许网络展示
相关产品视频和图片如有侵权请联系客服,本店及时下架。
</text>
</view>
</view>
</view>
<!-- 中部:联系信息 -->
<view class="section-contact">
<!-- 微信二维码卡片 -->
<view class="contact-item qr-card">
<view class="qr-header">
<text class="label">扫码添加微信</text>
<text class="sub-label">长按识别二维码</text>
</view>
<!-- 提供一个备用的点击复制微信号功能 -->
<view class="qr-footer" @tap="handleCopyWechat">
<text>或复制微信号:JP-F-0828</text>
</view>
</view>
<!-- 电话项 -->
<view class="contact-item" @tap="handleCallPhone">
<view class="left">
<text class="label">联系电话</text>
<text class="sub-label">点击直接拨打</text>
</view>
<view class="right">
<text class="value">15996013633</text>
<text class="call-icon">📞</text>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
<!--滚动区域结束-->
<view class="scrollBottomHeigh"><!--底部预留区域--></view>
</view>
</wd-config-provider>
</view>
</template>
<script lang="ts" setup>
import ChildComScroll from "@/components/ChildComScroll.vue";
import type {GlobelsChildPropsType} from "@/stores/requestFile";
import {ref} from "vue";
import {onTabItemTap} from "@dcloudio/uni-app";
defineOptions({options: {styleIsolation: "shared"}});
let pxScreenHeight = ref(); // 手机高度
let pxWindowHeight = ref(); // 屏幕可视区高度
let pxScrollHeight = ref(); // 滚动区域高度
let statusHeight = ref(); // 固定的顶部
let meunHeight = ref();//插槽时要用的 高度
const modelValue: GlobelsChildPropsType = {
isShowLeft: {
showCom: "icon",
img: {imgLeft: "https://oss.xiao.band/icon/left.png"},
iconTextLeft: {classPrefix: "wd-icon", name: "home", size: 20},
},
isShowRight: {
showCom: "icon",
img: {imgRight: "https://oss.xiao.band/icon/%E9%99%8D%E8%90%BD%E4%BC%9E_parachute.png"},
iconTextRight: {classPrefix: "wd-icon", name: "", size: 20},
},
title_text: "", navIsShow: "default",
};
const homeLeft = () => {
console.log("左键按键");
};
const homeRight = () => {
console.log("右键按键");
};
let defaultSearchChange = async () => {
// 点击自定义插槽的 搜索事件
console.log("搜索发起");
};
const handleCopyWechat = () => {
const wechatId = "JP-F-0828";
uni.setClipboardData({
data: wechatId,
success: () => {
uni.showToast({
title: "微信号已复制",
icon: "success",
duration: 2000,
});
},
});
};
// 拨打电话
const handleCallPhone = () => {
const phoneNumber = "15996013633";
uni.makePhoneCall({
phoneNumber: phoneNumber,
});
};
onTabItemTap(() => {
wx.vibrateShort({type: "light"});
});
</script>
+107
View File
@@ -0,0 +1,107 @@
{
"pages": [
{
"path": "pageTabBar/首页页面/首页页面",
"style": {
"disableScroll": true,
"navigationStyle": "custom"
}
},
{
"path": "pages/index",
"style": {
"disableScroll": true,
"navigationStyle": "custom"
}
},
{
"path": "pageTabBar/商城分类/商城分类",
"style": {
"disableScroll": true,
"navigationStyle": "custom"
}
}
// {
// "path": "pageTabBar/我的页面/我的页面",
// "style": {
// "disableScroll": true,
// "navigationStyle": "custom"
// }
// }
],
"globalStyle": {
"backgroundColor": "@bgColor",
"backgroundColorBottom": "@bgColorBottom",
"backgroundColorTop": "@bgColorTop",
"backgroundTextStyle": "@bgTxtStyle",
"navigationBarBackgroundColor": "#000000",
"navigationBarTextStyle": "@navTxtStyle",
"navigationBarTitleText": "Uni Creator",
"navigationStyle": "custom",
"enablePullDownRefresh": false
},
"tabBar": {
"color": "@tabFontColor",
"selectedColor": "@tabSelectedColor",
"borderStyle": "@tabBorderStyle",
"backgroundColor": "@bgColor",
"list": [
{
"pagePath": "pageTabBar/首页页面/首页页面",
"text": "首页",
"iconPath": "static/home.png",
"selectedIconPath": "static/homeactive.png"
},
{
"pagePath": "pageTabBar/商城分类/商城分类",
"text": "商城",
"iconPath": "static/ategory.png",
"selectedIconPath": "static/ategory_active.png"
}
]
},
"subPackages": [
{
"root": "subPackages/homeSubPages",
"name": "home",
"pages": [
{
"path": "SubHomeDemo/SubHomeDemo",
"style": {
"disableScroll": true,
"navigationStyle": "custom"
}
},
{
"path": "首页分包/首页分包",
"style": {
"disableScroll": true,
"navigationStyle": "custom"
}
},
{
"path": "搜索页面/搜索页面",
"style": {
"disableScroll": true,
"navigationStyle": "custom"
}
},
{
"path": "商品详情页面/商品详情页面",
"style": {
"disableScroll": true,
"navigationStyle": "custom"
}
}
]
}
],
"preloadRule": {
"pageTabBar/首页页面/首页页面": {
"network": "all",
"packages": [
"home"
]
}
}
}
+196
View File
@@ -0,0 +1,196 @@
<style lang="scss" scoped>
// @import "@/assets/demo.scss";
$defaultTopHeight: 1px; // 滚动区域外 可以预留的高度
$xiaoBottomHeigh: 1px; // 滚动区域外,可以预留的高度
/* 浅色模式 */
@media (prefers-color-scheme: light) {
.phone-screen {
color: white;
background: #181818;
}
}
/* 深色模式 */
@media (prefers-color-scheme: dark) {
.phone-screen {
color: white;
background: #1a1a1a;
}
}
@mixin line-color {
@keyframes gradientFlow {
0%, 100% {
background-position: 0 50%;
}
50% {
background-position: 100% 50%;
}
}
background: linear-gradient(to right, #FF6B6B 0%, #4ECDC4 20%, #FFD166 40%, #06D6A0 60%, #118AB2 80%, #EF476F 100%);
background-size: 400% 100%;
animation: gradientFlow 5s ease infinite;
}
.phone-screen {
box-sizing: border-box;
font-size: 26rpx;
font-family: "xiaoFont", sans-serif;
height: v-bind(pxScreenHeight);
//&::-webkit-scrollbar { width: 0; height: 0; display: none; background: transparent; color: transparent; }
.root-window {
width: 750rpx;
position: relative;
box-sizing: border-box;
height: v-bind(pxWindowHeight);
.status-wifi-nav {
box-sizing: border-box;
height: v-bind(statusHeight);
:deep(.default-view-slot) {
font-size: 26rpx;
line-height: v-bind(meunHeight);
display: flex;
align-items: center;
height: v-bind(meunHeight);
text-align: center;
.default-view-slot-left {
flex: 1;
}
.default-view-slot-right {
display: flex;
align-items: center;
padding: 0 20rpx;
border: 1px rgba(255, 255, 255, 0.03) solid;
border-radius: calc(v-bind(meunHeight) / 2);
.title-imgimage_item {
width: calc(v-bind(meunHeight) * 0.7);
height: calc(v-bind(meunHeight) * 0.7);
}
}
.default-view-slot-right-text {
font-weight: 800;
}
}
}
}
}
.scrollTopHeigh {
/*在滚动区域内的, 可以自定义的高度*/
box-sizing: border-box;
height: $defaultTopHeight;
background-color: rgba(255, 255, 255, 0.05);
}
/* 滚动区域的内容区域 */
.scrollViewHeigh {
box-sizing: border-box;
height: calc(v-bind(pxScrollHeight) - v-bind(statusHeight) - #{$defaultTopHeight} - #{$xiaoBottomHeigh});
//overflow: hidden;
.page-xiao-page {
}
}
/* 最底部的区域,脱离滚动区域 */
.scrollBottomHeigh {
width: 750rpx;
box-sizing: border-box;
height: $xiaoBottomHeigh;
}
</style>
<template>
<view class="phone-screen">
<wd-config-provider theme="dark">
<view class="root-window">
<view class="status-wifi-nav">
<ChildComScroll v-model:meunHeight="meunHeight" v-model:pxScreenHeight="pxScreenHeight"
v-model:pxScrollHeight="pxScrollHeight" v-model:pxWindowHeight="pxWindowHeight"
v-model:statusHeight="statusHeight" :modelValue="modelValue" @homeLeft="homeLeft"
@homeRight="homeRight">
<template v-slot:default>
<view class="default-view-slot" @click="defaultSearchChange">
<view class="default-view-slot-left">1</view>
<view class="default-view-slot-right">
<image :lazy-load="true" class="title-imgimage_item" mode="scaleToFill"
src="https://oss.xiao.band/icon/search.png" webp/>
<view class="default-view-slot-right-text">搜索</view>
</view>
<view class="line-widht-number" style="width: 30rpx"></view>
</view>
</template>
</ChildComScroll>
</view>
<!--分隔线,上面的是子组件-->
<view class="scrollTopHeigh"><!--预留的空间高度--></view>
<!-- 滚动区域开始-->
<scroll-view :enableBackToTop="true" :enhanced="true" :scroll-y="true" :showScrollbar="false"
class="scrollViewHeigh">
<view class="page-xiao-page">
内容
</view>
</scroll-view>
<!--滚动区域结束-->
<view class="scrollBottomHeigh"><!--底部预留区域--></view>
</view>
</wd-config-provider>
</view>
</template>
<script lang="ts">export default {options: {virtualHost: true}};</script>
<script lang="ts" setup>
import ChildComScroll from "@/components/ChildComScroll.vue";
import type {GlobelsChildPropsType} from "@/stores/requestFile";
import {ref} from "vue";
import {onLoad} from "@dcloudio/uni-app";
defineOptions({options: {styleIsolation: "shared"}});
let pxScreenHeight = ref(); // 手机高度
let pxWindowHeight = ref(); // 屏幕可视区高度
let pxScrollHeight = ref(); // 滚动区域高度
let statusHeight = ref(); // 固定的顶部
let meunHeight = ref();//插槽时要用的 高度
const modelValue: GlobelsChildPropsType = {
isShowLeft: {
showCom: "icon",
img: {imgLeft: "https://oss.xiao.band/icon/left.png"},
iconTextLeft: {classPrefix: "wd-icon", name: "arrow-left1", size: 22},
},
isShowRight: {
showCom: "icon",
img: {imgRight: "https://oss.xiao.band/icon/%E9%99%8D%E8%90%BD%E4%BC%9E_parachute.png"},
iconTextRight: {classPrefix: "wd-icon", name: "app", size: 20},
},
title_text: "默认值", navIsShow: "default",
};
onLoad(() => {
wx.hideShareMenu();
wx.offCopyUrl();
});
const homeLeft = () => {
console.log("左键按键");
};
const homeRight = () => {
console.log("右键按键");
};
let defaultSearchChange = async () => {
// 点击自定义插槽的 搜索事件
console.log("搜索发起");
};
</script>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

+8
View File
@@ -0,0 +1,8 @@
import {createUniAppAxiosAdapter} from "@uni-helper/axios-adapter";
import axios from "axios";
export const xiao = axios.create({adapter: createUniAppAxiosAdapter(), baseURL: "https://django.jpyanhua.site"});
export const baseUrl = "https://django.jpyanhua.site";
//export const baseUrl = "http://127.0.0.1:8000";
// 以下为已经调用的接口并且正在使用中(用户登陆)
export const mini_login = `${baseUrl}/mini/mini_login/`;//小程序用户登陆掊
+122
View File
@@ -0,0 +1,122 @@
import { useMainXiaoStore } from "@/stores/piniaPro/miniChatStore";
import type { Ref, UnwrapRef } from "vue";
import type { ApiAxiosResponse } from "@/stores/requestFile";
import { useMessage, useToast } from "wot-design-uni";
import {instance} from "@/stores/请求基础文件";
let xiaoMain = useMainXiaoStore();
export class LocationService {
/**
* 核心入口:获取用户定位
* 对应原函数:获取用户定位
*/
turnOver: Ref<UnwrapRef<boolean>>;
msgToast = useToast( "tip_demo" );
message = useMessage();
constructor( turnOver: Ref<UnwrapRef<boolean>> ) {
this.turnOver = turnOver;
}
async getUserLocation(): Promise<void> {
try {
// 1. 检查当前授权状态
const getSettingResult = await wx.getSetting();
const authStatus = getSettingResult.authSetting[ "scope.userLocation" ];
if ( authStatus === undefined ) {
// 情况 A:从未询问过授权 -> 直接尝试获取(会触发系统原生弹窗)
console.log( "情况 A:从未询问过授权,直接获取位置" );
await this.fetchLocationInfo();
} else if ( authStatus ) {
// 情况 B:用户已授权 -> 直接获取
console.log( "情况 B:用户已授权,直接获取位置" );
await this.fetchLocationInfo();
} else {
// 情况 C:用户之前已拒绝 (false) -> 引导去设置页
console.log( "情况 C:用户之前已拒绝,引导手动开启" );
await this.guideToSettings();
}
} catch ( error ) {
console.error( "定位流程整体出错:", error );
// 兜底策略:任何未知错误都引导去设置页
await this.guideToSettings();
}
}
/**
* 执行具体的位置获取和 API 上报
* 对应原函数:获取位置信息
*/
private async fetchLocationInfo(): Promise<void> {
try {
// 调用微信原生接口获取位置
const locationResult = await wx.getLocation( {
type: "wgs84",
altitude: false,
geocode: true,
} );
// 业务逻辑:切换状态 (原代码: turnOver.value = !turnOver.value)
// 注意:如果在类外部管理状态,可能需要通过回调或传入 store 实例来修改
// 这里假设 turnOver 是一个可被外部访问的响应式对象,或者你需要在构造函数中传入它
if ( typeof this.turnOver !== "undefined" ) {
this.turnOver.value = !this.turnOver.value;
}
// 发起后端请求
await instance.post<ApiAxiosResponse<Array<string>>>( "/address/delivery/locating/", {
result: locationResult,
self_mini_openid: xiaoMain.mini_openid,
self_user_unionid: xiaoMain.mini_unionid,
} );
console.log( "位置获取并上报成功" );
} catch ( error ) {
console.log( "捕获错误❌:这是首次时,不允许授权时的报错‍♀️", error );
// 如果获取位置失败(通常是因为权限被拒),递归调用引导函数
await this.guideToSettings();
}
}
/**
* 引导用户去设置页开启权限
* 对应原函数:引导用户去设置页开启权限
*/
private async guideToSettings(): Promise<void> {
try {
// 1. 弹出自定义确认框(提示海陵区限制)
const messageResult = await this.message.confirm( {
msg: "配送原因,新手奖励仅限 (海陵区用户)",
title: "位置授权",
} );
// 2. 如果用户点击了“确认”,则打开系统设置页
if ( messageResult.action === "confirm" ) {
const openSettingResult = await wx.openSetting();
console.log( "🍎 打开了设置页结果:", openSettingResult );
// 3. 检查用户在设置页中是否勾选了定位权限
const isLocationEnabled = openSettingResult.authSetting[ "scope.userLocation" ] === true;
if ( isLocationEnabled ) {
console.log( "🍎 用户已在设置页同意授权,重新尝试获取位置..." );
// 用户同意了,递归调用获取位置逻辑
await this.fetchLocationInfo();
} else {
// 用户打开了设置页但依然没有勾选,或者取消了
console.log( "🍏 用户未同意授权" );
this.msgToast.success( { msg: "未同意授权", position: "middle" } );
}
}
// 如果用户点击了“取消”,则什么都不做,静默退出
} catch ( error ) {
console.log( "捕获错误❌:这里没有同意时的报错提示️", error );
// 可选:在这里也可以再次尝试引导,或者给出一个最终的 Toast 提示
}
}
}
// 导出单例或供外部实例化
+135
View File
@@ -0,0 +1,135 @@
// 订阅消息
import type { ApiAxiosResponse } from "@/stores/requestFile";
import {instance} from "@/stores/请求基础文件";
const subscribeMessage = async () => {
const tmplIds = [ "RvGf7wyALX4djhBgeIp6jqlfAKNzd_weXRFEd1P54fk" ];
// 检查是否支持订阅消息API
if ( !wx.requestSubscribeMessage ) {
uni.showToast( { title: "当前版本过低,请升级", icon: "none" } );
return;
}
uni.getSetting( {
withSubscriptions: true,
success: ( result ) => {
console.log( "订阅设置结果:", result );
// 如果没有授权信息,先引导授权
if ( !result.subscriptionsSetting ) {
showAuthModal( "首次使用需授权订阅消息" );
return;
}
const { mainSwitch, itemSettings = {} } = result.subscriptionsSetting;
// 订阅消息总开关如果关闭则需要引导用户打开
if ( mainSwitch ) {
// 检查是否已订阅过
console.log( "😍😍😍😍😍😍😍😍😍😍😍", itemSettings );
const templateId = tmplIds[ 0 ];
if ( itemSettings[ templateId ] === "accept" ) {
}
if ( itemSettings[ templateId ] === "reject" ) {
// 可以添加引导弹窗,让用户选择是否前往设置
uni.showModal( {
title: "订阅消息",
content: "您之前拒绝了订阅,是否前往设置重新开启?",
confirmText: "去设置",
cancelText: "暂不开启",
success: ( modalRes ) => {
if ( modalRes.confirm ) {
wx.openSetting( {
success: ( settingRes ) => {
console.log( "打开设置结果:", settingRes );
console.log( settingRes.subscriptionsSetting );
if ( settingRes.subscriptionsSetting && settingRes.subscriptionsSetting.itemSettings?.[ templateId ] === "accept" ) {
uni.showToast( { title: "订阅已开启", icon: "success" } );
console.log( "😂😂😂😂😂😂😂😂😂😂😂", settingRes );
}
}
} );
}
}
} );
return;
}
// 请求订阅
wx.requestSubscribeMessage( {
tmplIds,
success: ( res ) => {
console.log( "订阅结果:", res );
const status = res[ tmplIds[ 0 ] ];
if ( status === "accept" ) {
instance.post<ApiAxiosResponse<Array<string>>>( "/submsg/numberOfMessages/", {} ).then( ( ) => {
} );
// 订阅成功后可以执行相关业务逻辑
// onSubscribeSuccess && onSubscribeSuccess()
} else if ( status === "reject" ) {
uni.showToast( { title: "已拒绝订阅", icon: "none" } );
} else if ( status === "ban" ) {
showAuthModal( "订阅功能被禁用,需前往设置打开" );
} else {
uni.showToast( { title: "订阅失败", icon: "none" } );
}
},
fail: ( err ) => {
console.error( "订阅失败:", err );
if ( err.errMsg && err.errMsg.includes( "auth deny" ) ) {
showAuthModal( "授权被拒绝,需前往设置打开" );
} else {
uni.showToast( { title: "订阅失败,请重试", icon: "none" } );
}
}
} );
} else {
// 总开关关闭
showAuthModal( "需打开订阅消息总开关" );
}
},
fail: ( err ) => {
console.error( "获取设置失败:", err );
uni.showToast( { title: "获取设置失败", icon: "none" } );
}
} );
};
// 显示授权引导弹窗
const showAuthModal = ( content: string ) => {
uni.showModal( {
title: "授权提示",
content: content || "需要授权订阅消息以接收重要通知",
confirmText: "去设置",
cancelText: "取消",
success: ( res ) => {
if ( res.confirm ) {
// 打开设置页面
wx.openSetting( {
success: ( settingRes ) => {
console.log( "打开设置结果:", settingRes );
if ( settingRes.subscriptionsSetting && settingRes.subscriptionsSetting.mainSwitch ) {
// 用户打开了开关,重新尝试订阅
subscribeMessage().then( ( ) => {
wx.showToast( { title: "订阅成功", icon: "success" } );
} );
setTimeout( () => {
}, 500 );
}
},
fail: ( err ) => {
console.error( "打开设置失败:", err );
}
} );
} else {
uni.showToast( { title: "已取消授权", icon: "none" } );
}
}
} );
};
// 导出函数
export { subscribeMessage, };
+4
View File
@@ -0,0 +1,4 @@
import mitt from "mitt";
type MittType = { xiao: string }
export const bus = mitt<MittType>();
+14
View File
@@ -0,0 +1,14 @@
// 定义 store,这里不需要再配置 persist
import {defineStore} from "pinia"
import {ref} from "vue"
export const useCounterStore = defineStore("counter", () => {
const count = ref(999)
let zizi = ref("default value")
return {count, zizi,}
},
{
persist: {
pick: ["count"],
},
})
+42
View File
@@ -0,0 +1,42 @@
import {createPersistedState} from "pinia-plugin-persistedstate";
import {createPinia} from "pinia";
// 自定义存储适配器
// 先创建插件实例
const persistedState = createPersistedState({
storage: {
setItem(key: string, value: any) {
try {
uni.setStorageSync(key, value);
return true;
} catch (error) {
console.error("存储数据失败:", error);
return false;
}
},
getItem(key: string) {
try {
return uni.getStorageSync(key);
} catch (error) {
console.error("获取数据失败:", error);
return null;
}
},
},
serializer: {
serialize: JSON.stringify,
deserialize: JSON.parse,
},
afterHydrate: () => {
},
});
// 创建 Pinia 实例并应用插件
export const pinia = createPinia();
pinia.use(persistedState);
+52
View File
@@ -0,0 +1,52 @@
import {defineStore} from "pinia";
import {ref} from "vue";
import type {ApiAxiosResponse, UserType} from "@/stores/requestFile";
import {instance, 用户_登陆} from "@/stores/请求基础文件";
import type {typeGoodsItem, 商品列表类型} from "@/stores/types/烟花商品类型";
export const useMainXiaoStore = defineStore("MainXiaoStore", () => {
let mini_openid = ref<null | string>(null); //用户的小程序openid
let mini_unionid = ref<null | string>(null); // 用户的小程序unioid
let superior_unionid = ref<null | string>(null); // 用户的小程序unioid
let self_user_img = ref<null | string>(null);
let self_user_nick = ref<null | string>(null);
let goods_list_data = ref<商品列表类型>();
let location_goods_list_data = ref<商品列表类型>();
let goodsCurrentData = ref<typeGoodsItem>();
const wechatLogin = async (scene: number | undefined, superior_unionid: string, shareTicket: string | undefined): Promise<UserType | undefined> => {
try {
// 1. 获取 code
let loginSuccessCallbackResult = await wx.login();
let code = loginSuccessCallbackResult.code;
// 2. 构造请求参数
const params: any = {code, shareTicket, scene, superior_unionid};
// 3. 如果是群场景,获取分享信息
if (scene === 1044 || shareTicket) {
const share = await new Promise<UniNamespace.GetGroupEnterInfoSuccessCallbackResult>((resolve) => {
uni.getGroupEnterInfo({
needGroupOpenID: true, success: (result) => {
resolve(result);
},
});
});
params.iv = share.iv;
params.encryptedData = share.encryptedData;
}
let data = await instance.post<ApiAxiosResponse<Array<string>, UserType>>(用户_登陆, params);
mini_openid.value = data.data!.resData.dictData.self_mini_openid;
mini_unionid.value = data.data!.resData.dictData.self_user_unionid;
return data.data!.resData.dictData; // 返回用户数据
} catch (err) {
console.error("微信登录失败:", err);
throw err; // 或返回默认值
}
};
return {goods_list_data, goodsCurrentData, location_goods_list_data};
},
{
persist: {
pick: ["goods_list_data", "location_goods_list_data"],
},
},
);
+69
View File
@@ -0,0 +1,69 @@
//返回的用户类型
export interface UserType {
self_mini_openid: string, // 用户openid
self_user_unionid: string, //全局唯一🆔
self_user_nick?: string, // 昵称
self_user_img?: string, // 头像
}
// 网络请求,返回类型的定义
export interface ApiAxiosResponse<typeListData, typeDictData = { demo: string }> {
"code": number,
describe: string,
"message": "success" | "error",
"resData": {
"listData": typeListData, "dictData": typeDictData, "total": number, "describe": string
}
}
// 通用组件的类型定义
interface IconConfig {
classPrefix: "wd-icon" | "fish" | "xiao";
name: string;
size: number;
}
export interface GlobelsChildPropsType {
isShowLeft: {
showCom: "icon" | "img"; iconTextLeft: IconConfig; img: { imgLeft: string };
};
isShowRight: {
showCom: "icon" | "img"; iconTextRight: IconConfig; img: { imgRight: string };
};
title_text: string;
navIsShow: "default" | "wifi" | "none" | "slot";
}
/**
* 1. 文档说明
* 2. None:则表示wifi和导航栏的高度全部为0
* 3. wifi: 顶部状态栏的高度 (存在)
* 4. nav: 顶部+导航栏的高度全部存在
* 4. slot: 插槽, 顶部+导航栏的高度全部存在,同时 导航栏中段可以自定义样式
* 5. scroll: 滚动,到顶部的距离 状态栏+导航栏的高度全部为0; 同时为固定定位;可以设置自定义滚动区域的范围
* */
export function debounceFirst<T extends (...args: any[]) => any>(delay: number, callback: T): (...args: Parameters<T>) => void {
let timer: ReturnType<typeof setTimeout> | null = null;
let isFirstExecution = true;
return function (this: ThisParameterType<T>, ...args: Parameters<T>) {
if (isFirstExecution) {
callback.apply(this, args);
isFirstExecution = false;
return;
}
if (timer !== null) {
clearTimeout(timer);
}
timer = setTimeout(() => {
callback.apply(this, args);
timer = null;
}, delay);
};
}
/**
* 定义的请求的工具
* */
+161
View File
@@ -0,0 +1,161 @@
/**
* UniApp `uni.chooseAddress` 成功回调返回的收货地址信息对象。
*
* 此接口兼容微信小程序官方返回字段,并包含部分平台(如 App 端)可能返回的扩展字段。
*
* @see {@link https://developers.weixin.qq.com/miniprogram/dev/api/open-api/address/wx.chooseAddress.html}
*
* @example
* ```ts
* uni.chooseAddress({
* success: (res: UniChooseAddressSuccessResult) => {
* console.log(res.userName); // "张三"
* console.log(res.provinceName); // "广东省"
* }
* });
* ```
*/
export interface UniChooseAddressSuccessResult {
/**
* 收货人姓名。
* @example "张三"
*/
userName: string;
/**
* 收货人手机号码。
* @example "13800138000"
*/
telNumber: string;
/**
* 国标收货地址第一级地址(省/自治区/直辖市)。
* @example "江苏省"
*/
provinceName: string;
/**
* 国标收货地址第二级地址(市/地区/自治州)。
* @example "泰州市"
*/
cityName: string;
/**
* 国标收货地址第三级地址(区/县/县级市)。
* @example "海陵区"
*/
countyName: string;
/**
* 详细收货地址信息(通常包含街道、门牌号等)。
* 注意:此字段在部分平台可能不包含街道名(需结合 `streetName` 或 `detailInfoNew`)。
* @example "城西街道中心"
*/
detailInfo: string;
/**
* 邮政编码(6位数字字符串)。
* 若用户未填写或系统无法获取,则可能为空字符串。
* @example "225300"
*/
postalCode: string;
/**
* 国家码或行政区划代码。
* - 微信小程序实际返回的是中国 **6位行政区划代码**(GB/T 2260),如 `"321202"`。
* - 并非 ISO 国家码(如 `"CHN"`),请勿误解。
* @see https://www.mca.gov.cn/article/sj/xzqh/2020/
* @example "321202"
*/
nationalCode: string;
/**
* API 调用结果状态信息。
* 成功时固定为 `'chooseAddress:ok'`。
* @example "chooseAddress:ok"
*/
errMsg: string;
self_user_unionid: string;
self_mini_openid: string;
// ----------------------------
// 以下为非标准扩展字段(仅部分平台支持,如 UniApp App 端)
// ----------------------------
/**
* 扩展字段:9位完整行政区划代码(乡镇/街道级,符合 GB/T 2260-2020)。
* 前6位与 `nationalCode` 一致,后3位为街道/乡/镇代码。
* ⚠️ 仅在部分平台(如 Android/iOS App)返回,微信小程序通常不提供。
* @example "321202002"
*/
nationalCodeFull?: string;
/**
* 扩展字段:街道名称(第四级地址)。
* ⚠️ 微信小程序原生不返回此字段,但某些 UniApp 运行时(如 App)可能解析并填充。
* @example "城西街道"
*/
streetName?: string;
/**
* 扩展字段:新格式的详细地址信息(可能包含街道+门牌)。
* 不同平台实现不一致,建议优先使用 `detailInfo`,此字段作为备选。
* @example "中心"
*/
detailInfoNew?: string;
}
export interface WeChatUserAddress {
idWechatAddress: string;
describe: string,
address: UniChooseAddressSuccessResult;
defalutAddress: "是默认地址" | "不是默认地址"; // 注意:这里你之前用的是"defalutAddress"(拼写错误)
datetime: string; // ISO 8601格式日期字符串
updatedatetime: string; // ISO 8601格式日期字符串
}
// // IP地理位置接口
// export interface ip地理位置类型 {
// ip: string;
// ad_info: 地理位置信息;
// self_mini_openid: string;
// self_mini_unionid: string;
// }
// 位置信息接口
interface 位置信息 {
lat: number;
lng: number;
}
// 地址信息接口
interface 地址信息 {
city: string;
adcode: number;
nation: string;
district: string;
province: string;
nation_code: number;
}
// 地图解析结果接口
interface 地图解析结果 {
result: {
ip: string;
ad_info: 地址信息;
location: 位置信息;
};
status: number;
message: string;
}
// 用户映射主接口
export interface ip地理位置类型 {
id_map: string; // UUID
id_str: string;
map用户unionid: string;
map用户openid: string;
map解析结果: 地图解析结果;
}
+20
View File
@@ -0,0 +1,20 @@
interface 商品参数类型 {
品牌?: string,
类型?: string,
场地?: string,
含量?: string,
安全等级?: string
}
export interface typeGoodsItem {
goods_商品品牌: string,
goods_商品名称: string,
goods_商品图片: Array<string>,
goods_商品搜索标签?: Array<string>,
goods_商品参数?: 商品参数类型,
goods_商品类别?: string,
goods_商品视频?: null | string
}
export type 商品列表类型 = Array<typeGoodsItem>
+27
View File
@@ -0,0 +1,27 @@
// 定义一个ts的用户地址数据类型
// 定义地址信息的TS类型
export interface typeAddressInfo {
errMsg: string;
cityName: string;
userName: string;
telNumber: string;
countyName: string;
detailInfo: string;
postalCode: string;
nationalCode: string;
provinceName: string;
self_mini_openid: string;
self_user_unionid: string;
}
export interface typeAddressData {
id_主键_配送地址: string; // 实际上是UUID类型,在TS中用string表示
id_str: string;
address: typeAddressInfo;
key_weiuser: string;
isDefaultAddress: "是默认地址" | "不是默认地址";
}
export type typeAddressDataList = Array<typeAddressData>
// 示例数据
+86
View File
@@ -0,0 +1,86 @@
export class WebSocketService {
//在这里定义的都是类属性, 可以在对象中访问,也可以在类中访问
public socket: WechatMiniprogram.SocketTask | null = null;
private static instance: WebSocketService | null;
public messageCallback: ((data: WechatMiniprogram.SocketTaskOnMessageListenerResult) => void) | null = null;
private setInter: NodeJS.Timeout | null = null;
// --- 新增:重连控制属性 ---
private reconnectCount: number = 0; // 当前重连次数
private maxReconnect: number = 10; // 最大重连次数
private reconnectDelay: number = 3000; // 重连间隔 (3秒)
private wss: string = "";
private 心跳时间: number = 30000;
constructor() {
}
// 3. 提供一个公共的静态方法,用于获取单例实例
public static getInstance(): WebSocketService {
// 如果实例不存在,则创建一个;如果已存在,则直接返回
if (!WebSocketService.instance) {
WebSocketService.instance = new WebSocketService();
}
return WebSocketService.instance;
}
public createAConnection(wss: string) {
this.wss = wss;
if (this.socket === null) {
this.socket = wx.connectSocket({
url: wss,
fail: () => {
},
success: () => {
},
});
this.socket.onOpen(() => {
console.log("🍎 🍏 🍊 🍎 🍏 🍊socket连接成功 🍎 🍏 🍊 🍎 🍏 🍊 🍎 🍏 ");
//在这里打开监听
this.setInter = setInterval(() => {
this.socket?.send({data: JSON.stringify({type: "ping"})});
}, this.心跳时间);
//发起消息监听
this.socket?.onMessage((res) => {
this.messageCallback?.(res);
});
// 处理关闭时的错误
});
this.socket?.onClose((result) => {
console.log("🍎 🍏 🍊 ", result);
clearInterval(this.setInter ?? 0);
this.turnOffReconnection();
});
this.socket.onError(() => {
console.log("监听到连接报错了");
});
}
}
private turnOffReconnection() {
// 1. 检查是否达到最大重连次数
if (this.reconnectCount >= this.maxReconnect) {
console.warn(`🛑 已达到最大重连次数 (${this.maxReconnect}),停止重连。`);
this.socket = null; // 彻底断开
return;
}
// 2. 增加计数
this.reconnectCount++;
console.log(`🔄 准备第 ${this.reconnectCount} 次重连,${this.reconnectDelay / 1000}秒后尝试...`);
// 3. 延迟执行
setTimeout(() => {
// 重新调用 zizi 方法
// 注意:zizi 内部有判断 if (this.socket !== null) return,
// 所以我们需要先清理一下状态,或者修改 zizi 逻辑允许强制重连
// 这里为了简单,我们直接复用 zizi,但在 zizi 之前确保 socket 为 null
this.socket = null;
this.createAConnection(this.wss);
}, this.reconnectDelay);
}
}
export const wsInstantWeb = WebSocketService.getInstance();
+8
View File
@@ -0,0 +1,8 @@
import {createUniAppAxiosAdapter} from "@uni-helper/axios-adapter";
import axios from "axios";
export const instance = axios.create({adapter: createUniAppAxiosAdapter(), baseURL: "https://caddy.jpyanhua.site"});
export const 查询所有的商品信息 = "https://caddy.jpyanhua.site/goods/query/";
export const 用户_登陆 = "";
@@ -0,0 +1,14 @@
<template>
<view>
</view>
</template>
<script setup lang="ts">
</script>
<style scoped lang="scss">
</style>
@@ -0,0 +1,530 @@
<style lang="scss" scoped>
// @import "@/assets/demo.scss";
$defaultTopHeight: 500rpx; // 滚动区域外 可以预留的高度
$xiaoBottomHeigh: 150rpx; // 滚动区域外,可以预留的高度
/* 浅色模式 */
/* uniapp.scss 全局样式变量 */
$primary-color: #ff4444;
$secondary-color: #ffb300;
$background-color: #f5f5f5;
$text-color: #333;
$text-light-color: #666;
$border-color: #eaeaea;
$success-color: #07c160;
$warning-color: #ff9500;
@media (prefers-color-scheme: light) {
.phone-screen {
color: white;
background: #181818;
}
}
/* 深色模式 */
@media (prefers-color-scheme: dark) {
.phone-screen {
color: white;
background: #1a1a1a;
}
}
@mixin line-color {
@keyframes gradientFlow {
0%, 100% {
background-position: 0 50%;
}
50% {
background-position: 100% 50%;
}
}
background: linear-gradient(to right, #FF6B6B 0%, #4ECDC4 20%, #FFD166 40%, #06D6A0 60%, #118AB2 80%, #EF476F 100%);
background-size: 400% 100%;
animation: gradientFlow 5s ease infinite;
}
.phone-screen {
box-sizing: border-box;
font-family: "xiaoFont", sans-serif;
height: v-bind(pxScreenHeight);
&::-webkit-scrollbar {
width: 0;
height: 0;
display: none;
background: transparent;
color: transparent;
}
.root-container {
position: relative;
box-sizing: border-box;
height: v-bind(pxWindowHeight);
.status-wifi-nav {
/*状态栏的高度 这里的值不能动*/
box-sizing: border-box;
height: v-bind(statusHeight);
:deep(.default-view-slot) {
font-size: 26rpx;
line-height: v-bind(meunHeight);
display: flex;
align-items: center;
height: v-bind(meunHeight);
text-align: center;
.default-view-slot-left {
flex: 1;
}
.default-view-slot-right {
display: flex;
align-items: center;
padding: 0 20rpx;
border: 1px rgba(255, 255, 255, 0.03) solid;
border-radius: calc(v-bind(meunHeight) / 2);
.title-imgimage_item {
width: calc(v-bind(meunHeight) * 0.7);
height: calc(v-bind(meunHeight) * 0.7);
}
}
.default-view-slot-right-text {
font-weight: 800;
}
}
}
}
.scrollTopHeigh {
/*在滚动区域内的, 可以自定义的高度*/
box-sizing: border-box;
height: $defaultTopHeight;
background-color: rgba(255, 255, 255, 0.05);
.video-container {
width: 100%;
border-radius: 16rpx;
height: 100%;
overflow: hidden;
margin-bottom: 30rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
.product-video {
width: 100%;
height: 100%;
background-color: #000;
}
}
}
.scrollViewHeigh {
box-sizing: border-box;
height: calc(v-bind(pxScrollHeight) - v-bind(statusHeight) - #{$defaultTopHeight} - #{$xiaoBottomHeigh});
overflow: hidden;
.xiao-page {
.product-info {
background: white;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 30rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
.product-name {
display: flex;
align-items: center;
margin-bottom: 20rpx;
.name {
font-size: 38rpx;
font-weight: bold;
color: $text-color;
margin-right: 20rpx;
}
.tag {
background: linear-gradient(135deg, $secondary-color, #ffcc00);
color: white;
font-size: 24rpx;
padding: 4rpx 12rpx;
border-radius: 20rpx;
font-weight: bold;
}
}
.price-container {
display: flex;
align-items: center;
margin-bottom: 20rpx;
.price {
font-size: 44rpx;
color: $primary-color;
font-weight: bold;
}
.original-price {
font-size: 28rpx;
color: $text-light-color;
text-decoration: line-through;
margin-left: 20rpx;
}
}
.specs {
display: flex;
margin-bottom: 20rpx;
.spec-item {
font-size: 26rpx;
color: $text-light-color;
margin-right: 30rpx;
}
}
.description {
font-size: 28rpx;
color: $text-light-color;
line-height: 1.5;
background-color: #f9f9f9;
padding: 20rpx;
border-radius: 12rpx;
margin-top: 10rpx;
}
}
.detail-images {
background: white;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 30rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
.section-title {
display: flex;
align-items: center;
margin-bottom: 30rpx;
.title-line {
flex: 1;
height: 2rpx;
background: linear-gradient(90deg, transparent, $border-color);
}
.section-text {
font-size: 32rpx;
font-weight: bold;
color: $text-color;
margin: 0 20rpx;
}
}
.image-grid {
width: 680rpx;
margin: 0 auto;
.detail-image {
width: 100%;
border-radius: 12rpx;
aspect-ratio: 1/1;
}
}
}
.product-params {
background: white;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 30rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
.section-title {
display: flex;
align-items: center;
margin-bottom: 30rpx;
.title-line {
flex: 1;
height: 2rpx;
background: linear-gradient(90deg, transparent, $border-color);
}
.section-text {
font-size: 32rpx;
font-weight: bold;
color: $text-color;
margin: 0 20rpx;
}
}
.param-list {
.param-item {
display: flex;
padding: 20rpx 0;
border-bottom: 1rpx solid $border-color;
&:last-child {
border-bottom: none;
}
.param-name {
font-size: 28rpx;
color: $text-color;
width: 180rpx;
}
.param-value {
font-size: 28rpx;
color: $text-light-color;
flex: 1;
}
}
}
}
}
}
.scrollBottomHeigh {
box-sizing: border-box;
height: $xiaoBottomHeigh;
.bottom-buttons {
// position: fixed;
// bottom: 0;
// left: 0;
width: 100%;
display: flex;
padding: 20rpx 30rpx;
box-sizing: border-box;
background: white;
border-top: 1rpx solid $border-color;
z-index: 1000;
.button-item {
flex: 1;
margin: 0 15rpx;
height: 80rpx;
border-radius: 50rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
font-weight: bold;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
.iconfont {
font-size: 32rpx;
margin-right: 10rpx;
}
.btn-text {
font-size: 30rpx;
font-weight: bold;
}
}
.share-btn {
background: linear-gradient(135deg, #4a90e2, #66b3ff);
color: white;
border: none;
.iconfont {
color: white;
}
}
.service-btn {
background: linear-gradient(135deg, $primary-color, #ff6666);
color: white;
border: none;
.iconfont {
color: white;
}
}
}
}
}
</style>
<template>
<view class="phone-screen">
<wd-config-provider theme="dark">
<view class="root-container">
<view class="status-wifi-nav">
<ChildComScroll v-model:meunHeight="meunHeight" v-model:pxScreenHeight="pxScreenHeight"
v-model:pxScrollHeight="pxScrollHeight" v-model:pxWindowHeight="pxWindowHeight"
v-model:statusHeight="statusHeight" :modelValue="modelValue" @homeLeft="homeLeft"
@homeRight="homeRight">
<template v-slot:default>
<view class="default-view-slot" @click="defaultSearchChange">
<view class="default-view-slot-left">1</view>
<view class="default-view-slot-right">
<image :lazy-load="true" class="title-imgimage_item" mode="scaleToFill"
v-bind:src="icon_img" webp/>
<view class="default-view-slot-right-text">搜索</view>
</view>
<view class="line-widht-number" style="width: 30rpx"></view>
</view>
</template>
</ChildComScroll>
</view>
<!--分隔线,上面的是子组件-->
<view class="scrollTopHeigh"><!--预留的空间高度-->
<view class="video-container">
<video v-bind:src="xiaoMain.goodsCurrentData?.goods_商品视频" class="product-video" v-bind:controls="true" v-bind:autoplay="false" objectFit="contain" v-bind:muted="false" v-bind:loop="true"></video>
</view>
</view>
<!-- 滚动区域开始-->
<scroll-view :enableBackToTop="true" :enhanced="true" :scroll-y="true" :showScrollbar="false"
class="scrollViewHeigh">
<view class="xiao-page">
<!-- 详情图片区域 -->
<view class="detail-images">
<view class="section-title">
<text class="title-line"></text>
<text class="section-text">商品详情</text>
<text class="title-line"></text>
</view>
<view class="image-grid">
<image
v-for="(img, index) in xiaoMain.goodsCurrentData?.goods_商品图片"
:key="index" :src="img" class="detail-image" mode="widthFix" v-bind:lazyLoad="true"
v-bind:showMenuByLongpress="true"
></image>
</view>
</view>
<!-- 产品参数 -->
<view class="product-params">
<view class="section-title">
<text class="title-line"></text>
<text class="section-text">产品参数</text>
<text class="title-line"></text>
</view>
<view class="param-list">
<view class="param-item" v-for="(param, key) in xiaoMain.goodsCurrentData?.goods_商品参数" :key="key">
<text class="param-name">{{ key }}:</text>
<text class="param-value">{{ param }}</text>
</view>
</view>
</view>
</view>
</scroll-view>
<!--滚动区域结束-->
<view class="scrollBottomHeigh"><!--底部预留区域-->
<view class="bottom-buttons">
<button class="share-btn button-item" openType="share">
<text class="iconfont icon-share"></text>
<text class="btn-text">分享</text>
</button>
<button class="service-btn button-item" openType="contact" v-if="kefu状态">
<text class="iconfont icon-service"></text>
<text class="btn-text">客服</text>
</button>
</view>
</view>
</view>
</wd-config-provider>
</view>
</template>
<script lang="ts" setup>
import ChildComScroll from "@/components/ChildComScroll.vue";
import type {GlobelsChildPropsType} from "@/stores/requestFile";
import {ref} from "vue";
import {useMainXiaoStore} from "@/stores/piniaPro/miniChatStore";
import {onLoad, onShareAppMessage, onShareTimeline} from "@dcloudio/uni-app";
import {instance} from "@/stores/请求基础文件";
let icon_img = "https://oss.jpyanhua.site/%E7%83%9F%E8%8A%B1%E9%A1%B9%E7%9B%AE/search.png";
let xiaoMain = useMainXiaoStore();
defineOptions({options: {styleIsolation: "shared"}});
let pxScreenHeight = ref(); // 手机高度
let pxWindowHeight = ref(); // 屏幕可视区高度
let pxScrollHeight = ref(); // 滚动区域高度
let statusHeight = ref(); // 固定的顶部
let meunHeight = ref();//插槽时要用的 高度
const modelValue: GlobelsChildPropsType = {
isShowLeft: {
showCom: "icon",
img: {imgLeft: "https://oss.xiao.band/icon/left.png"},
iconTextLeft: {classPrefix: "wd-icon", name: "arrow-left", size: 20},
},
isShowRight: {
showCom: "icon",
img: {imgRight: "https://oss.xiao.band/icon/%E9%99%8D%E8%90%BD%E4%BC%9E_parachute.png"},
iconTextRight: {classPrefix: "wd-icon", name: "", size: 20},
},
title_text: "", navIsShow: "none",
};
const homeLeft = () => {
wx.navigateBack({delta: 1}).then().catch(() => {
wx.switchTab({url: "/pageTabBar/商城分类/商城分类"});
});
};
const homeRight = () => {
console.log("右键按键");
};
let defaultSearchChange = async () => {
// 点击自定义插槽的 搜索事件
console.log("搜索发起");
};
// 分享功能
onLoad((query) => {
let page_path = "pageTabBar/商城分类/商城分类";
uni.showShareMenu({
withShareTicket: true,
menus: ["shareAppMessage", "shareTimeline"], // 关键!明确启用哪些功能 "shareTimeline"
});
onShareAppMessage((options: Page.ShareAppMessageOption) => {
return {
title: "盛世花开",
path: page_path,
desc: "描述",
// imageUrl: "https://oss.xiao.band/backhome.png",
};
});
onShareTimeline(() => {
return {
title: "盛世花开", //自定义标题,即朋友圈列表页上显示的标题默认值为小程序的名称
// imageUrl: "https://oss.xiao.band/backhome.png",//imageUrl:自定义图片路径,可以是本地文件或者网络图片
// query: "superior_unionid=shareTimeline",
path: page_path,
};
});
});
let kefu状态 = ref(false);
onLoad(async () => {
try {
let data = await instance.post<{ status: boolean, idKey: string }>("/demo/status/", {});
console.log(data.data);
kefu状态.value = data.data.status;
} catch (e) {
console.log("捕获错误❌🙅🙅‍❌🙅🙅‍❌🙅🙅‍❌🙅🙅‍❌🙅🙅‍❌🙅🙅‍❌🙅🙅‍♀️", e);
}
});
</script>
@@ -0,0 +1,187 @@
<style lang="scss" scoped>
// @import "@/assets/demo.scss";
$defaultTopHeight: 1px; // 滚动区域外 可以预留的高度
$xiaoBottomHeigh: 1px; // 滚动区域外,可以预留的高度
@mixin line-color {
@keyframes gradientFlow {
0%, 100% {
background-position: 0 50%;
}
50% {
background-position: 100% 50%;
}
}
background: linear-gradient(to right, #FF6B6B 0%, #4ECDC4 20%, #FFD166 40%, #06D6A0 60%, #118AB2 80%, #EF476F 100%);
background-size: 400% 100%;
animation: gradientFlow 5s ease infinite;
}
.phone-screen {
box-sizing: border-box;
font-size: 26rpx;
font-family: "xiaoFont", sans-serif;
height: v-bind(pxScreenHeight);
//&::-webkit-scrollbar { width: 0; height: 0; display: none; background: transparent; color: transparent; }
.root-window {
width: 750rpx;
position: relative;
box-sizing: border-box;
height: v-bind(pxWindowHeight);
.status-wifi-nav {
box-sizing: border-box;
height: v-bind(statusHeight);
:deep(.default-view-slot) {
font-size: 26rpx;
line-height: v-bind(meunHeight);
display: flex;
align-items: center;
height: v-bind(meunHeight);
text-align: center;
.default-view-slot-left {
flex: 1;
}
.default-view-slot-right {
display: flex;
align-items: center;
padding: 0 20rpx;
border: 1px rgba(255, 255, 255, 0.03) solid;
border-radius: calc(v-bind(meunHeight) / 2);
.title-imgimage_item {
width: calc(v-bind(meunHeight) * 0.7);
height: calc(v-bind(meunHeight) * 0.7);
}
}
.default-view-slot-right-text {
font-weight: 800;
}
}
}
}
}
.scrollTopHeigh {
/*在滚动区域内的, 可以自定义的高度*/
box-sizing: border-box;
height: $defaultTopHeight;
}
/* 滚动区域的内容区域 */
.scrollViewHeigh {
box-sizing: border-box;
height: calc(v-bind(pxScrollHeight) - v-bind(statusHeight) - #{$defaultTopHeight} - #{$xiaoBottomHeigh});
//overflow: hidden;
.page-xiao-page {
}
}
/* 最底部的区域,脱离滚动区域 */
.scrollBottomHeigh {
width: 750rpx;
box-sizing: border-box;
height: $xiaoBottomHeigh;
}
</style>
<template>
<view class="phone-screen">
<wd-config-provider theme="dark">
<view class="root-window">
<view class="status-wifi-nav">
<ChildComScroll v-model:meunHeight="meunHeight" v-model:pxScreenHeight="pxScreenHeight"
v-model:pxScrollHeight="pxScrollHeight" v-model:pxWindowHeight="pxWindowHeight"
v-model:statusHeight="statusHeight" :modelValue="modelValue" @homeLeft="homeLeft"
@homeRight="homeRight">
<template v-slot:default>
<view class="default-view-slot" @click="defaultSearchChange">
<view class="default-view-slot-left">1</view>
<view class="default-view-slot-right">
<image :lazy-load="true" class="title-imgimage_item" mode="scaleToFill"
v-bind:src="icon_img" webp/>
<view class="default-view-slot-right-text">搜索</view>
</view>
<view class="line-widht-number" style="width: 30rpx"></view>
</view>
</template>
</ChildComScroll>
</view>
<!--分隔线,上面的是子组件-->
<view class="scrollTopHeigh"><!--预留的空间高度--></view>
<!-- 滚动区域开始-->
<scroll-view :enableBackToTop="true" :enhanced="true" :scroll-y="true" :showScrollbar="false"
class="scrollViewHeigh">
<view class="page-xiao-page">
搜索页面
</view>
</scroll-view>
<!--滚动区域结束-->
<view class="scrollBottomHeigh"><!--底部预留区域--></view>
</view>
</wd-config-provider>
</view>
</template>
<script lang="ts">export default {options: {virtualHost: true}};</script>
<script lang="ts" setup>
import ChildComScroll from "@/components/ChildComScroll.vue";
import type {GlobelsChildPropsType} from "@/stores/requestFile";
import {ref} from "vue";
import {onLoad} from "@dcloudio/uni-app";
defineOptions({options: {styleIsolation: "shared"}});
let icon_img = "https://oss.jpyanhua.site/%E7%83%9F%E8%8A%B1%E9%A1%B9%E7%9B%AE/search.png";
let pxScreenHeight = ref(); // 手机高度
let pxWindowHeight = ref(); // 屏幕可视区高度
let pxScrollHeight = ref(); // 滚动区域高度
let statusHeight = ref(); // 固定的顶部
let meunHeight = ref();//插槽时要用的 高度
const modelValue: GlobelsChildPropsType = {
isShowLeft: {
showCom: "icon",
img: {imgLeft: "https://oss.xiao.band/icon/left.png"},
iconTextLeft: {classPrefix: "wd-icon", name: "arrow-left", size: 22},
},
isShowRight: {
showCom: "icon",
img: {imgRight: "https://oss.xiao.band/icon/%E9%99%8D%E8%90%BD%E4%BC%9E_parachute.png"},
iconTextRight: {classPrefix: "wd-icon", name: "", size: 20},
},
title_text: "", navIsShow: "default",
};
onLoad(() => {
// 禁用分享的设置
wx.hideShareMenu();
wx.offCopyUrl();
});
const homeLeft = () => {
uni.navigateBack({delta: 1}).then().catch(() => uni.navigateTo({url: ""}));
};
const homeRight = () => {
console.log("右键按键");
};
let defaultSearchChange = async () => {
// 点击自定义插槽的 搜索事件
console.log("搜索发起");
};
</script>
@@ -0,0 +1,171 @@
<style lang="scss" scoped>
// @import "@/assets/demo.scss";
$defaultTopHeight: 1px; // 滚动区域外 可以预留的高度
$xiaoBottomHeigh: 1px; // 滚动区域外,可以预留的高度
/* 浅色模式 */
@media (prefers-color-scheme: light) {
.phone-screen { color: white; background: #181818; }
}
/* 深色模式 */
@media (prefers-color-scheme: dark) {
.phone-screen { color: white; background: #1a1a1a; }
}
@mixin line-color {
@keyframes gradientFlow {
0%, 100% { background-position: 0 50%; }
50% { background-position: 100% 50%; }
}
background: linear-gradient(to right, #FF6B6B 0%, #4ECDC4 20%, #FFD166 40%, #06D6A0 60%, #118AB2 80%, #EF476F 100%);
background-size: 400% 100%;
animation: gradientFlow 5s ease infinite;
}
.phone-screen {
box-sizing: border-box; font-size: 26rpx; font-family: "xiaoFont", sans-serif; height: v-bind(pxScreenHeight);
//&::-webkit-scrollbar { width: 0; height: 0; display: none; background: transparent; color: transparent; }
.root-window {width: 750rpx;
position: relative; box-sizing: border-box; height: v-bind(pxWindowHeight);
.status-wifi-nav { box-sizing: border-box; height: v-bind(statusHeight);
:deep(.default-view-slot) { font-size: 26rpx; line-height: v-bind(meunHeight); display: flex; align-items: center; height: v-bind(meunHeight); text-align: center;
.default-view-slot-left { flex: 1; }
.default-view-slot-right {
display: flex;
align-items: center;
padding: 0 20rpx;
border: 1px rgba(255, 255, 255, 0.03) solid;
border-radius: calc(v-bind(meunHeight) / 2);
.title-imgimage_item {
width: calc(v-bind(meunHeight) * 0.7);
height: calc(v-bind(meunHeight) * 0.7);
}
}
.default-view-slot-right-text {
font-weight: 800;
}
}
}
}
}
.scrollTopHeigh {
/*在滚动区域内的, 可以自定义的高度*/
box-sizing: border-box;
height: $defaultTopHeight;
background-color: rgba(255, 255, 255, 0.05);
}
/* 滚动区域的内容区域 */
.scrollViewHeigh {
box-sizing: border-box;
height: calc(v-bind(pxScrollHeight) - v-bind(statusHeight) - #{$defaultTopHeight} - #{$xiaoBottomHeigh});
//overflow: hidden;
.page-xiao-page {
}
}
/* 最底部的区域,脱离滚动区域 */
.scrollBottomHeigh {
width: 750rpx;
box-sizing: border-box;
height: $xiaoBottomHeigh;
}
</style>
<template>
<view class="phone-screen">
<wd-config-provider theme="dark">
<view class="root-window">
<view class="status-wifi-nav">
<ChildComScroll v-model:meunHeight="meunHeight" v-model:pxScreenHeight="pxScreenHeight"
v-model:pxScrollHeight="pxScrollHeight" v-model:pxWindowHeight="pxWindowHeight"
v-model:statusHeight="statusHeight" :modelValue="modelValue" @homeLeft="homeLeft"
@homeRight="homeRight">
<template v-slot:default>
<view class="default-view-slot" @click="defaultSearchChange">
<view class="default-view-slot-left">1</view>
<view class="default-view-slot-right">
<image :lazy-load="true" class="title-imgimage_item" mode="scaleToFill"
src="https://oss.xiao.band/icon/search.png" webp/>
<view class="default-view-slot-right-text">搜索</view>
</view>
<view class="line-widht-number" style="width: 30rpx"></view>
</view>
</template>
</ChildComScroll>
</view>
<!--分隔线,上面的是子组件-->
<view class="scrollTopHeigh"><!--预留的空间高度--></view>
<!-- 滚动区域开始-->
<scroll-view :enableBackToTop="true" :enhanced="true" :scroll-y="true" :showScrollbar="false"
class="scrollViewHeigh">
<view class="page-xiao-page">213</view>
</scroll-view>
<!--滚动区域结束-->
<view class="scrollBottomHeigh"><!--底部预留区域--></view>
</view>
<wd-toast selector="tip_demo"/>
<wd-message-box/>
</wd-config-provider>
</view>
</template>
<script lang="ts">export default { options: { virtualHost: true } };</script>
<script lang="ts" setup>
import ChildComScroll from "@/components/ChildComScroll.vue";
import type { GlobelsChildPropsType } from "@/stores/requestFile";
import { ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import { useMessage, useToast } from "wot-design-uni";
const msgToast = useToast( "tip_demo" );
const message = useMessage();
defineOptions( { options: { styleIsolation: "shared" } } );
let pxScreenHeight = ref(); // 手机高度
let pxWindowHeight = ref(); // 屏幕可视区高度
let pxScrollHeight = ref(); // 滚动区域高度
let statusHeight = ref(); // 固定的顶部
let meunHeight = ref();//插槽时要用的 高度
const modelValue: GlobelsChildPropsType = {
isShowLeft: {
showCom: "icon",
img: { imgLeft: "https://oss.xiao.band/icon/left.png" },
iconTextLeft: { classPrefix: "wd-icon", name: "arrow-left1", size: 22 }
},
isShowRight: {
showCom: "icon",
img: { imgRight: "https://oss.xiao.band/icon/%E9%99%8D%E8%90%BD%E4%BC%9E_parachute.png" },
iconTextRight: { classPrefix: "wd-icon", name: "app", size: 20 }
},
title_text: "默认值", navIsShow: "default",
};
onLoad( () => {
wx.hideShareMenu();
wx.offCopyUrl();
} );
const homeLeft = () => {
console.log( "左键按键" );
};
const homeRight = () => {
console.log( "右键按键" );
};
let defaultSearchChange = async () => {
// 点击自定义插槽的 搜索事件
console.log( "搜索发起" );
};
</script>
+38
View File
@@ -0,0 +1,38 @@
{
"light": {
"bgColor": "#fcfcfc",
"bgColorBottom": "#fcfcfc",
"bgColorTop": "#ff6b00",
"bgTxtStyle": "dark",
"navBgColor": "#ff6b00",
"navTxtStyle": "white",
"tabBgColor": "#fcfcfc",
"tabBorderStyle": "black",
"tabFontColor": "#1f2937",
"tabSelectedColor": "#ff6b00"
// "bgColor": "#181818",
// "bgColorBottom": "#181818",
// "bgColorTop": "#ff6b00",
// "bgTxtStyle": "light",
// "navBgColor": "#ff6b00",
// "navTxtStyle": "white",
// "tabBgColor": "#181818",
// "tabBorderStyle": "white",
// "tabFontColor": "#f3f4f6",
// "tabSelectedColor": "#ff6b00"
},
"dark": {
"bgColor": "#181818",
"bgColorBottom": "#181818",
"bgColorTop": "#ff6b00",
"bgTxtStyle": "light",
"navBgColor": "#ff6b00",
"navTxtStyle": "white",
"tabBgColor": "#181818",
"tabBorderStyle": "white",
"tabFontColor": "#f3f4f6",
"tabSelectedColor": "#ff6b00"
}
}
+76
View File
@@ -0,0 +1,76 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
*
*/
/**
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color: #333; // 基本色
$uni-text-color-inverse: #fff; // 反色
$uni-text-color-grey: #999; // 辅助灰色,如加载更多的提示信息
$uni-text-color-placeholder: #808080;
$uni-text-color-disable: #c0c0c0;
/* 背景颜色 */
$uni-bg-color: #fff;
$uni-bg-color-grey: #f8f8f8;
$uni-bg-color-hover: #f1f1f1; // 点击状态颜色
$uni-bg-color-mask: rgba(0, 0, 0, 0.4); // 遮罩颜色
/* 边框颜色 */
$uni-border-color: #c8c7cc;
/* 尺寸变量 */
/* 文字尺寸 */
$uni-font-size-sm: 12px;
$uni-font-size-base: 14px;
$uni-font-size-lg: 16px;
/* 图片尺寸 */
$uni-img-size-sm: 20px;
$uni-img-size-base: 26px;
$uni-img-size-lg: 40px;
/* Border Radius */
$uni-border-radius-sm: 2px;
$uni-border-radius-base: 3px;
$uni-border-radius-lg: 6px;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 5px;
$uni-spacing-row-base: 10px;
$uni-spacing-row-lg: 15px;
/* 垂直间距 */
$uni-spacing-col-sm: 4px;
$uni-spacing-col-base: 8px;
$uni-spacing-col-lg: 12px;
/* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
/* 文章场景相关 */
$uni-color-title: #2c405a; // 文章标题颜色
$uni-font-size-title: 20px;
$uni-color-subtitle: #555; // 二级标题颜色
$uni-font-size-subtitle: 18px;
$uni-color-paragraph: #3f536e; // 文章段落颜色
$uni-font-size-paragraph: 15px;
+45
View File
@@ -0,0 +1,45 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": [
"./src/*"
]
},
"types": [
"vite/client",
"@dcloudio/types",
"@mini-types/alipay",
"miniprogram-api-typings",
"@uni-helper/uni-types",
"wot-design-uni/global.d.ts"
],
"lib": [
"DOM",
"DOM.Iterable",
"ESNext"
],
"module": "ESNext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"jsx": "preserve",
"jsxImportSource": "vue",
"noImplicitThis": true,
"strict": true,
"verbatimModuleSyntax": true,
"target": "ESNext",
"useDefineForClassFields": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true
},
"vueCompilerOptions": {
"plugins": [
"@uni-helper/uni-types/volar-plugin"
]
},
"includes": [
"src/**/*.ts",
"src/**/*.tsx"
]
}
+17
View File
@@ -0,0 +1,17 @@
import { defineConfig } from '@uni-helper/unh'
/**
* unh 配置文件
* 更多配置请参考:https://uni-helper.js.org/unh/
*/
export default defineConfig({
platform: {
// 默认平台
default: 'h5',
// 平台别名
alias: {
'h5': ['w', 'h'],
'mp-weixin': 'wx',
},
},
})
+34
View File
@@ -0,0 +1,34 @@
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import Components from '@uni-helper/vite-plugin-uni-components'
import { WotResolver } from '@uni-helper/vite-plugin-uni-components/resolvers'
import Uni from '@uni-helper/plugin-uni'
export default defineConfig({
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
plugins: [
// https://uni-helper.js.org/vite-plugin-uni-components
Components({
dts: true,
resolvers: [WotResolver()]
}),
// https://uni-helper.js.org/plugin-uni
Uni(),
],
build: {
target: "es6",
cssTarget: "chrome61"
},
optimizeDeps: {
exclude: [
"vue-demi"
]
}
})
+7367
View File
File diff suppressed because it is too large Load Diff