调整ui
10
App.vue
@@ -1,14 +1,10 @@
|
||||
<script>
|
||||
export default {
|
||||
globalData: {
|
||||
indexParam: null
|
||||
},
|
||||
onLaunch: function() {
|
||||
console.log('App Launch')
|
||||
Vue.prototype.$checkAuth = () => {
|
||||
if (!uni.getStorageSync('vuex_token')) {
|
||||
uni.$emit("needLogin")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
},
|
||||
onShow: function() {
|
||||
console.log('App Show')
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// 全局配置文件
|
||||
// let baseUrl = 'http://192.168.0.108:8088';
|
||||
// let staticUrl = 'http://192.168.0.108:8088';
|
||||
let baseUrl = 'https://sourcebyte.vip';
|
||||
let staticUrl = 'https://sourcebyte.vip';
|
||||
// let baseUrl = 'https://sourcebyte.vip';
|
||||
// let staticUrl = 'https://sourcebyte.vip';
|
||||
let baseUrl = 'http://localhost:8089';
|
||||
let staticUrl = 'http://localhost:8089';
|
||||
// 版本号 用于更新
|
||||
let version = 1;
|
||||
// vuex_version版本号 用于显示
|
||||
|
||||
@@ -12,7 +12,10 @@ const install = (Vue, vm) => {
|
||||
// config.header.Token = '5d33018e653d897fc259b42cf022c1b3';
|
||||
// 方式一,存放在vuex的token,假设使用了uView封装的vuex方式,见:https://uviewui.com/components/globalVariable.html
|
||||
// 自定义token头
|
||||
// config.header.Authorization = vm.vuex_token;
|
||||
config.header = {
|
||||
...config.header, // ⭐ 保留你外部传入的 header
|
||||
'content-type': 'application/json'
|
||||
}
|
||||
return config;
|
||||
};
|
||||
// 响应拦截,判断状态码是否通过
|
||||
|
||||
105
components/DatePicker/DateFilter.vue
Normal file
@@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<view class="date-filter">
|
||||
|
||||
<!-- 开始日期 -->
|
||||
<view class="filter-item" @click="$refs.startPicker.open(startDate)">
|
||||
<text class="label">开始日期</text>
|
||||
<text class="value">{{ startDate || '请选择' }}</text>
|
||||
</view>
|
||||
|
||||
<view class="divider"></view>
|
||||
|
||||
<!-- 结束日期 -->
|
||||
<view class="filter-item" @click="$refs.endPicker.open(endDate)">
|
||||
<text class="label">结束日期</text>
|
||||
<text class="value">{{ endDate || '请选择' }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 开始日期选择器 -->
|
||||
<DatePicker
|
||||
v-model="startDate"
|
||||
ref="startPicker"
|
||||
@confirm="selectStart"
|
||||
/>
|
||||
|
||||
<!-- 结束日期选择器 -->
|
||||
<DatePicker
|
||||
v-model="endDate"
|
||||
ref="endPicker"
|
||||
@confirm="selectEnd"
|
||||
/>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DatePicker from './DatePicker.vue';
|
||||
|
||||
export default {
|
||||
name: 'DateFilter',
|
||||
components: { DatePicker },
|
||||
|
||||
props: {
|
||||
start: { type: String, default: '' },
|
||||
end: { type: String, default: '' }
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
startDate: this.start,
|
||||
endDate: this.end
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
/** 选择开始日期 */
|
||||
selectStart(e) {
|
||||
this.startDate = e;
|
||||
this.$emit('update:start', e);
|
||||
this.$emit('change', { start: this.startDate, end: this.endDate });
|
||||
},
|
||||
|
||||
/** 选择结束日期 */
|
||||
selectEnd(e) {
|
||||
this.endDate = e;
|
||||
this.$emit('update:end', e);
|
||||
this.$emit('change', { start: this.startDate, end: this.endDate });
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.date-filter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
.filter-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 24rpx;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 28rpx;
|
||||
padding-left: 30rpx;
|
||||
color: #333;
|
||||
margin-top: 6rpx;
|
||||
}
|
||||
|
||||
.divider {
|
||||
width: 2rpx;
|
||||
height: 40rpx;
|
||||
background: #e5e5e5;
|
||||
margin: 0 20rpx;
|
||||
}
|
||||
</style>
|
||||
232
components/DatePicker/DatePicker.vue
Normal file
@@ -0,0 +1,232 @@
|
||||
<template>
|
||||
<view v-if="visible" class="picker-overlay" @click.stop="close">
|
||||
<view class="picker-container" @click.stop>
|
||||
<view class="picker-header">
|
||||
<text class="cancel" @click="close">取消</text>
|
||||
<text class="title">请选择日期</text>
|
||||
<text class="confirm" @click="confirm">确定</text>
|
||||
</view>
|
||||
|
||||
<view class="picker-columns">
|
||||
<!-- 年 -->
|
||||
<scroll-view
|
||||
class="column"
|
||||
scroll-y
|
||||
:scroll-top="scrollPos[0]"
|
||||
@scroll="onScroll(0,$event)"
|
||||
>
|
||||
<view
|
||||
v-for="(y,i) in years"
|
||||
:key="i"
|
||||
class="item"
|
||||
:class="{active:selected[0]===i}"
|
||||
@click="select(0,i)"
|
||||
>
|
||||
{{y}}年
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 月 -->
|
||||
<scroll-view
|
||||
class="column"
|
||||
scroll-y
|
||||
:scroll-top="scrollPos[1]"
|
||||
@scroll="onScroll(1,$event)"
|
||||
>
|
||||
<view
|
||||
v-for="(m,i) in months"
|
||||
:key="i"
|
||||
class="item"
|
||||
:class="{active:selected[1]===i}"
|
||||
@click="select(1,i)"
|
||||
>
|
||||
{{m}}月
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 日 -->
|
||||
<scroll-view
|
||||
class="column"
|
||||
scroll-y
|
||||
:scroll-top="scrollPos[2]"
|
||||
@scroll="onScroll(2,$event)"
|
||||
>
|
||||
<view
|
||||
v-for="(d,i) in days"
|
||||
:key="i"
|
||||
class="item"
|
||||
:class="{active:selected[2]===i}"
|
||||
@click="select(2,i)"
|
||||
>
|
||||
{{d}}日
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: { value: String },
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
years: [],
|
||||
months: Array.from({ length: 12 }, (_, i) => i + 1),
|
||||
days: [],
|
||||
selected: [0, 0, 0],
|
||||
scrollPos: [0, 0, 0], // 小程序 scroll-view 只能用 scroll-top 来滚动
|
||||
itemH: 40,
|
||||
scrollTimer: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
open(val) {
|
||||
this.visible = true;
|
||||
const currentYear = new Date().getFullYear();
|
||||
this.years = Array.from({ length: currentYear - 1980 + 1 }, (_, i) => 1980 + i);
|
||||
const date = val ? new Date(val) : new Date();
|
||||
const y = date.getFullYear();
|
||||
const m = date.getMonth() + 1;
|
||||
const d = date.getDate();
|
||||
|
||||
this.selected = [
|
||||
this.years.indexOf(y),
|
||||
m - 1,
|
||||
0 // 先占位,待 days 生成后再修正
|
||||
];
|
||||
|
||||
this.updateDays(() => {
|
||||
this.selected[2] = Math.min(d - 1, this.days.length - 1);
|
||||
this.updateScrollPos();
|
||||
});
|
||||
},
|
||||
close() {
|
||||
this.visible = false;
|
||||
},
|
||||
|
||||
confirm() {
|
||||
const y = this.years[this.selected[0]];
|
||||
const m = this.selected[1] + 1;
|
||||
const d = this.selected[2] + 1;
|
||||
const dateStr = `${y}-${String(m).padStart(2,'0')}-${String(d).padStart(2,'0')}`;
|
||||
|
||||
this.$emit("input", dateStr);
|
||||
this.$emit("confirm", dateStr);
|
||||
this.close();
|
||||
},
|
||||
|
||||
// 点击选择项
|
||||
select(col, idx) {
|
||||
this.selected.splice(col, 1, idx);
|
||||
|
||||
if (col === 0 || col === 1) {
|
||||
this.updateDays(() => {
|
||||
if (this.selected[2] >= this.days.length) {
|
||||
this.selected[2] = this.days.length - 1;
|
||||
}
|
||||
this.updateScrollPos();
|
||||
});
|
||||
} else {
|
||||
this.updateScrollPos();
|
||||
}
|
||||
},
|
||||
|
||||
// 滚动事件处理(兼容小程序)
|
||||
onScroll(col, e) {
|
||||
if (!e.detail) return;
|
||||
const top = e.detail.scrollTop;
|
||||
|
||||
if (this.scrollTimer) clearTimeout(this.scrollTimer);
|
||||
|
||||
this.scrollTimer = setTimeout(() => {
|
||||
const idx = Math.round(top / this.itemH);
|
||||
|
||||
this.selected.splice(col, 1, idx);
|
||||
|
||||
if (col === 0 || col === 1) {
|
||||
this.updateDays(() => {
|
||||
if (this.selected[2] >= this.days.length) {
|
||||
this.selected[2] = this.days.length - 1;
|
||||
}
|
||||
this.updateScrollPos();
|
||||
});
|
||||
} else {
|
||||
this.updateScrollPos();
|
||||
}
|
||||
}, 120);
|
||||
},
|
||||
|
||||
// 更新 scroll-top,使选中项居中
|
||||
updateScrollPos() {
|
||||
this.scrollPos = [
|
||||
this.selected[0] * this.itemH,
|
||||
this.selected[1] * this.itemH,
|
||||
this.selected[2] * this.itemH,
|
||||
];
|
||||
},
|
||||
|
||||
updateDays(callback) {
|
||||
const year = this.years[this.selected[0]];
|
||||
const month = this.selected[1] + 1;
|
||||
const max = new Date(year, month, 0).getDate();
|
||||
|
||||
this.days = Array.from({ length: max }, (_, i) => i + 1);
|
||||
|
||||
this.$nextTick(() => {
|
||||
if (callback) callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.picker-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0,0,0,0.4);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-end;
|
||||
z-index: 999;
|
||||
}
|
||||
.picker-container {
|
||||
background: #fff;
|
||||
width: 100%;
|
||||
border-radius: 16px 16px 0 0;
|
||||
}
|
||||
.picker-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 12px 20px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.cancel { color: #999; }
|
||||
.confirm { color:#007aff; }
|
||||
.title { font-weight:bold; }
|
||||
|
||||
.picker-columns {
|
||||
display: flex;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.column {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.item {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
color:#666;
|
||||
}
|
||||
|
||||
.item.active {
|
||||
color:#007aff;
|
||||
font-weight:bold;
|
||||
font-size:18px;
|
||||
}
|
||||
</style>
|
||||
295
components/gallery/AssetGallery.vue
Normal file
@@ -0,0 +1,295 @@
|
||||
<template>
|
||||
<view class="house-gallery">
|
||||
<!-- 图片轮播 -->
|
||||
<u-swiper
|
||||
:list="swiperList"
|
||||
:current="current"
|
||||
height="1200rpx"
|
||||
>
|
||||
<template #default="{ item, index }">
|
||||
<view class="slide-item">
|
||||
<image :src="item.url" mode="aspectFill" class="slide-img" />
|
||||
|
||||
<!-- VR 按钮 -->
|
||||
<view v-if="item.type === 'vr'" class="vr-btn" @click.stop="openVR">
|
||||
VR
|
||||
</view>
|
||||
|
||||
<!-- 视频按钮 -->
|
||||
<view v-if="item.type === 'video'" class="video-btn" @click.stop="playVideo">
|
||||
▶
|
||||
</view>
|
||||
|
||||
<!-- 图片索引 -->
|
||||
<view class="slide-index">{{ index + 1 }}/{{ swiperList.length }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</u-swiper>
|
||||
|
||||
<!-- 广告遮罩栏 -->
|
||||
<view v-if="adVisible && adImage" class="ad-mask" @click="onAdClick">
|
||||
<image :src="adImage" mode="aspectFill" class="ad-img" />
|
||||
<view class="ad-close" @click.stop="adVisible = false">×</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部 Tab -->
|
||||
<view class="gallery-tab">
|
||||
<view
|
||||
class="gallery-tab-item"
|
||||
v-for="(item, i) in tabs"
|
||||
:key="i"
|
||||
:id="'tab-' + i"
|
||||
:class="{ active: activeTab === i }"
|
||||
@click="onTabClick(i)"
|
||||
>
|
||||
{{ item.label }}
|
||||
<text v-if="item.count">({{ item.count }})</text>
|
||||
</view>
|
||||
|
||||
<!-- 滑块动画 -->
|
||||
<view
|
||||
class="tab-line"
|
||||
:style="{ width: lineStyle.width + 'px', left: lineStyle.left + 'px' }"
|
||||
></view>
|
||||
</view>
|
||||
|
||||
<!-- 视频弹窗 -->
|
||||
<u-popup v-model="videoVisible" mode="center" border-radius="20">
|
||||
<video
|
||||
:src="videoUrl"
|
||||
autoplay
|
||||
controls
|
||||
style="width: 600rpx; height: 400rpx;"
|
||||
></video>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AssetGallery",
|
||||
props: {
|
||||
vrImage: String,
|
||||
videoCover: String,
|
||||
videoUrl: String,
|
||||
insideImages: Array,
|
||||
planImages: Array,
|
||||
adImage: String
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
current: 0,
|
||||
videoVisible: false,
|
||||
adVisible: true,
|
||||
tabs: [],
|
||||
indexMap: [],
|
||||
lineStyle: { width: 0, left: 0 }
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => this.updateTabLine(), 50);
|
||||
});
|
||||
},
|
||||
|
||||
watch: {
|
||||
activeTab() {
|
||||
this.$nextTick(() => this.updateTabLine());
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
swiperList() {
|
||||
let list = [];
|
||||
this.tabs = [];
|
||||
this.indexMap = [];
|
||||
let idx = 0;
|
||||
|
||||
if (this.vrImage) {
|
||||
this.tabs.push({ key: "vr", label: "VR", count: 1 });
|
||||
this.indexMap.push(idx);
|
||||
list.push({ type: "vr", url: this.vrImage });
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (this.videoCover) {
|
||||
this.tabs.push({ key: "video", label: "视频", count: 1 });
|
||||
this.indexMap.push(idx);
|
||||
list.push({ type: "video", url: this.videoCover });
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (this.insideImages?.length > 0) {
|
||||
this.tabs.push({ key: "inside", label: "内部图", count: this.insideImages.length });
|
||||
this.indexMap.push(idx);
|
||||
list.push(...this.insideImages.map((img) => ({ type: "inside", img })));
|
||||
idx += this.insideImages.length;
|
||||
}
|
||||
|
||||
if (this.planImages?.length > 0) {
|
||||
this.tabs.push({ key: "plan", label: "平面图", count: this.planImages.length });
|
||||
this.indexMap.push(idx);
|
||||
list.push(...this.planImages.map((url) => ({ type: "plan", url })));
|
||||
idx += this.planImages.length;
|
||||
}
|
||||
|
||||
return list;
|
||||
},
|
||||
|
||||
activeTab() {
|
||||
for (let i = 0; i < this.indexMap.length; i++) {
|
||||
const start = this.indexMap[i];
|
||||
const end = this.indexMap[i + 1] ?? 99999;
|
||||
if (this.current >= start && this.current < end) return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onAdClick() {
|
||||
this.$emit("ad-click");
|
||||
},
|
||||
|
||||
onSwiperChange(e) {
|
||||
this.current = e.detail.current;
|
||||
},
|
||||
|
||||
onTabClick(i) {
|
||||
this.current = this.indexMap[i];
|
||||
},
|
||||
|
||||
openVR() {
|
||||
this.$emit("open-vr");
|
||||
},
|
||||
|
||||
playVideo() {
|
||||
this.videoVisible = true;
|
||||
},
|
||||
|
||||
updateTabLine() {
|
||||
const index = this.activeTab;
|
||||
if (this.tabs.length === 0) return;
|
||||
|
||||
const id = `#tab-${index}`;
|
||||
uni.createSelectorQuery()
|
||||
.in(this)
|
||||
.select(id)
|
||||
.boundingClientRect((rect) => {
|
||||
if (!rect) return;
|
||||
this.lineStyle = { width: rect.width, left: rect.left };
|
||||
})
|
||||
.exec();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.house-gallery {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 轮播 */
|
||||
.slide-item {
|
||||
width: 100%;
|
||||
height: 1200rpx;
|
||||
position: relative;
|
||||
}
|
||||
.slide-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 0;
|
||||
}
|
||||
.vr-btn,
|
||||
.video-btn {
|
||||
position: absolute;
|
||||
bottom: 40rpx;
|
||||
right: 40rpx;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
color: #fff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.video-btn {
|
||||
font-size: 50rpx;
|
||||
}
|
||||
.slide-index {
|
||||
position: absolute;
|
||||
bottom: 20rpx;
|
||||
right: 20rpx;
|
||||
padding: 4rpx 8rpx;
|
||||
background: rgba(0,0,0,0.5);
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
/* 广告遮罩 */
|
||||
.ad-mask {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 120rpx;
|
||||
background: rgba(0,0,0,0.35);
|
||||
padding: 0 20rpx;
|
||||
z-index: 9;
|
||||
}
|
||||
.ad-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
.ad-close {
|
||||
position: absolute;
|
||||
right: 20rpx;
|
||||
top: 20rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 50%;
|
||||
background: rgba(0,0,0,0.55);
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 40rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
/* Tab bar */
|
||||
.gallery-tab {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
background: rgba(255,255,255,0.9);
|
||||
border-top: 1rpx solid #eee;
|
||||
height: 90rpx;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
z-index: 10;
|
||||
}
|
||||
.gallery-tab-item {
|
||||
padding: 20rpx 0;
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
.gallery-tab-item.active {
|
||||
color: #2979ff;
|
||||
font-weight: bold;
|
||||
}
|
||||
.tab-line {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 4rpx;
|
||||
background: #2979ff;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
</style>
|
||||
@@ -6,8 +6,8 @@
|
||||
<view class="nav-content">
|
||||
<!-- 左侧返回 -->
|
||||
<view class="nav-left">
|
||||
<u-icon name="arrow-left" size="44" color="#333" @click="onBack"></u-icon>
|
||||
<u-icon name="home" size="44" color="#333" @click="goHome"></u-icon>
|
||||
<u-icon name="arrow-left" size="44" color="#333" @click="onBack" v-if="showBack"></u-icon>
|
||||
<u-icon name="home" size="44" color="#333" @click="goHome" v-if="showHome"></u-icon>
|
||||
</view>
|
||||
|
||||
<!-- 中间标题 -->
|
||||
@@ -51,6 +51,14 @@ export default {
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
showBack: {
|
||||
type: Boolean,
|
||||
default: true // 左侧返回按钮默认显示
|
||||
},
|
||||
showHome: {
|
||||
type: Boolean,
|
||||
default: true // 回首页按钮默认显示
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
139
components/navbar/indexNavbar.vue
Normal file
@@ -0,0 +1,139 @@
|
||||
<template>
|
||||
<view
|
||||
class="index-navbar"
|
||||
:style="{ height: navHeight + 'px' }"
|
||||
>
|
||||
<view class="nav-content" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||||
<!-- 左侧返回 -->
|
||||
<view class="nav-left">
|
||||
<u-icon name="arrow-left" size="44" color="#333" @click="onBack" v-if="showBack"></u-icon>
|
||||
<u-icon name="home" size="44" color="#333" @click="goHome" v-if="showHome"></u-icon>
|
||||
</view>
|
||||
|
||||
<!-- 中间标题 -->
|
||||
<view class="nav-title">{{ title }}</view>
|
||||
|
||||
<!-- 右侧按钮(位于胶囊左侧) -->
|
||||
<view
|
||||
class="nav-right"
|
||||
:style="{ marginRight: menuRightGap + 'px' }"
|
||||
>
|
||||
<view
|
||||
v-for="(btn, index) in rightButtons"
|
||||
:key="index"
|
||||
class="nav-btn"
|
||||
@click="btn.onClick && btn.onClick()"
|
||||
>
|
||||
<u-icon
|
||||
:name="btn.icon"
|
||||
:color="btn.color || '#333'"
|
||||
:size="btn.size || 40"
|
||||
></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'indexNavbar',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
rightButtons: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
back: {
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
showBack: {
|
||||
type: Boolean,
|
||||
default: false // 左侧返回按钮默认显示
|
||||
},
|
||||
showHome: {
|
||||
type: Boolean,
|
||||
default: false // 回首页按钮默认显示
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
statusBarHeight: 0,
|
||||
navHeight: 0,
|
||||
menuRightGap: 0, // 胶囊按钮与右侧边距
|
||||
navContentHeight:0
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
const menuButton = wx.getMenuButtonBoundingClientRect ? wx.getMenuButtonBoundingClientRect() : null;
|
||||
|
||||
if (menuButton) {
|
||||
this.statusBarHeight = systemInfo.statusBarHeight;
|
||||
this.navContentHeight = menuButton.height; // 只算胶囊按钮区域高度
|
||||
this.navHeight = this.statusBarHeight + this.navContentHeight; // 总高度
|
||||
this.menuRightGap = systemInfo.screenWidth - menuButton.right + 8;
|
||||
} else {
|
||||
this.statusBarHeight = systemInfo.statusBarHeight;
|
||||
this.navContentHeight = 44; // 默认内容高度
|
||||
this.navHeight = this.statusBarHeight + this.navContentHeight;
|
||||
this.menuRightGap = 16;
|
||||
}
|
||||
|
||||
},
|
||||
methods: {
|
||||
onBack() {
|
||||
if (this.back) {
|
||||
this.back();
|
||||
} else {
|
||||
uni.navigateBack();
|
||||
}
|
||||
},
|
||||
goHome(){
|
||||
uni.reLaunch({
|
||||
url:'../index/index'
|
||||
})
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.index-navbar {
|
||||
background-color: none;
|
||||
|
||||
.nav-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
padding: 0 24rpx;
|
||||
}
|
||||
|
||||
.nav-left {
|
||||
width: 50rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.nav-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.nav-btn {
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
99
components/searchBar/SearchBar.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<view class="search-bar" :style="{ backgroundColor: backgroundColor,border:border}">
|
||||
<view v-if="showChoseCity" class="location-chose" @click="$emit('chooseCity')" :style="{fontSize:fontSize,color:fontColor}">
|
||||
{{ city || '选择' }}
|
||||
<u-icon name="arrow-down-fill" class="choseIcon" size="15" :color="fontColor" :style="{marginLeft:'2rpx'}" />
|
||||
</view>
|
||||
<view class="search-input" @click="$emit('search')">
|
||||
<u-icon v-if="searchIconShowLeft" name="search" size="40" :color="fontColor" class="search-icon-left" />
|
||||
<text class="placeholder" :style="{fontSize:fontSize,color:fontColor}">{{ placeholder }}</text>
|
||||
<u-icon v-if="!searchIconShowLeft" name="search" size="40" :color="fontColor" class="search-icon-right" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'SearchBar',
|
||||
props: {
|
||||
city: {
|
||||
type: String,
|
||||
default: '宜昌市'
|
||||
},
|
||||
showChoseCity: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
fontSize: {
|
||||
type: String,
|
||||
default: '30rpx'
|
||||
},
|
||||
searchIconShowLeft: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
fontColor:{
|
||||
type: String,
|
||||
default: '#FFFFFF'
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: 'rgba(255,255,255,0.6)' ,
|
||||
},
|
||||
border: {
|
||||
type: String,
|
||||
default: 'border: 1px solid #FFFFFF' ,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '搜索小区/城市/门店'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.choseIcon {
|
||||
margin-left: 5rpx;
|
||||
}
|
||||
.search-bar {
|
||||
margin-top: 10rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 10rpx;
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
.location-chose {
|
||||
font-family: Noto Sans S Chinese;
|
||||
font-weight: 400;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
height: 83.5rpx;
|
||||
padding: 25rpx 30rpx;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
font-family: Noto Sans S Chinese;
|
||||
font-weight: 400;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.search-icon-right {
|
||||
|
||||
}
|
||||
|
||||
.search-icon-left {
|
||||
margin-right: 5%;
|
||||
}
|
||||
</style>
|
||||
4
main.js
@@ -26,7 +26,6 @@ Vue.mixin(mpShare)
|
||||
Vue.component('customNavbar', customNavbar)
|
||||
Vue.component('AuthLogin', AuthLogin)
|
||||
Vue.component('PhoneSelect', PhoneSelect)
|
||||
|
||||
const app = new Vue({
|
||||
store,
|
||||
...App
|
||||
@@ -34,8 +33,9 @@ const app = new Vue({
|
||||
|
||||
// http拦截器,将此部分放在new Vue()和app.$mount()之间,才能App.vue中正常使用
|
||||
import httpInterceptor from '@/common/http.interceptor.js';
|
||||
Vue.use(httpInterceptor, app);
|
||||
// 挂载自定义 http 封装
|
||||
|
||||
Vue.use(httpInterceptor, app);
|
||||
// 封装自定义提示框
|
||||
import $mytip from 'common/utils/tip.js'
|
||||
Vue.prototype.$mytip = $mytip
|
||||
|
||||
19
node_modules/.vue-global-types/vue_2.6_0.d.ts
generated
vendored
@@ -1,13 +1,13 @@
|
||||
// @ts-nocheck
|
||||
export {};
|
||||
|
||||
; declare module 'vue' {
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents { }
|
||||
export interface GlobalDirectives { }
|
||||
}
|
||||
; declare global {
|
||||
declare global {
|
||||
var __VLS_PROPS_FALLBACK: Record<string, unknown>;
|
||||
|
||||
const __VLS_directiveBindingRestFields: { instance: null, oldValue: null, modifiers: any, dir: any };
|
||||
const __VLS_unref: typeof import('vue').unref;
|
||||
const __VLS_placeholder: any;
|
||||
const __VLS_intrinsics: globalThis.JSX.IntrinsicElements;
|
||||
|
||||
@@ -17,7 +17,7 @@ export {};
|
||||
type __VLS_IsAny<T> = 0 extends 1 & T ? true : false;
|
||||
type __VLS_PickNotAny<A, B> = __VLS_IsAny<A> extends true ? B : A;
|
||||
type __VLS_SpreadMerge<A, B> = Omit<A, keyof B> & B;
|
||||
type __VLS_WithComponent<N0 extends string, LocalComponents, Self, N1 extends string, N2 extends string, N3 extends string> =
|
||||
type __VLS_WithComponent<N0 extends string, LocalComponents, Self, N1 extends string, N2 extends string = N1, N3 extends string = N1> =
|
||||
N1 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N1] } :
|
||||
N2 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N2] } :
|
||||
N3 extends keyof LocalComponents ? { [K in N0]: LocalComponents[N3] } :
|
||||
@@ -39,7 +39,7 @@ export {};
|
||||
attrs?: any;
|
||||
slots?: T extends { $slots: infer Slots } ? Slots : Record<string, any>;
|
||||
emit?: T extends { $emit: infer Emit } ? Emit : {};
|
||||
props?: (T extends { $props: infer Props } ? Props : {}) & Record<string, unknown>;
|
||||
props?: typeof props;
|
||||
expose?: (exposed: T) => void;
|
||||
};
|
||||
};
|
||||
@@ -99,12 +99,7 @@ export {};
|
||||
type __VLS_ResolveDirectives<T> = {
|
||||
[K in keyof T & string as `v${Capitalize<K>}`]: T[K];
|
||||
};
|
||||
type __VLS_PrettifyGlobal<T> = { [K in keyof T as K]: T[K]; } & {};
|
||||
type __VLS_WithDefaultsGlobal<P, D> = {
|
||||
[K in keyof P as K extends keyof D ? K : never]-?: P[K];
|
||||
} & {
|
||||
[K in keyof P as K extends keyof D ? never : K]: P[K];
|
||||
};
|
||||
type __VLS_PrettifyGlobal<T> = (T extends any ? { [K in keyof T]: T[K]; } : { [K in keyof T as K]: T[K]; }) & {};
|
||||
type __VLS_UseTemplateRef<T> = Readonly<import('vue').ShallowRef<T | null>>;
|
||||
type __VLS_ProxyRefs<T> = import('vue').ShallowUnwrapRef<T>;
|
||||
|
||||
|
||||
11
node_modules/.vue-global-types/vue_99_0.d.ts
generated
vendored
@@ -2,13 +2,14 @@
|
||||
export {};
|
||||
|
||||
; declare global {
|
||||
var __VLS_PROPS_FALLBACK: Record<string, unknown>;
|
||||
|
||||
const __VLS_directiveBindingRestFields: { instance: null, oldValue: null, modifiers: any, dir: any };
|
||||
const __VLS_unref: typeof import('vue').unref;
|
||||
const __VLS_placeholder: any;
|
||||
const __VLS_intrinsics: import('vue/jsx-runtime').JSX.IntrinsicElements;
|
||||
|
||||
type __VLS_NativeElements = __VLS_SpreadMerge<SVGElementTagNameMap, HTMLElementTagNameMap>;
|
||||
type __VLS_IntrinsicElements = import('vue/jsx-runtime').JSX.IntrinsicElements;
|
||||
type __VLS_Element = import('vue/jsx-runtime').JSX.Element;
|
||||
type __VLS_Elements = __VLS_SpreadMerge<SVGElementTagNameMap, HTMLElementTagNameMap>;
|
||||
type __VLS_GlobalComponents = import('vue').GlobalComponents;
|
||||
type __VLS_GlobalDirectives = import('vue').GlobalDirectives;
|
||||
type __VLS_IsAny<T> = 0 extends 1 & T ? true : false;
|
||||
@@ -31,12 +32,12 @@ export {};
|
||||
? K extends { __ctx?: { props?: infer P } } ? NonNullable<P> : never
|
||||
: T extends (props: infer P, ...args: any) => any ? P
|
||||
: {};
|
||||
type __VLS_FunctionalComponent<T> = (props: (T extends { $props: infer Props } ? Props : {}) & Record<string, unknown>, ctx?: any) => __VLS_Element & {
|
||||
type __VLS_FunctionalComponent<T> = (props: (T extends { $props: infer Props } ? Props : {}) & Record<string, unknown>, ctx?: any) => import('vue/jsx-runtime').JSX.Element & {
|
||||
__ctx?: {
|
||||
attrs?: any;
|
||||
slots?: T extends { $slots: infer Slots } ? Slots : Record<string, any>;
|
||||
emit?: T extends { $emit: infer Emit } ? Emit : {};
|
||||
props?: (T extends { $props: infer Props } ? Props : {}) & Record<string, unknown>;
|
||||
props?: typeof props;
|
||||
expose?: (exposed: T) => void;
|
||||
};
|
||||
};
|
||||
|
||||
10
pages.json
@@ -6,8 +6,8 @@
|
||||
{
|
||||
"path": "pages/index/index",
|
||||
"style": {
|
||||
"navigationStyle": "default" ,// 隐藏系统导航栏
|
||||
"navigationBarTitleText": "首页",
|
||||
"navigationStyle": "custom" ,// 隐藏系统导航栏
|
||||
"navigationBarTitleText": "启辰资产",
|
||||
"enablePullDownRefresh": true,
|
||||
"app-plus": {
|
||||
"pullToRefresh": {
|
||||
@@ -166,7 +166,7 @@
|
||||
|
||||
},
|
||||
{
|
||||
"path" : "pages/content/content",
|
||||
"path" : "pages/notice/noticeDetail",
|
||||
"style": {
|
||||
"navigationStyle": "custom" ,// 隐藏系统导航栏
|
||||
"navigationBarTitleText": "资讯"
|
||||
@@ -226,9 +226,9 @@
|
||||
"path" : "pages/search/searchList",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText": "房源列表",
|
||||
"navigationBarTitleText": "资产列表",
|
||||
"enablePullDownRefresh": true,
|
||||
// "navigationStyle": "custom" ,// 隐藏系统导航栏
|
||||
"navigationStyle": "custom" ,// 隐藏系统导航栏
|
||||
"app-plus": {
|
||||
"pullToRefresh": {
|
||||
"support": true,
|
||||
|
||||
0
pages/auth/company.vue
Normal file
0
pages/auth/person.vue
Normal file
@@ -4,10 +4,9 @@
|
||||
<view class="user-header u-flex u-p-30">
|
||||
<u-avatar :src="avatar" size="100"></u-avatar>
|
||||
<view class="user-info u-m-l-20">
|
||||
<!-- <view class="u-font-18 u-m-b-10">{{ userName }}</view> -->
|
||||
<view class="u-font-18 u-m-b-10">吴康桥</view>
|
||||
<view class="user-tag">用户类型: 个人</view>
|
||||
<view class="user-tag">系统认证:已认证</view>
|
||||
<view class="u-font-18 u-m-b-10">{{vuex_user.nickName}}</view>
|
||||
<view class="user-tag">用户类型: {{userType === '0' ? '个人' : '组织'}}</view>
|
||||
<view class="user-tag">系统认证:{{oaAuth === '1' ? '已认证' : '未认证'}}</view>
|
||||
</view>
|
||||
<view class="msg-setting">
|
||||
<view class="u-relative u-m-r-20" @click="toMessage()">
|
||||
@@ -35,7 +34,7 @@
|
||||
</u-row>
|
||||
<view class="vip-upgrade-btn" @click="upgrade">超值优惠 升级立享</view>
|
||||
</view> -->
|
||||
|
||||
<view class="user-content">
|
||||
<!-- 功能网格 -->
|
||||
<!-- <view class="function-grid u-m-t-30">
|
||||
<u-grid :col="4" :border="false">
|
||||
@@ -108,7 +107,8 @@
|
||||
<u-col span="3" text-align="center" v-for="(item,index) in gridList" :key="index">
|
||||
<view v-if="item.name=='问题反馈'">
|
||||
<!-- 调用微信反馈功能 -->
|
||||
<button type="default" open-type="feedback" class="clearBtn" hover-class="none" style="background-color: #FFFFFF;">
|
||||
<button type="default" open-type="feedback" class="clearBtn" hover-class="none"
|
||||
style="background-color: #FFFFFF;">
|
||||
<u-icon :name="item.icon" color="#909399" size="50"></u-icon>
|
||||
<view class="tabName" style="padding-top: 15rpx;">{{item.name}}</view>
|
||||
</button>
|
||||
@@ -127,25 +127,102 @@
|
||||
|
||||
<!-- 其他功能列表 -->
|
||||
<view class="other-list u-m-t-20 cell-group">
|
||||
<!-- 功能网格 -->
|
||||
|
||||
<UCellItemPlus
|
||||
<view class="function-grid">
|
||||
<swiper
|
||||
:indicator-dots="true"
|
||||
class="swiper"
|
||||
>
|
||||
<swiper-item>
|
||||
<u-grid :border="false">
|
||||
<u-grid-item
|
||||
:customStyle="{width:220+'rpx',height:220+'rpx'}"
|
||||
v-for="(item, index) in cellList"
|
||||
:index="index"
|
||||
:key="index"
|
||||
:title="item.title"
|
||||
:icon="item.icon"
|
||||
arrow
|
||||
v-if="index < 9"
|
||||
@click="clickNav(item.url)"
|
||||
/>
|
||||
>
|
||||
<!-- <u-icon
|
||||
:customStyle="{paddingTop:20+'rpx'}"
|
||||
:name="item.icon"
|
||||
size="46" color="#333"
|
||||
></u-icon> -->
|
||||
<image :src="item.icon" style="width: 50px;height: 50rpx;" mode="widthFix"></image>
|
||||
<text class="u-font-14 u-m-t-10">{{item.name}}</text>
|
||||
</u-grid-item>
|
||||
</u-grid>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<u-grid :border="false">
|
||||
<u-grid-item
|
||||
:customStyle="{width:220+'rpx',height:220+'rpx'}"
|
||||
v-for="(item, index) in cellList"
|
||||
:index="index + 9"
|
||||
v-if="index >= 9 && index < 18 "
|
||||
:key="index"
|
||||
@click="clickNav(item.url)"
|
||||
>
|
||||
<!-- <u-icon
|
||||
:customStyle="{paddingTop:20+'rpx'}"
|
||||
:name="item.icon"
|
||||
size="46" color="#333"
|
||||
></u-icon> -->
|
||||
<image :src="item.icon" style="width: 50px;height: 50rpx;" mode="widthFix"></image>
|
||||
<text class="u-font-14 u-m-t-10">{{item.name}}</text>
|
||||
</u-grid-item>
|
||||
</u-grid>
|
||||
</swiper-item>
|
||||
<swiper-item>
|
||||
<u-grid :border="false">
|
||||
<u-grid-item
|
||||
:customStyle="{width:220+'rpx',height:220+'rpx'}"
|
||||
v-for="(item, index) in cellList"
|
||||
:index="index + 18"
|
||||
:key="index"
|
||||
@click="clickNav(item.url)"
|
||||
>
|
||||
<!-- <u-icon
|
||||
:customStyle="{paddingTop:20+'rpx'}"
|
||||
:name="item.icon"
|
||||
size="46" color="#333"
|
||||
></u-icon> -->
|
||||
<image :src="item.icon" style="width: 50px;height: 50rpx;" mode="widthFix"></image>
|
||||
<text class="u-font-14 u-m-t-10">{{item.name}}</text>
|
||||
</u-grid-item>
|
||||
</u-grid>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 弹窗 -->
|
||||
<!-- <u-popup v-model="showGetProfile" mode="center" border-radius="20">
|
||||
<view class="popup-content">
|
||||
<view class="title">获取头像</view>
|
||||
<view class="desc">获取微信头像与昵称用于展示</view>
|
||||
|
||||
<button class="auth-btn" @click="getWxProfile">
|
||||
授权获取头像
|
||||
</button>
|
||||
</view>
|
||||
</u-popup> -->
|
||||
|
||||
<!-- <UCellItemPlus v-for="(item, index) in cellList" :key="index" :title="item.name" :icon="item.icon" arrow
|
||||
@click="clickNav(item.url)" /> -->
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UCellItemPlus from "../../components/ucellitem/UCellItemPlus.vue";
|
||||
import config from "@/common/config.js";
|
||||
import UCellItemPlus from "../../components/ucellitem/UCellItemPlus.vue";
|
||||
import config from "@/common/config.js";
|
||||
|
||||
export default {
|
||||
components: { UCellItemPlus },
|
||||
export default {
|
||||
components: {
|
||||
UCellItemPlus
|
||||
},
|
||||
|
||||
data() {
|
||||
const life = uni.getStorageSync('lifeData') || {}
|
||||
@@ -154,17 +231,55 @@ export default {
|
||||
return {
|
||||
user, // user 信息放这里即可
|
||||
show: true,
|
||||
gridList: [
|
||||
{name:"我的合同",icon:"../../static/icon/我的合同.png",url:"pages/center/history"},
|
||||
{name:"我的账单",icon:"../../static/icon/我的账单.png",url:"pages/bill/bill"},
|
||||
{name:"我的待付",icon:"../../static/icon/我的待付.png",url:"pages/unpaid/unpaid"},
|
||||
{name:"水电缴费",icon:"../../static/icon/水电缴费.png",url:"pages/wae/wae"}
|
||||
showGetProfile: false,
|
||||
userType:'',
|
||||
oaAuth:'',
|
||||
gridList: [{
|
||||
name: "我的合同",
|
||||
icon: "/static/icon/sign.png",
|
||||
url: "pages/center/history"
|
||||
},
|
||||
{
|
||||
name: "我的账单",
|
||||
icon: "../../static/icon/账单.png",
|
||||
url: "pages/bill/bill"
|
||||
},
|
||||
{
|
||||
name: "我的待付",
|
||||
icon: "../../static/icon/待付款.png",
|
||||
url: "pages/unpaid/unpaid"
|
||||
},
|
||||
{
|
||||
name: "水电缴费",
|
||||
icon: "../../static/icon/水电费.png",
|
||||
url: "pages/wae/wae"
|
||||
}
|
||||
],
|
||||
cellList: [
|
||||
{title:"我的租赁资产",icon:"star",url:"pages/center/myLease"},
|
||||
{title:"我的预约",icon:"star",url:"pages/reserve/reserveRecords"},
|
||||
{title:"缴费记录",icon:"star",url:"pages/bill/payHistory"},
|
||||
{title:"水电费明细",icon:"star",url:"pages/wae/waeRecords"}
|
||||
cellList: [{
|
||||
name: "我的租赁资产",
|
||||
icon: "/static/icon/住房C.png",
|
||||
url: "pages/center/myLease"
|
||||
},
|
||||
{
|
||||
name: "我的预约",
|
||||
icon: "/static/icon/预约.png",
|
||||
url: "pages/reserve/reserveRecords"
|
||||
},
|
||||
{
|
||||
name: "缴费记录",
|
||||
icon: "/static/icon/账本.png",
|
||||
url: "pages/bill/payHistory"
|
||||
},
|
||||
{
|
||||
name: "水电费明细",
|
||||
icon: "/static/icon/书签.png",
|
||||
url: "pages/wae/waeRecords"
|
||||
},
|
||||
{
|
||||
name: "留言板",
|
||||
icon: "/static/icon/留言纸.png",
|
||||
url: "pages/wae/waeRecords"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -172,14 +287,14 @@ export default {
|
||||
computed: {
|
||||
avatar() {
|
||||
const life = uni.getStorageSync('lifeData') || {}
|
||||
const user = (life.vuex_user && life.vuex_user.user) || {}
|
||||
const raw = user.avatar || ""
|
||||
const user = life.vuex_user || {}
|
||||
const raw = user.avatarUrl
|
||||
|
||||
if (!raw) return "/static/images/default-avatar.png"
|
||||
if (!raw) return raw
|
||||
|
||||
return raw.includes(config.staticUrl)
|
||||
? raw
|
||||
: config.staticUrl + raw
|
||||
return raw.includes(config.staticUrl) ?
|
||||
raw :
|
||||
config.staticUrl + raw
|
||||
}
|
||||
},
|
||||
|
||||
@@ -195,6 +310,7 @@ export default {
|
||||
|
||||
onShow() {
|
||||
this.checkToken();
|
||||
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -213,7 +329,9 @@ export default {
|
||||
},
|
||||
|
||||
callPhoneNumber() {
|
||||
uni.makePhoneCall({ phoneNumber: "18720989281" });
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: "18720989281"
|
||||
});
|
||||
},
|
||||
|
||||
aboutMe() {
|
||||
@@ -223,28 +341,30 @@ export default {
|
||||
toMyLease() {
|
||||
this.$u.route('/pages/center/myLease')
|
||||
},
|
||||
|
||||
checkToken() {
|
||||
let lifeData = uni.getStorageSync('lifeData') || {};
|
||||
let lifeData = uni.getStorageSync('lifeData');
|
||||
let token = lifeData.vuex_token
|
||||
|
||||
if (!token) {
|
||||
if (!token || token === null || token === undefined ||
|
||||
(typeof token === 'object' && Object.keys(token).length === 0)) {
|
||||
console.log("登录态不存在")
|
||||
return uni.reLaunch({ url:'../login/login' })
|
||||
return uni.reLaunch({
|
||||
url: '../login/login'
|
||||
})
|
||||
}
|
||||
|
||||
let url = "/api/profile/isExpiration";
|
||||
this.$u.get(url,{ token }).then(obj => {
|
||||
if(obj.data){
|
||||
return uni.reLaunch({ url:'../login/login' })
|
||||
let url = "/login/checkExpiration";
|
||||
this.$u.get(url, {}, {'WT': token}).then(obj => {
|
||||
if (obj.data) {
|
||||
uni.reLaunch({
|
||||
url: '../login/login'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
clickNav(url){
|
||||
if(url){
|
||||
clickNav(url) {
|
||||
if (url) {
|
||||
this.$u.route(url);
|
||||
}else{
|
||||
} else {
|
||||
this.$mytip.toast('敬请期待')
|
||||
}
|
||||
},
|
||||
@@ -252,71 +372,143 @@ export default {
|
||||
updateAvatar() {
|
||||
// 触发 computed 自动更新
|
||||
this.$forceUpdate()
|
||||
},
|
||||
// 进入个人中心时判断是否需要补充资料
|
||||
checkNeedProfile() {
|
||||
let life = uni.getStorageSync('lifeData') || {}
|
||||
let user = life.vuex_user
|
||||
let token = life.vuex_token
|
||||
if (!token) return; // 未登录不弹窗
|
||||
// 没有头像或昵称才弹窗
|
||||
if (!user || !user.avatarUrl || !user.nickName) {
|
||||
this.showGetProfile = true;
|
||||
}
|
||||
},
|
||||
getWxProfile() {
|
||||
uni.getUserProfile({
|
||||
desc: "用于完善个人资料展示",
|
||||
success: res => {
|
||||
const userInfo = res.userInfo;
|
||||
// 存储
|
||||
this.$u.vuex('vuex_user', userInfo);
|
||||
|
||||
// 也可同步调用后端更新头像昵称
|
||||
// this.$u.post('/user/updateWxInfo', userInfo);
|
||||
|
||||
this.showGetProfile = false;
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
title: "授权失败",
|
||||
icon: "none"
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
getUserOtherInfo() {
|
||||
let life = uni.getStorageSync('lifeData') || {}
|
||||
let token = life.vuex_token
|
||||
let url = "/login/userOtherInfo";
|
||||
this.$u.get(url, {}, {'WT': token}).then(obj => {
|
||||
this.userType = obj.data.userType;
|
||||
this.oaAuth = obj.data.oaAuth;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.swiper {
|
||||
height: 400rpx;
|
||||
height: 700rpx;
|
||||
}
|
||||
.user-center {
|
||||
|
||||
.user-center {
|
||||
background-color: #f7f8fa;
|
||||
min-height: 100vh;
|
||||
padding: 15rpx;
|
||||
}
|
||||
.center-nav{
|
||||
}
|
||||
|
||||
.user-content{
|
||||
padding: 0 20rpx 20rpx 20rpx;
|
||||
position: relative; /* 相对定位不会脱流,仅创建一个 z-index 环境 */
|
||||
z-index: 1;
|
||||
margin: 0 20rpx;
|
||||
margin-top: 12rpx; /* 视觉上插入到延伸背景中,调节数值以适配 */
|
||||
|
||||
}
|
||||
.center-nav {
|
||||
background-color: #FFFFFF;
|
||||
margin-top: 30rpx;
|
||||
padding: 30rpx 0;
|
||||
border-radius: 8px;
|
||||
.tabName{
|
||||
color: #606266;
|
||||
|
||||
.tabName {
|
||||
color: black;
|
||||
font-size: 26rpx;
|
||||
padding-top: 10rpx;
|
||||
}
|
||||
}
|
||||
.cell-group {
|
||||
}
|
||||
|
||||
.cell-group {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.cell-group > view:not(:last-child) {
|
||||
}
|
||||
|
||||
.cell-group>view:not(:last-child) {
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
/* 用户信息卡 */
|
||||
.user-header {
|
||||
}
|
||||
|
||||
/* 用户信息卡 */
|
||||
.user-header {
|
||||
align-items: center;
|
||||
margin-top: 200rpx;
|
||||
position: relative;
|
||||
padding-top: 200rpx !important;
|
||||
padding-bottom: 80rpx !important;
|
||||
background: linear-gradient(to right, #89CFF0, #5AA4D1);
|
||||
overflow: visible; /* 必须,否则延伸区域会被裁掉 */
|
||||
.user-info {
|
||||
|
||||
.user-tag {
|
||||
background: #f6f6f6;
|
||||
color: #ff8c00;
|
||||
color: black;
|
||||
padding: 8rpx 12rpx;
|
||||
border-radius: 8rpx;
|
||||
font-size: 24rpx;
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
.msg-setting {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
right: 85rpx;
|
||||
}
|
||||
}
|
||||
.user-header::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: -80rpx;
|
||||
height: 80rpx;
|
||||
background: inherit;
|
||||
border-bottom-left-radius: 40rpx;
|
||||
border-bottom-right-radius: 40rpx;
|
||||
/* 把伪元素放在 header 背景后面 */
|
||||
z-index: 0;
|
||||
}
|
||||
.vip-card {
|
||||
.vip-card {
|
||||
margin: 20rpx;
|
||||
padding: 30rpx;
|
||||
background: linear-gradient(135deg, #1f1f1f 0%, #2a2a2a 100%);
|
||||
border-radius: 20rpx;
|
||||
color: #fff;
|
||||
|
||||
.vip-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #f8e28e;
|
||||
}
|
||||
|
||||
.vip-upgrade-btn {
|
||||
margin-top: 30rpx;
|
||||
background: linear-gradient(to right, #ffb347, #ffcc33);
|
||||
@@ -326,10 +518,39 @@ export default {
|
||||
border-radius: 40rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.function-grid {
|
||||
}
|
||||
|
||||
.function-grid {
|
||||
margin: 0 20rpx;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-content {
|
||||
padding: 40rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.auth-btn {
|
||||
width: 80%;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
background: linear-gradient(90deg, #4CAF50, #07c160);
|
||||
color: white;
|
||||
line-height: 80rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 34rpx;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -1,46 +1,37 @@
|
||||
<template>
|
||||
|
||||
<view class="contract-page">
|
||||
<!-- 顶部导航栏 -->
|
||||
<customNavbar title="我的合同"/>
|
||||
<!-- 顶部筛选栏 -->
|
||||
<u-tabs
|
||||
:list="tabList"
|
||||
:current="currentTab"
|
||||
@change="onTabChange"
|
||||
lineColor="#2979ff"
|
||||
activeColor="#2979ff"
|
||||
></u-tabs>
|
||||
<customNavbar title="我的合同" />
|
||||
|
||||
<!-- 合同列表 -->
|
||||
<scroll-view
|
||||
scroll-y
|
||||
class="scroll-content"
|
||||
@scrolltolower="loadMore"
|
||||
:refresher-enabled="true"
|
||||
:refresher-triggered="isRefreshing"
|
||||
@refresherrefresh="refresh"
|
||||
>
|
||||
<view v-if="contracts.length > 0" class="contract-list">
|
||||
<view
|
||||
class="contract-card"
|
||||
v-for="item in contracts"
|
||||
:key="item.id"
|
||||
@click="goDetail(item)"
|
||||
>
|
||||
<!-- 左侧封面图 -->
|
||||
<image
|
||||
class="contract-cover"
|
||||
:src="item.coverUrl || defaultCover"
|
||||
mode="aspectFill"
|
||||
<!-- Tabs -->
|
||||
<view class="tab-wrapper">
|
||||
<u-tabs :list="tabList" :current="currentTab" @change="onTabChange" lineColor="#2979ff"
|
||||
activeColor="#2979ff" itemStyle="padding: 0 30rpx;"></u-tabs>
|
||||
</view>
|
||||
|
||||
|
||||
<DateFilter
|
||||
:start="startDate"
|
||||
:end="endDate"
|
||||
@update:start="startDate = $event"
|
||||
@update:end="endDate = $event"
|
||||
@change="onDateFilterChange"
|
||||
/>
|
||||
|
||||
<!-- 右侧信息 -->
|
||||
<!-- 合同列表 -->
|
||||
<scroll-view scroll-y class="scroll-content" @scrolltolower="loadMore" :refresher-enabled="true"
|
||||
:refresher-triggered="isRefreshing" @refresherrefresh="refresh">
|
||||
<view v-if="contracts.length > 0" class="contract-list">
|
||||
<view class="contract-card" v-for="item in contracts" :key="item.id" @click="goDetail(item)">
|
||||
<image class="contract-cover" :src="item.coverUrl || defaultCover" mode="aspectFill" />
|
||||
|
||||
<view class="contract-info">
|
||||
<view class="top-row">
|
||||
<text class="asset-name">{{ item.assetName }}</text>
|
||||
<u-icon name="arrow-right" size="28" color="#ccc" />
|
||||
</view>
|
||||
<view class="asset-room">{{ item.assetRoom || '—' }}</view>
|
||||
<view class="asset-room">{{ item.assetRoom || "—" }}</view>
|
||||
<view class="date-range">{{ item.startDate }} ~ {{ item.endDate }}</view>
|
||||
|
||||
<view :class="['status-tag', item.status]">
|
||||
@@ -56,51 +47,94 @@
|
||||
<u-empty mode="list" text="暂无合同记录" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default {
|
||||
import DateFilter from '../../components/DatePicker/DateFilter.vue';
|
||||
export default {
|
||||
components: { DateFilter },
|
||||
data() {
|
||||
return {
|
||||
tabList: [
|
||||
{ name: '全部', value: 'all' },
|
||||
{ name: '待签署', value: 'pending' },
|
||||
{ name: '已签署', value: 'signed' },
|
||||
{ name: '已过期', value: 'expired' }
|
||||
tabList: [{
|
||||
name: "全部",
|
||||
value: "all"
|
||||
},
|
||||
{
|
||||
name: "待签署",
|
||||
value: "pending"
|
||||
},
|
||||
{
|
||||
name: "已签署",
|
||||
value: "signed"
|
||||
},
|
||||
{
|
||||
name: "已过期",
|
||||
value: "expired"
|
||||
},
|
||||
],
|
||||
currentTab: 0,
|
||||
statusFilter: 'all',
|
||||
|
||||
currentTab: 0,
|
||||
statusFilter: "all",
|
||||
|
||||
// --- 时间筛选 ---
|
||||
startDate: "",
|
||||
endDate: "",
|
||||
// 可选:限制日期范围
|
||||
minDate: "2000-01-01",
|
||||
maxDate: "2099-12-31",
|
||||
contracts: [],
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
loadStatus: 'loadmore',
|
||||
total: 0,
|
||||
loadStatus: "loadmore",
|
||||
isRefreshing: false,
|
||||
defaultCover: '/static/img/index/swiper/swiper3.jpg' // 可换成你的默认封面
|
||||
defaultCover: "/static/img/index/swiper/swiper3.jpg",
|
||||
};
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.loadContracts();
|
||||
this.loadContracts(true);
|
||||
},
|
||||
|
||||
methods: {
|
||||
onTabChange(index) {
|
||||
this.currentTab = index;
|
||||
this.statusFilter = this.tabList[index].value;
|
||||
this.pageNo = 1;
|
||||
this.contracts = [];
|
||||
this.loadContracts();
|
||||
this.resetAndLoad();
|
||||
},
|
||||
onDateFilterChange({ start, end }) {
|
||||
this.resetAndLoad();
|
||||
},
|
||||
|
||||
loadContracts() {
|
||||
this.loadStatus = 'loading';
|
||||
formatDate(time) {
|
||||
const d = new Date(time);
|
||||
const m = String(d.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(d.getDate()).padStart(2, "0");
|
||||
return `${d.getFullYear()}-${m}-${day}`;
|
||||
},
|
||||
|
||||
resetAndLoad() {
|
||||
this.pageNo = 1;
|
||||
this.contracts = [];
|
||||
this.loadStatus = "loading";
|
||||
this.loadContracts(true);
|
||||
},
|
||||
|
||||
/** 你的 loadContracts() 保持不变,只需加:按时间筛选 */
|
||||
loadContracts(isInit = false) {
|
||||
this.loadStatus = "loading";
|
||||
|
||||
setTimeout(() => {
|
||||
const allData = [
|
||||
{
|
||||
let mockAll = [{
|
||||
id: 1,
|
||||
assetName: '金辉大厦',
|
||||
assetRoom: '502',
|
||||
coverUrl: '/static/img/index/swiper/swiper3.jpg',
|
||||
coverUrl: '',
|
||||
status: 'pending',
|
||||
startDate: '2025-01-01',
|
||||
endDate: '2025-12-31'
|
||||
@@ -109,7 +143,6 @@ export default {
|
||||
id: 2,
|
||||
assetName: '东方广场',
|
||||
assetRoom: '',
|
||||
coverUrl: '/static/img/index/swiper/swiper3.jpg',
|
||||
status: 'signed',
|
||||
startDate: '2024-03-01',
|
||||
endDate: '2025-03-01'
|
||||
@@ -118,75 +151,101 @@ export default {
|
||||
id: 3,
|
||||
assetName: '海景公寓',
|
||||
assetRoom: 'A-1201',
|
||||
coverUrl: '/static/img/index/swiper/swiper3.jpg',
|
||||
status: 'expired',
|
||||
startDate: '2023-01-01',
|
||||
endDate: '2024-01-01'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
assetName: '富力中心',
|
||||
assetRoom: '1699',
|
||||
status: 'pending',
|
||||
startDate: '2024-10-01',
|
||||
endDate: '2025-10-01'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
assetName: '财富大厦',
|
||||
assetRoom: '2308',
|
||||
status: 'signed',
|
||||
startDate: '2023-06-01',
|
||||
endDate: '2024-06-01'
|
||||
}
|
||||
];
|
||||
|
||||
const filtered =
|
||||
this.statusFilter === 'all'
|
||||
? allData
|
||||
: allData.filter(i => i.status === this.statusFilter);
|
||||
// 状态过滤
|
||||
if (this.statusFilter !== "all") {
|
||||
mockAll = mockAll.filter(i => i.status === this.statusFilter);
|
||||
}
|
||||
|
||||
this.contracts = filtered;
|
||||
this.loadStatus = 'nomore';
|
||||
// 时间过滤
|
||||
if (this.startDate) mockAll = mockAll.filter(i => i.startDate >= this.startDate);
|
||||
if (this.endDate) mockAll = mockAll.filter(i => i.endDate <= this.endDate);
|
||||
|
||||
// 分页
|
||||
this.total = mockAll.length;
|
||||
const start = (this.pageNo - 1) * this.pageSize;
|
||||
const pageList = mockAll.slice(start, start + this.pageSize);
|
||||
|
||||
if (this.pageNo === 1) {
|
||||
this.contracts = pageList;
|
||||
} else {
|
||||
this.contracts = [...this.contracts, ...pageList];
|
||||
}
|
||||
|
||||
this.loadStatus = this.contracts.length >= this.total ? "nomore" : "loadmore";
|
||||
this.isRefreshing = false;
|
||||
}, 400);
|
||||
},
|
||||
|
||||
refresh() {
|
||||
this.isRefreshing = true;
|
||||
this.pageNo = 1;
|
||||
this.loadContracts();
|
||||
this.resetAndLoad();
|
||||
},
|
||||
|
||||
loadMore() {
|
||||
if (this.loadStatus === 'nomore') return;
|
||||
if (this.loadStatus !== "loadmore") return;
|
||||
this.pageNo++;
|
||||
this.loadContracts();
|
||||
},
|
||||
|
||||
goDetail(item) {
|
||||
console.log('跳转合同详情页')
|
||||
uni.navigateTo({
|
||||
url: `/pages/detail/contractDetail?id=${item.id}`
|
||||
url: `/pages/detail/contractDetail?id=${item.id}`,
|
||||
});
|
||||
},
|
||||
|
||||
getStatusText(status) {
|
||||
switch (status) {
|
||||
case 'pending':
|
||||
return '待签署';
|
||||
case 'signed':
|
||||
return '已签署';
|
||||
case 'expired':
|
||||
return '已过期';
|
||||
default:
|
||||
return '';
|
||||
case "pending":
|
||||
return "待签署";
|
||||
case "signed":
|
||||
return "已签署";
|
||||
case "expired":
|
||||
return "已过期";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.contract-page {
|
||||
.contract-page {
|
||||
background-color: #f8f8f8;
|
||||
padding-top: 175rpx; /* 给导航栏留空间 */
|
||||
padding-top: 175rpx;
|
||||
/* 给导航栏留空间 */
|
||||
min-height: 100vh;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-content {
|
||||
.scroll-content {
|
||||
height: calc(100vh - 100rpx);
|
||||
}
|
||||
}
|
||||
|
||||
.contract-list {
|
||||
.contract-list {
|
||||
padding: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.contract-card {
|
||||
.contract-card {
|
||||
display: flex;
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
@@ -194,49 +253,50 @@ export default {
|
||||
padding: 20rpx;
|
||||
box-shadow: 0 4rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.contract-cover {
|
||||
.contract-cover {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 12rpx;
|
||||
background-color: #f0f0f0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.contract-info {
|
||||
.contract-info {
|
||||
flex: 1;
|
||||
margin-left: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.top-row {
|
||||
.top-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.asset-name {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.asset-room {
|
||||
.asset-room {
|
||||
font-size: 26rpx;
|
||||
color: #555;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.date-range {
|
||||
.date-range {
|
||||
font-size: 24rpx;
|
||||
color: #888;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
.status-tag {
|
||||
position: absolute;
|
||||
bottom: 10rpx;
|
||||
right: 0rpx;
|
||||
@@ -248,17 +308,29 @@ export default {
|
||||
background: #fff8e1;
|
||||
color: #ff9800;
|
||||
}
|
||||
|
||||
&.signed {
|
||||
background: #e8f5e9;
|
||||
color: #4caf50;
|
||||
}
|
||||
|
||||
&.expired {
|
||||
background: #fbe9e7;
|
||||
color: #e53935;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty {
|
||||
.empty {
|
||||
margin-top: 200rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-wrapper {
|
||||
background-color: #ffffff;
|
||||
padding: 10rpx 0;
|
||||
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.06);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -2,40 +2,28 @@
|
||||
<view class="asset-detail">
|
||||
<!-- 顶部导航栏 -->
|
||||
<customNavbar
|
||||
title="不动资产详情"
|
||||
></customNavbar>
|
||||
title="不动资产详情" ref="navbar"/>
|
||||
<!-- 顶部信息块 -->
|
||||
<view class="top-block u-flex u-row-between u-p-20">
|
||||
<!-- 左侧轮播图 -->
|
||||
<view class="left-swiper">
|
||||
<u-swiper
|
||||
<view :style="{ paddingTop: navTotalHeight + 'px' }">
|
||||
<!-- <u-swiper
|
||||
:list="asset.images"
|
||||
height="220"
|
||||
border-radius="12"
|
||||
autoplay
|
||||
interval="3000"
|
||||
></u-swiper>
|
||||
</view>
|
||||
></u-swiper> -->
|
||||
<AssetGallery
|
||||
:insideImages="asset.images"
|
||||
:vrImage="asset.vrImage"
|
||||
:vrSrc="asset.vr"
|
||||
:videos="asset.videos"
|
||||
:plans="asset.plans"
|
||||
:adImage="asset.adImage"
|
||||
@vr-click="viewVR"
|
||||
@video-play="playVideo"
|
||||
@ad-click="onAdClick"
|
||||
/>
|
||||
|
||||
<!-- 右侧信息块 -->
|
||||
<view class="right-info u-flex u-flex-col u-justify-between">
|
||||
<view>
|
||||
<view class="asset-name">{{ asset.name }}</view>
|
||||
<view class="asset-community">所属小区:{{ asset.community }}</view>
|
||||
<view class="asset-rent">租金:<text class="price">¥{{ formatMoney(asset.rent) }}/月</text></view>
|
||||
</view>
|
||||
|
||||
<view class="btn-group">
|
||||
<u-button
|
||||
size="mini"
|
||||
type="primary"
|
||||
icon="map"
|
||||
@click="viewVR"
|
||||
>
|
||||
查看VR图
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="content">
|
||||
@@ -93,17 +81,18 @@
|
||||
<script>
|
||||
import mycard from '../../components/card/mycard.vue';
|
||||
import assetBottomBar from '../../components/bottom/assetBottomBar.vue';
|
||||
|
||||
import AssetGallery from '../../components/gallery/AssetGallery.vue'
|
||||
export default {
|
||||
components:{
|
||||
mycard,
|
||||
assetBottomBar
|
||||
assetBottomBar,
|
||||
AssetGallery
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 控制预约弹窗显示
|
||||
showReserve: false,
|
||||
|
||||
navTotalHeight: 0,
|
||||
// 预约表单数据
|
||||
reserveName: '',
|
||||
reservePhone: '',
|
||||
@@ -131,6 +120,13 @@ export default {
|
||||
onLoad(options) {
|
||||
this.assetId = options.id || 'A001';
|
||||
this.loadAssetDetail();
|
||||
// this.recordView();
|
||||
},
|
||||
mounted() {
|
||||
const navbar = this.$refs.navbar;
|
||||
const navHeight = navbar.navContentHeight; // 直接拿子组件 data
|
||||
this.navTotalHeight = navHeight; // 加上额外间距
|
||||
|
||||
},
|
||||
methods: {
|
||||
// 模拟接口请求
|
||||
@@ -150,12 +146,15 @@ export default {
|
||||
lat: 23.135,
|
||||
lng: 113.327,
|
||||
images: [
|
||||
'https://cdn.uviewui.com/uview/swiper/swiper1.png',
|
||||
'https://cdn.uviewui.com/uview/swiper/swiper2.png',
|
||||
{
|
||||
image:'/static/img/index/swiper/swiper3.jpg'
|
||||
}
|
||||
|
||||
|
||||
],
|
||||
remark: '该资产目前用于办公出租,维护状态良好。',
|
||||
isFavorite: false,
|
||||
status: 1
|
||||
status: 0
|
||||
};
|
||||
this.markers = [
|
||||
{
|
||||
@@ -192,6 +191,14 @@ export default {
|
||||
submitReserve (){
|
||||
console.log('提交预约看房申请')
|
||||
this.showReserve = false;
|
||||
},
|
||||
recordView(assetId) {
|
||||
let lifeData = uni.getStorageSync('lifeData');
|
||||
let token = lifeData.vuex_token
|
||||
let url = "/assets/viewRecord";
|
||||
this.$u.get(url, {}, {'WT': token}).then(obj => {
|
||||
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,120 +1,134 @@
|
||||
<template>
|
||||
<view class="u-p-l-10 u-p-r-10 index">
|
||||
|
||||
<!-- 流量主-腾讯banner广告 -->
|
||||
<view>
|
||||
<!-- <ad unit-id="adunit-fcfdcc4d7095b6b1" ad-intervals="30"></ad> -->
|
||||
<!-- 轮播图 -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<!-- <u-swiper :list="swiperList" height="350"></u-swiper> -->
|
||||
<!-- #endif -->
|
||||
<u-swiper :list="swiperList" height="350" @click="moreInfo"></u-swiper>
|
||||
<view class="index">
|
||||
<image src="/static/index/index_bg.png" mode="aspectFill" class="bg"></image>
|
||||
<!-- 搜索栏 -->
|
||||
<view class="index-title">
|
||||
启辰资产
|
||||
</view>
|
||||
<view class="content-wrapper">
|
||||
|
||||
<view class="search-wrapper">
|
||||
<search-bar
|
||||
:city="vuex_city==''?'选择':vuex_city"
|
||||
placeholder="你想住在哪儿"
|
||||
@chooseCity="location"
|
||||
@search="search"
|
||||
/>
|
||||
</view>
|
||||
<!-- 房源信息导航栏 -->
|
||||
<view>
|
||||
<view class="nav-area">
|
||||
<view class="rowClass">
|
||||
<u-row>
|
||||
<u-col span="3" text-align="center" v-for="(item,index) in navList" :key="index">
|
||||
<view class="u-padding-20" @tap="clickNav(item, index)" hover-class="hoverClass">
|
||||
<image :src="item.src" style="width: 130rpx;height: 130rpx;" mode="widthFix"></image>
|
||||
<view class="tabName">{{item.name}}</view>
|
||||
<!-- 点击后出现下划线 -->
|
||||
<view
|
||||
v-if="activeIndex === index"
|
||||
class="underline"
|
||||
:style="{ background: item.underline_color }"
|
||||
></view>
|
||||
<image :src="item.src" style="width: 86rpx;height: 86rpx;" mode="heightFix"></image>
|
||||
<view class="tabName" :style="{color:'#FFFFFF'}">{{item.name}}</view>
|
||||
</view>
|
||||
</u-col>
|
||||
</u-row>
|
||||
<!-- 下划线(动态颜色 + 动画滑动) -->
|
||||
<!-- <view
|
||||
class="underline"
|
||||
:style="{
|
||||
transform: `translateX(${activeIndex * 100}%)`,
|
||||
background: navList[activeIndex].underline_color
|
||||
}"
|
||||
></view> -->
|
||||
</view>
|
||||
<view class="rowClass">
|
||||
<view class="rowClass navbox2">
|
||||
<u-row>
|
||||
<u-col span="3" text-align="center" v-for="(item,index) in gridList" :key="index">
|
||||
<view class="u-padding-20" @tap="clickGrid(item)" hover-class="hoverClass">
|
||||
<image :src="item.src" style="width: 110rpx;height: 110rpx;" mode="widthFix"></image>
|
||||
<view class="tabName">{{item.name}}</view>
|
||||
<image :src="item.src" style="width: 50rpx;height: 50rpx;" mode="heightFix"></image>
|
||||
<view class="tabName" :style="{color:'#222222'}">{{item.name}}</view>
|
||||
</view>
|
||||
</u-col>
|
||||
</u-row>
|
||||
</view>
|
||||
<u-gap height="10"></u-gap>
|
||||
<!-- 公告栏 -->
|
||||
<view @click="notice">
|
||||
<u-notice-bar mode="vertical" :list="noticeList" type="primary" more-icon
|
||||
bg-color="#fff" :duration="5000" border-radius="15"></u-notice-bar>
|
||||
</view>
|
||||
<!-- 搜索栏 -->
|
||||
<!-- <u-navbar :is-back="false" :fixed="false" :safeAreaInsetTop="false"> -->
|
||||
<view class="search-bar" style="display: flex;justify-content: center;align-items: center;">
|
||||
<!-- 选择地区 -->
|
||||
<view class="u-p-20 location-chose" @click="location">
|
||||
{{vuex_city==''?'选择':vuex_city}}
|
||||
<u-icon name="arrow-down-fill" class="u-p-l-10" color="#515356"></u-icon>
|
||||
</view>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<u-search placeholder="你想住在哪儿" v-model="keyword" input-align="center" :show-action="false" :clearabled="true"
|
||||
:disabled="true" style="width: 380rpx;" @click="search"></u-search>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN -->
|
||||
<u-search placeholder="你想住在哪儿" v-model="keyword" input-align="center" :show-action="false" :clearabled="true"
|
||||
:disabled="true" style="width: 580rpx;" @click="search"></u-search>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
|
||||
<!-- </u-navbar> -->
|
||||
<u-gap height="10"></u-gap>
|
||||
<!-- 公告栏 -->
|
||||
<view @click="notice" class="noticeStyle">
|
||||
<image src="/static/index/公告.png" style="width: 38rpx;height: 37rpx;"></image>
|
||||
<u-notice-bar mode="vertical" :list="noticeList" type="primary" more-icon
|
||||
bg-color="none" :duration="5000" :fontSize = "30" color="#2D2B2C" :volumeIcon="false"></u-notice-bar>
|
||||
</view>
|
||||
|
||||
<u-gap height="5"></u-gap>
|
||||
<scroll-view
|
||||
scroll-y
|
||||
style="height: 100vh;"
|
||||
:scroll-top="scrollTop"
|
||||
@scrolltolower="findHouseList"
|
||||
lower-threshold="50"
|
||||
>
|
||||
<u-waterfall v-model="flowList" ref="uWaterfall">
|
||||
<template v-slot:left="{leftList}">
|
||||
<view class="demo-warter" v-for="(item, index) in leftList" :key="index">
|
||||
<u-lazy-load threshold="750" border-radius="12" :image="item.coverImgUrl" :index="index"
|
||||
<view class="demo-warter" v-for="(item, index) in leftList" :key="index" style="margin-right: 10rpx;">
|
||||
<u-lazy-load threshold="750" border-radius="12" image="/static/img/index/swiper/swiper3.jpg" :index="index" mode="widthFix"
|
||||
@click="clickImage(item.id)"></u-lazy-load>
|
||||
<view class="item-title">{{item.name}}</view>
|
||||
<view class="item-title">{{ item.assetsName}}</view>
|
||||
<view class="item-desc">{{ item.footPrint}}㎡</view>
|
||||
<view class="item-price">¥{{item.rentFee}}</view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:right="{rightList}">
|
||||
<view class="demo-warter" v-for="(item, index) in rightList" :key="index">
|
||||
<u-lazy-load threshold="750" border-radius="10" :image="item.coverImgUrl" :index="index"
|
||||
<view class="demo-warter" v-for="(item, index) in rightList" :key="index" style="margin-left: 10rpx;">
|
||||
<u-lazy-load threshold="750" border-radius="10" image="/static/img/index/swiper/swiper3.jpg" :index="index" mode="widthFix"
|
||||
@click="clickImage(item.id)"></u-lazy-load>
|
||||
<view class="item-title">{{item.name}}</view>
|
||||
<view class="item-title">{{ item.assetsName}}</view>
|
||||
<view class="item-desc">{{ item.footPrint}}㎡</view>
|
||||
<view class="item-price">¥{{item.rentFee}}</view>
|
||||
</view>
|
||||
</template>
|
||||
</u-waterfall>
|
||||
</scroll-view>
|
||||
|
||||
</view>
|
||||
|
||||
<u-loadmore bg-color="rgb(240, 240, 240)" :status="loadStatus" @loadmore="findHouseList" style="height: 80rpx;line-height: 80rpx;"></u-loadmore>
|
||||
<u-back-top :scroll-top="scrollTop" top="1000"></u-back-top>
|
||||
<u-no-network></u-no-network>
|
||||
<!-- 联系客服 -->
|
||||
<!-- <view class="buttom">
|
||||
<view class="loginType">
|
||||
<view class="wechat item">
|
||||
<view class="icon"><u-icon size="60" name="server-man" color="#999" @click="server"></u-icon></view>
|
||||
|
||||
</view>
|
||||
<u-popup
|
||||
v-model="showFillAuthInfo"
|
||||
mode="center"
|
||||
:mask-close-able="false"
|
||||
border-radius="24"
|
||||
>
|
||||
<view class="auth-popup">
|
||||
<!-- 标题 -->
|
||||
<view class="auth-title">
|
||||
请完善{{authLabel}}信息
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 描述 -->
|
||||
<view class="auth-desc">
|
||||
您当前尚未完善相关信息,为避免影响后续功能使用,请尽快补充。
|
||||
</view>
|
||||
|
||||
<!-- 输入区域 -->
|
||||
<view class="auth-input">
|
||||
<u-input
|
||||
v-model="authCode"
|
||||
:placeholder="authPlaceholder"
|
||||
clearable
|
||||
border="bottom"
|
||||
font-size="30"
|
||||
placeholder-style="color:#bbb"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 按钮 -->
|
||||
<button class="auth-btn" @click="recordAuthInfo">
|
||||
提交
|
||||
</button>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from "@/common/config.js" // 全局配置文件
|
||||
import SearchBar from '../../components/searchBar/SearchBar.vue';
|
||||
import indexNavbarVue from '../../components/navbar/indexNavbar.vue';
|
||||
export default {
|
||||
components: { SearchBar,indexNavbarVue},
|
||||
data() {
|
||||
return {
|
||||
loginType: null,
|
||||
authCode: '', // 身份证号 / 社会信用代码
|
||||
showFillAuthInfo: false,
|
||||
keyword:'',
|
||||
pageNum: 1,
|
||||
pageSize: 20,
|
||||
@@ -131,56 +145,21 @@
|
||||
title: '身无彩凤双飞翼,心有灵犀一点通'
|
||||
},
|
||||
],
|
||||
noticeList: ['伍家岗招租'],
|
||||
noticeList: [],
|
||||
navList:[
|
||||
{name:"保租房",src:"/static/icon/保租房.png",type:"0",underline_color:"linear-gradient(to right, #ff8c00, #ffcc33)"},
|
||||
{name:"商铺",src:"/static/icon/商铺.png",type:"1",underline_color:"linear-gradient(to right, #ff8c00, #ffcc33)"},
|
||||
{name:"厂房",src:"/static/icon/厂房.png",url:"/pages/center/tips",underline_color:"linear-gradient(to right, #ff8c00, #ffcc33)"},
|
||||
{name:"停车场",src:"/static/icon/停车场.png",type:"2",underline_color:"linear-gradient(to right, #ff8c00, #ffcc33)"}
|
||||
{name:"住房",src:"/static/index/住房.png",type:"0",underline_color:"linear-gradient(to right, #ff8c00, #ffcc33)"},
|
||||
{name:"商铺",src:"/static/index/商铺.png",type:"1",underline_color:"linear-gradient(to right, #89CFF0, #5AA4D1)"},
|
||||
{name:"厂房",src:"/static/index/厂房.png",url:"/pages/center/tips",underline_color:"linear-gradient(to right, #0000FF, #800080)"},
|
||||
{name:"停车场",src:"/static/index/停车场.png",type:"2",underline_color:"linear-gradient(to bottom, #000080, #00008080)"}
|
||||
],
|
||||
gridList:[
|
||||
{name:"看房预约",src:"/static/icon/预约看房.png",url:"pages/reserve/reserveRecords"},
|
||||
{name:"合同签约",src:"/static/icon/合同签约.png",url:"pages/center/contract"},
|
||||
{name:"退租申请",src:"/static/icon/退租申请.png",url:"pages/form/leaseCancel"}
|
||||
{name:"看房预约",src:"/static/index/看房预约.png",url:"pages/reserve/reserveRecords"},
|
||||
{name:"合同签约",src:"/static/index/合同签约.png",url:"pages/center/contract"},
|
||||
{name:"退租申请",src:"/static/index/退租申请.png",url:"pages/form/leaseCancel"},
|
||||
{name:"留言板",src:"/static/index/留言板.png",url:"pages/form/leaseCancel"}
|
||||
],
|
||||
loadStatus: 'loadmore',
|
||||
flowList: [
|
||||
{
|
||||
"id":"0001",
|
||||
"name":"测试房屋",
|
||||
"type":"0",
|
||||
"rentFee": "1400",
|
||||
"footPrint": "80",
|
||||
"coverImgUrl":"/static/img/index/swiper/swiper3.jpg"
|
||||
|
||||
},
|
||||
{
|
||||
"id":"0002",
|
||||
"name":"测试房屋",
|
||||
"type":"0",
|
||||
"rentFee": "1400",
|
||||
"footPrint": "80",
|
||||
"coverImgUrl":"/static/img/index/swiper/swiper3.jpg"
|
||||
|
||||
},
|
||||
{
|
||||
"id":"0003",
|
||||
"name":"测试房屋",
|
||||
"type":"0",
|
||||
"rentFee": "1400",
|
||||
"footPrint": "80",
|
||||
"coverImgUrl":"/static/img/index/swiper/swiper3.jpg"
|
||||
|
||||
},
|
||||
{
|
||||
"id":"0001",
|
||||
"name":"测试房屋",
|
||||
"type":"0",
|
||||
"rentFee": "1400",
|
||||
"footPrint": "80",
|
||||
"coverImgUrl":"/static/img/index/swiper/swiper3.jpg"
|
||||
|
||||
}
|
||||
],
|
||||
uvCode: uni.getStorageSync('uvCode')
|
||||
}
|
||||
@@ -192,11 +171,15 @@
|
||||
this.findHouseList();
|
||||
this.getNoticecList();
|
||||
// 流量统计
|
||||
this.appSysFlowInfo();
|
||||
// this.appSysFlowInfo();
|
||||
uni.$on('findIndexHouseList', (obj) => {
|
||||
// 获取数据
|
||||
this.findHouseList(1);
|
||||
})
|
||||
|
||||
},
|
||||
onShow(){
|
||||
this.needFillAuthInfo();
|
||||
},
|
||||
onUnload() {
|
||||
// 移除监听事件
|
||||
@@ -217,6 +200,21 @@
|
||||
// 关闭刷新
|
||||
uni.stopPullDownRefresh();
|
||||
},
|
||||
mounted(){
|
||||
|
||||
},
|
||||
computed: {
|
||||
authLabel() {
|
||||
return this.loginType === 'person'
|
||||
? '身份证号'
|
||||
: '企业社会信用代码'
|
||||
},
|
||||
authPlaceholder() {
|
||||
return this.loginType === 'person'
|
||||
? '请输入身份证号'
|
||||
: '请输入企业社会信用代码'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
checkCity(){
|
||||
// 检查是否已选择城市,如果未选择,跳转到选择城市页面
|
||||
@@ -228,6 +226,18 @@
|
||||
return this.$u.route('/pages/location/location');
|
||||
}
|
||||
},
|
||||
// 简单身份证校验(18 位)
|
||||
checkIdCard(code) {
|
||||
return /^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/.test(
|
||||
code
|
||||
);
|
||||
},
|
||||
|
||||
// 统一社会信用代码校验(18 位)
|
||||
checkCreditCode(code) {
|
||||
return /^[0-9A-Z]{18}$/.test(code);
|
||||
}
|
||||
,
|
||||
location(){
|
||||
this.$u.route({
|
||||
url: 'pages/location/location',
|
||||
@@ -250,8 +260,8 @@
|
||||
this.flowList = []
|
||||
this.$refs.uWaterfall.clear();
|
||||
}
|
||||
let url = "/api/houseApi/findHouseRoomList";
|
||||
this.$u.get(url, {
|
||||
let url = "/assets/findAssetList";
|
||||
this.$u.post(url, {
|
||||
state:1,
|
||||
villageCity:uni.getStorageSync('lifeData').vuex_city,
|
||||
pageNum: this.pageNum,
|
||||
@@ -259,45 +269,26 @@
|
||||
orderByColumn: 'update_time,create_time',
|
||||
isAsc: 'desc'
|
||||
}).then(result => {
|
||||
const data = result.rows;
|
||||
const data = result.data.result;
|
||||
if(this.pageNum>1 && data.length < this.pageSize){
|
||||
return this.loadStatus = 'nomore';
|
||||
// return this.loadStatus = 'nomore';
|
||||
}
|
||||
this.houseList = data;
|
||||
for (let i = 0; i < this.houseList.length; i++) {
|
||||
// 先转成字符串再转成对象,避免数组对象引用导致数据混乱
|
||||
let item = this.houseList[i]
|
||||
if(!item.faceUrl.includes(config.staticUrl)){
|
||||
item.image = config.staticUrl+item.faceUrl
|
||||
}else{
|
||||
item.image = item.faceUrl
|
||||
}
|
||||
if(item.type == 0){
|
||||
item.type = '整租'
|
||||
}else if(item.type == 1){
|
||||
item.type = '合租'
|
||||
}
|
||||
if(item.roomType == 1){
|
||||
item.roomType = '主卧'
|
||||
}else if(item.roomType == 2){
|
||||
item.roomType = '次卧'
|
||||
}else{
|
||||
item.roomType = '未知'
|
||||
}
|
||||
if(this.$u.test.isEmpty(item.houseNum)){
|
||||
item.houseNum = ''
|
||||
}
|
||||
if(this.$u.test.isEmpty(item.houseHall)){
|
||||
item.houseHall = ''
|
||||
}
|
||||
if(this.$u.test.isEmpty(item.toiletNum)){
|
||||
item.toiletNum = ''
|
||||
}
|
||||
// if(!item.faceUrl.includes(config.staticUrl)){
|
||||
// item.image = config.staticUrl+item.faceUrl
|
||||
// }else{
|
||||
// item.image = item.faceUrl
|
||||
// }
|
||||
this.flowList.push(item);
|
||||
}
|
||||
++ this.pageNum
|
||||
this.loadStatus = 'loadmore';
|
||||
});
|
||||
}).catch(err => {
|
||||
console.log("失败:", err)
|
||||
})
|
||||
},
|
||||
clickSearch() {
|
||||
this.$u.route('/pages/search/search');
|
||||
@@ -347,18 +338,35 @@
|
||||
});
|
||||
},
|
||||
getNoticecList(){
|
||||
// let url = "/api/notice/findNoticeList";
|
||||
// this.$u.get(url,{
|
||||
// pageNum:1,
|
||||
// pageSize:50,
|
||||
// orderByColumn:'create_time',
|
||||
// isAsc:'desc'
|
||||
// }).then(obj => {
|
||||
// let data = obj.rows
|
||||
// data.filter(item=>{
|
||||
// this.noticeList.push(item.noticeTitle)
|
||||
// })
|
||||
// });
|
||||
let url = "/notice/findNoticeList";
|
||||
this.$u.get(url,{
|
||||
pageNum:1,
|
||||
pageSize:50,
|
||||
orderByColumn:'create_time',
|
||||
isAsc:'desc'
|
||||
}).then(obj => {
|
||||
let data = obj.data.result
|
||||
data.filter(item=>{
|
||||
this.noticeList.push(item.noticeTitle)
|
||||
})
|
||||
});
|
||||
},
|
||||
needFillAuthInfo(){
|
||||
let lifeData = uni.getStorageSync('lifeData');
|
||||
let token = lifeData.vuex_token
|
||||
if (!token || token === null || token === undefined ||
|
||||
(typeof token === 'object' && Object.keys(token).length === 0)) {
|
||||
return;
|
||||
}
|
||||
let url = "/login/needFillAuthInfo";
|
||||
this.$u.get(url, {}, {'WT': token}).then(obj => {
|
||||
console.log(obj.data)
|
||||
if (obj.data) {
|
||||
this.showFillAuthInfo = obj.data
|
||||
const indexParam = uni.getStorageSync('indexParam') || {}
|
||||
this.loginType = indexParam.loginType || 'person'
|
||||
}
|
||||
});
|
||||
},
|
||||
moreInfo(){
|
||||
uni.navigateToMiniProgram({
|
||||
@@ -374,37 +382,103 @@
|
||||
}
|
||||
})
|
||||
},
|
||||
recordAuthInfo() {
|
||||
// 身份证校验
|
||||
if (this.loginType === 'person' && !this.checkIdCard(this.authCode)) {
|
||||
uni.showToast({
|
||||
title: '身份证号格式不正确',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 企业社会信用代码校验
|
||||
if (this.loginType === 'company' && !this.checkCreditCode(this.authCode)) {
|
||||
uni.showToast({
|
||||
title: '社会信用代码格式不正确',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
let lifeData = uni.getStorageSync('lifeData');
|
||||
let token = lifeData.vuex_token
|
||||
if (!token || token === null || token === undefined ||
|
||||
(typeof token === 'object' && Object.keys(token).length === 0)) {
|
||||
return;
|
||||
}
|
||||
let url = "/login/recordAuthInfo";
|
||||
this.$u.post(url, {
|
||||
code: this.authCode,
|
||||
userType: this.loginType,
|
||||
},{'WT': token}).then(obj => {
|
||||
if (obj.flag) {
|
||||
this.showFillAuthInfo = false;
|
||||
this.authCode = '';
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.index{
|
||||
margin-top: 20rpx;
|
||||
.index {
|
||||
background: #F8F8F8;
|
||||
min-height: 100vh; // 防止内容少时顶部空白
|
||||
position: relative;
|
||||
|
||||
}
|
||||
.bg{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 550rpx; /* ✅ 用固定高度更稳,你可改 320/400 */
|
||||
z-index: 0;
|
||||
}
|
||||
.index-title{
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 5%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
font-family: Noto Sans S Chinese;
|
||||
font-weight: 400;
|
||||
font-size: 34rpx;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
.content-wrapper{
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.search-wrapper {
|
||||
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
padding: 197rpx 30rpx 22rpx 30rpx; // 统一左右内边距
|
||||
}
|
||||
.navbox2 {
|
||||
height: 170rpx;
|
||||
padding-top: 2%;
|
||||
background: #FFFFFF;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
.nomore {
|
||||
background-color: $u-bg-color;
|
||||
}
|
||||
.search-bar {
|
||||
margin-top: 10rpx;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-radius: 8px;
|
||||
}
|
||||
.location-chose{
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
.search{
|
||||
width: 70px;
|
||||
height: 44px;
|
||||
&:active{
|
||||
background-color: $u-bg-color;
|
||||
}
|
||||
}
|
||||
.function-grid {
|
||||
margin: 0 20rpx;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.noticeStyle{
|
||||
display: flex;
|
||||
margin-top: 22rpx;
|
||||
height: 86rpx;
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 10rpx;
|
||||
|
||||
}
|
||||
/* 下划线 */
|
||||
.underline {
|
||||
margin-top: 5rpx;
|
||||
@@ -415,28 +489,21 @@
|
||||
}
|
||||
|
||||
.rowClass{
|
||||
border-radius: 8px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
margin-top: 10rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
.rowBgColor{
|
||||
background-color: rgb(248, 248, 248);
|
||||
}
|
||||
.leftOffSetRow{
|
||||
margin-left: 20%;
|
||||
}
|
||||
|
||||
.hoverClass{
|
||||
background-color: #E4E7ED;
|
||||
}
|
||||
|
||||
.tabName{
|
||||
font-size: 28rpx;
|
||||
color: $u-main-color;
|
||||
}
|
||||
|
||||
.demo-warter {
|
||||
border-radius: 8px;
|
||||
margin-top: 3px;
|
||||
background-color: #ffffff;
|
||||
padding: 3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.u-close {
|
||||
position: absolute;
|
||||
top: 20rpx;
|
||||
@@ -448,12 +515,27 @@
|
||||
color: $u-type-warning;
|
||||
}
|
||||
|
||||
.item-tag {
|
||||
font-size: 24rpx;
|
||||
color: $u-tips-color;
|
||||
margin-top: 3px;
|
||||
}
|
||||
.demo-warter {
|
||||
margin-bottom: 20rpx;
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.u-waterfall {
|
||||
padding: 0 20rpx; /* 左右留白一致 */
|
||||
}
|
||||
|
||||
.item-title {
|
||||
font-size: 28rpx;
|
||||
color: $u-main-color;
|
||||
font-weight: bold;
|
||||
padding-top: 5rpx;
|
||||
padding-left: 10rpx;
|
||||
font-weight: 600;
|
||||
margin-top: 14rpx;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
|
||||
.item-price {
|
||||
@@ -461,21 +543,69 @@
|
||||
font-size: 32rpx;
|
||||
color: $u-type-warning;
|
||||
}
|
||||
|
||||
.item-desc {
|
||||
font-weight: normal;
|
||||
font-size: 26rpx;
|
||||
color: $u-tips-color;
|
||||
padding-bottom: 5rpx;
|
||||
padding-left: 10rpx;
|
||||
}
|
||||
|
||||
.item-tag {
|
||||
font-size: 24rpx;
|
||||
color: $u-tips-color;
|
||||
margin-top: 3px;
|
||||
.item-desc, .item-price {
|
||||
padding: 0 10rpx;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
.auth-popup {
|
||||
width: 600rpx;
|
||||
padding: 48rpx 40rpx 40rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 24rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 标题 */
|
||||
.auth-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
text-align: center;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
/* 描述 */
|
||||
.auth-desc {
|
||||
font-size: 26rpx;
|
||||
color: #888;
|
||||
text-align: center;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
/* 输入区域 */
|
||||
.auth-input {
|
||||
margin-bottom: 48rpx;
|
||||
|
||||
::v-deep .u-input {
|
||||
padding-bottom: 12rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 提交按钮 */
|
||||
.auth-btn {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
background: linear-gradient(135deg, #FF2F31, #FF9379);
|
||||
color: #fff;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
border-radius: 44rpx;
|
||||
border: none;
|
||||
box-shadow: 0 10rpx 24rpx rgba(41, 121, 255, 0.3);
|
||||
}
|
||||
|
||||
/* 按压效果 */
|
||||
.auth-btn:active {
|
||||
opacity: 0.85;
|
||||
}
|
||||
.buttom {
|
||||
.loginType {
|
||||
font-size: 14px;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<view>
|
||||
<u-navbar :is-back="false" title="选择城市" :border-bottom="false"></u-navbar>
|
||||
<view class="location-page">
|
||||
<custom-navbar title="选择城市" />
|
||||
<view class="selected" >
|
||||
<view class="title">
|
||||
已选 :
|
||||
@@ -116,6 +116,9 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.location-page{
|
||||
padding-top: 175rpx;
|
||||
}
|
||||
.selected{
|
||||
.title {
|
||||
font-size: 30rpx;
|
||||
|
||||
@@ -1,113 +1,190 @@
|
||||
<template>
|
||||
<view class="login-page">
|
||||
|
||||
<!-- 背景视频 -->
|
||||
<video
|
||||
class="bg-video"
|
||||
src="/static/login.mp4"
|
||||
autoplay
|
||||
loop
|
||||
muted
|
||||
object-fit="cover"
|
||||
controls="false"
|
||||
show-center-play-btn="false"
|
||||
show-play-btn="false"
|
||||
show-fullscreen-btn="false"
|
||||
show-mute-btn="false"
|
||||
show-status-bar="false"
|
||||
enable-progress-gesture="false"
|
||||
/>
|
||||
|
||||
<!-- 遮罩层增强可读性 -->
|
||||
<view class="overlay"></view>
|
||||
<!-- 背景图 -->
|
||||
<!-- <image class="bg-img" :src="currentBg" :class="{ fade: isFading }" mode="aspectFill"></image> -->
|
||||
<!-- 内容层 -->
|
||||
<view class="login-content">
|
||||
<view class="title u-font-36 u-m-b-40">
|
||||
微信授权登录
|
||||
<view class="login-container">
|
||||
<!-- 顶部状态栏 -->
|
||||
<view class="status-bar">
|
||||
<u-icon
|
||||
:name="btn.icon"
|
||||
:color="btn.color || '#333'"
|
||||
:size="btn.size || 40"
|
||||
></u-icon>
|
||||
</view>
|
||||
|
||||
<button
|
||||
class="login-btn"
|
||||
open-type="getPhoneNumber"
|
||||
@getphonenumber="onGetPhone"
|
||||
>
|
||||
使用微信手机号授权登录
|
||||
<!-- 主体内容区 -->
|
||||
<view class="content">
|
||||
<!-- 标题区域 -->
|
||||
<view class="title">登录</view>
|
||||
|
||||
<!-- 登录插图区域 -->
|
||||
<view class="illustration">
|
||||
<image src="/static/login/bg.png" mode="aspectFit"></image>
|
||||
</view>
|
||||
|
||||
<!-- 登录按钮 -->
|
||||
<button class="login-btn" open-type="getPhoneNumber" @getphonenumber="onGetPhone">
|
||||
使用微信授权登录
|
||||
</button>
|
||||
|
||||
<view class="privacy-tip u-m-t-30 u-text-center">
|
||||
<!-- 用户类型选择 -->
|
||||
<view class="user-type" shape="square">
|
||||
<u-radio-group v-model="loginType" active-color="#EA414A" shape="square" >
|
||||
<u-radio name="person" >个人</u-radio>
|
||||
<u-radio name="company" >企业</u-radio>
|
||||
</u-radio-group>
|
||||
</view>
|
||||
|
||||
<!-- 协议提示 -->
|
||||
<view class="agreement">
|
||||
登录即同意
|
||||
<text class="link" @click="goPrivacy('user')">《用户协议》</text>
|
||||
<text class="link">《用户协议》</text>
|
||||
及
|
||||
<text class="link" @click="goPrivacy('privacy')">《隐私政策》</text>
|
||||
<text class="link">《隐私政策》</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
designWidth: 750,
|
||||
screenWidth: 0,
|
||||
scale: 1,
|
||||
bgImages: [
|
||||
'/static/loginbg1.jpg',
|
||||
'/static/loginbg2.jpg'
|
||||
],
|
||||
currentIndex: 0,
|
||||
currentBg: '/static/loginbg1.jpg',
|
||||
timer: null
|
||||
currentBg: '/static/login/bg.png',
|
||||
isFading: false,
|
||||
timer: null,
|
||||
loginType:"person"
|
||||
}
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.startBgTimer();
|
||||
// this.startBgTimer();
|
||||
wx.getWindowInfo({
|
||||
success: (res) => {
|
||||
this.screenWidth = res.windowWidth
|
||||
this.scale = this.screenWidth / this.designWidth
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onUnload() {
|
||||
clearInterval(this.timer);
|
||||
},
|
||||
computed: {
|
||||
// title 样式
|
||||
titleStyle() {
|
||||
const s = this.scale;
|
||||
return {
|
||||
width: `${93 * s}rpx`,
|
||||
height: `${45 * s}rpx`,
|
||||
fontSize: `${48 * s}rpx`,
|
||||
lineHeight: `${40 * s}rpx`,
|
||||
fontWeight: 500,
|
||||
color: '#222222',
|
||||
fontFamily: 'Noto Sans S Chinese',
|
||||
textAlign: 'center'
|
||||
}
|
||||
},
|
||||
headerStyle() {
|
||||
const s = this.scale;
|
||||
return {
|
||||
marginTop: `${214 * s}rpx`,
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center', // 水平居中
|
||||
justifyContent: 'flex-start' // 从顶部开始
|
||||
}
|
||||
},
|
||||
// cover 样式
|
||||
coverStyle() {
|
||||
const s = this.scale;
|
||||
return {
|
||||
width: `${428 * s}rpx`,
|
||||
height: `${608 * s}rpx`
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 背景切换定时器 */
|
||||
startBgTimer() {
|
||||
this.timer = setInterval(() => {
|
||||
this.isFading = true;
|
||||
|
||||
setTimeout(() => {
|
||||
this.currentIndex = (this.currentIndex + 1) % this.bgImages.length;
|
||||
this.currentBg = this.bgImages[this.currentIndex];
|
||||
}, 2000); // 每 4 秒切换一次
|
||||
this.isFading = false;
|
||||
}, 500);
|
||||
}, 4000);
|
||||
},
|
||||
|
||||
/** 微信手机号授权 */
|
||||
onGetPhone(e) {
|
||||
const { code } = e.detail;
|
||||
|
||||
if (!code) {
|
||||
this.$mytip.toast("授权失败");
|
||||
return;
|
||||
}
|
||||
this.doLogin(code);
|
||||
},
|
||||
async doLogin(code) {
|
||||
|
||||
/** 执行登录逻辑 */
|
||||
async doLogin(phoneGetCode) {
|
||||
uni.showLoading({ title: "登录中...", mask: true });
|
||||
|
||||
try {
|
||||
const authRes = await this.$u.get(`/api/weChatAuth?code=${code}`);
|
||||
if (!authRes.hasPhone) {
|
||||
this.showPhoneSelector(authRes.phoneList, authRes.openid);
|
||||
return;
|
||||
}
|
||||
await this.loginWithOpenId(authRes.openid);
|
||||
// 微信登录
|
||||
const loginRes = await new Promise((resolve, reject) => {
|
||||
uni.login({
|
||||
provider: 'weixin',
|
||||
success: resolve,
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
|
||||
// 调用后端登录接口
|
||||
const authRes = await this.$u.post(`/login/weChatLogin`, {
|
||||
phoneGetCode: phoneGetCode,
|
||||
loginCode: loginRes.code
|
||||
});
|
||||
|
||||
// 保存token
|
||||
this.$u.vuex('vuex_token', authRes.data);
|
||||
uni.hideLoading();
|
||||
|
||||
console.log(this.loginType)
|
||||
uni.setStorageSync('indexParam', {
|
||||
loginType: this.loginType
|
||||
})
|
||||
// 跳转首页
|
||||
uni.switchTab({
|
||||
url: '/pages/index/index'
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
uni.hideLoading();
|
||||
this.$mytip.toast("登录失败");
|
||||
uni.switchTab({ url: '/pages/index/index' });
|
||||
console.error('Login failed:', err);
|
||||
}
|
||||
},
|
||||
/** 触发手机号选择(子组件 → 父组件) */
|
||||
showPhoneSelector(phoneList, openid) {
|
||||
this.$emit("choosePhone", { phoneList, openid });
|
||||
},
|
||||
async loginWithOpenId(openid) {
|
||||
const loginRes = await this.$u.post('/api/weChatLoginByOpenId', { openid });
|
||||
this.$u.vuex('vuex_token', loginRes.token);
|
||||
this.$u.vuex('vuex_user', loginRes.loginUser);
|
||||
uni.hideLoading();
|
||||
uni.switchTab({ url: '/pages/index/index' });
|
||||
},
|
||||
/** 查看协议 */
|
||||
goPrivacy(type) {
|
||||
const url = type === 'user'
|
||||
? '/pages/privacy/userAgreement'
|
||||
: '/pages/privacy/privacyPolicy';
|
||||
|
||||
uni.navigateTo({ url });
|
||||
}
|
||||
}
|
||||
@@ -115,95 +192,89 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.login-page {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
.login-container {
|
||||
height: 100vh;
|
||||
background-color: #fff;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
|
||||
.bg-video {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
z-index: -1;
|
||||
.status-bar {
|
||||
margin-top: 7.56%;
|
||||
height: var(--status-bar-height);
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
width:100%;
|
||||
height:100%;
|
||||
background: rgba(0,0,0,0.3);
|
||||
z-index:0;
|
||||
}
|
||||
|
||||
.bg-img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
filter: brightness(0.7) blur(2px);
|
||||
opacity: 1;
|
||||
transition: opacity 0.5s ease;
|
||||
}
|
||||
|
||||
.bg-img.fade {
|
||||
opacity: 0;
|
||||
}
|
||||
.login-content {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 80%;
|
||||
max-width: 400rpx;
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
z-index: 1;
|
||||
animation: floatBtn 2s ease-in-out infinite alternate;
|
||||
height: calc(100vh - var(--status-bar-height));
|
||||
margin-top: 12.8%;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
height: 45rpx;
|
||||
font-family: Noto Sans S Chinese;
|
||||
font-weight: 500;
|
||||
font-size: 48rpx;
|
||||
color: #222222;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.illustration {
|
||||
width: 100%;
|
||||
height: 44.6%;
|
||||
padding-left: 21.47%;
|
||||
padding-right: 21.47%;
|
||||
margin-bottom: 6%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.illustration image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
line-height: 80rpx;
|
||||
font-size: 28rpx;
|
||||
color: #fff;
|
||||
border-radius: 40rpx;
|
||||
background: linear-gradient(90deg, #4CAF50, #07c160);
|
||||
box-shadow: 0 6rpx 12rpx rgba(0,0,0,0.25);
|
||||
text-align: center;
|
||||
margin-top: 20rpx;
|
||||
width: 78.6%;
|
||||
height: 7.12%;
|
||||
background: linear-gradient(90deg, #FF2F31 0%, #FF9379 100%);
|
||||
border-radius: 49rpx;
|
||||
font-family: Noto Sans S Chinese;
|
||||
font-weight: 400;
|
||||
font-size: 36rpx;
|
||||
color: #FFFFFF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.privacy-tip {
|
||||
font-size: 24rpx;
|
||||
color: #fff;
|
||||
margin-top: 20rpx;
|
||||
text-align: center;
|
||||
.user-type {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 40rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #ffd700;
|
||||
text-decoration: underline;
|
||||
margin: 0 4rpx;
|
||||
}
|
||||
.agreement {
|
||||
font-family: Noto Sans S Chinese;
|
||||
font-weight: 400;
|
||||
font-size: 30rpx;
|
||||
color: #CECECE;
|
||||
align-items: center;
|
||||
margin-top: 6.24%;
|
||||
}
|
||||
.link{
|
||||
color: #334254;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes floatBtn {
|
||||
0% { transform: translate(-50%, -50%) translateY(0); }
|
||||
100% { transform: translate(-50%, -50%) translateY(-10rpx); }
|
||||
|
||||
|
||||
/* 响应式适配 */
|
||||
@media (max-width: 320rpx) {
|
||||
.title { font-size: 42rpx; margin-bottom: 100rpx; }
|
||||
.illustration { height: 360rpx; }
|
||||
.login-btn { height: 80rpx; font-size: 30rpx; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<scroll-view scroll-y class="message-list">
|
||||
<view v-for="(msg,index) in messages" :key="index" class="msg-item u-flex u-row-between" @click="viewMessage(msg)">
|
||||
<view class="u-flex">
|
||||
<u-icon :name="msg.icon" size="48" :color="msg.read ? '#ccc' : '#ff8c00'"></u-icon>
|
||||
<u-icon :name="msg.icon" size="48" :color="msg.read ? '#ccc' : 'cornflowerblue'"></u-icon>
|
||||
<view class="msg-content u-m-l-20">
|
||||
<view class="msg-title u-font-16">{{ msg.title }}</view>
|
||||
<view class="msg-desc u-tips-color u-font-12 u-line-2">{{ msg.desc }}</view>
|
||||
|
||||
@@ -40,27 +40,27 @@ export default {
|
||||
methods: {
|
||||
clickContent(item){
|
||||
if(item.id){
|
||||
this.$u.route('/pages/content/content', {
|
||||
this.$u.route('/pages/notice/noticeDetail', {
|
||||
id: item.id
|
||||
});
|
||||
}
|
||||
},
|
||||
getNoticecList(){
|
||||
let url = "/api/notice/findNoticeList";
|
||||
let url = "/notice/findNoticeList";
|
||||
this.$u.get(url,{
|
||||
pageNum:this.pageNum,
|
||||
pageSize:this.pageSize,
|
||||
orderByColumn:'create_time',
|
||||
isAsc:'desc'
|
||||
}).then(obj => {
|
||||
let data = obj.rows
|
||||
let data = obj.data.result
|
||||
data.filter(item=>{
|
||||
this.dataList.push(
|
||||
{
|
||||
id:item.noticeId,
|
||||
title: item.noticeTitle,
|
||||
date:item.createTime,
|
||||
content: item.remark,
|
||||
content: item.reMark,
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<view>
|
||||
<!-- <u-navbar :is-back="true" title="房源列表" :border-bottom="false"></u-navbar> -->
|
||||
<view class="search-list-page">
|
||||
<!-- 顶部导航栏 -->
|
||||
<customNavbar title="资产列表" />
|
||||
<u-sticky offset-top="0">
|
||||
<view class="sticky">
|
||||
<filterDropdown :menuTop="0" :filterData="filterData" :defaultSelected="defaultSelected" :updateMenuName="true" @confirm="confirm" dataFormat="Object"></filterDropdown>
|
||||
@@ -10,20 +11,20 @@
|
||||
<u-waterfall v-model="flowList" ref="uWaterfall">
|
||||
<template v-slot:left="{leftList}">
|
||||
<view class="demo-warter" v-for="(item, index) in leftList" :key="index">
|
||||
<u-lazy-load threshold="750" border-radius="12" :image="item.image" :index="index"
|
||||
<u-lazy-load threshold="750" border-radius="12" :image="item.coverImgUrl" :index="index"
|
||||
@click="clickImage(item.id)"></u-lazy-load>
|
||||
<view class="item-title">{{item.villageName}} {{item.type == '整租' ? item.houseNum + item.houseHall + item.toiletNum : item.roomType}}</view>
|
||||
<view class="item-price">¥{{item.price}}</view>
|
||||
<view class="item-desc">{{item.type}} | {{item.type == '整租' ? item.houseArea : item.roomArea}}㎡ | {{item.decoration}} </view>
|
||||
<view class="item-title">{{item.name}}</view>
|
||||
<view class="item-desc">{{ item.footPrint}}㎡</view>
|
||||
<view class="item-price">¥{{item.rentFee}}</view>
|
||||
</view>
|
||||
</template>
|
||||
<template v-slot:right="{rightList}">
|
||||
<view class="demo-warter" v-for="(item, index) in rightList" :key="index">
|
||||
<u-lazy-load threshold="750" border-radius="10" :image="item.image" :index="index"
|
||||
<u-lazy-load threshold="750" border-radius="10" :image="item.coverImgUrl" :index="index"
|
||||
@click="clickImage(item.id)"></u-lazy-load>
|
||||
<view class="item-title">{{item.villageName}} {{item.type == '整租' ? item.houseNum + item.houseHall + item.toiletNum : item.roomType}}</view>
|
||||
<view class="item-price">¥{{item.price}}</view>
|
||||
<view class="item-desc">{{item.type}} | {{item.type == '整租' ? item.houseArea : item.roomArea}}㎡ | {{item.decoration}} </view>
|
||||
<view class="item-title">{{item.name}}</view>
|
||||
<view class="item-desc">{{ item.footPrint}}㎡</view>
|
||||
<view class="item-price">¥{{item.rentFee}}</view>
|
||||
</view>
|
||||
</template>
|
||||
</u-waterfall>
|
||||
@@ -91,58 +92,41 @@
|
||||
uni.stopPullDownRefresh();
|
||||
},
|
||||
methods: {
|
||||
findHouseList() {
|
||||
let url = "/api/houseApi/findHouseRoomList";
|
||||
let defaultData = {
|
||||
findHouseList(type = 0) {
|
||||
if(type == 1){
|
||||
this.pageNum = 1
|
||||
this.flowList = []
|
||||
this.$refs.uWaterfall.clear();
|
||||
}
|
||||
let url = "/assets/findAssetList";
|
||||
this.$u.post(url, {
|
||||
state:1,
|
||||
villageCity:uni.getStorageSync('lifeData').vuex_city,
|
||||
pageNum: this.pageNum,
|
||||
pageSize: this.pageSize,
|
||||
orderByColumn: 'update_time,create_time',
|
||||
isAsc: 'desc'
|
||||
}
|
||||
this.$u.get(url, {...defaultData,...this.searchData}).then(result => {
|
||||
console.log(this.searchData);
|
||||
console.log(result);
|
||||
const data = result.rows;
|
||||
}).then(result => {
|
||||
const data = result.data.result;
|
||||
if(this.pageNum>1 && data.length < this.pageSize){
|
||||
return this.loadStatus = 'nomore';
|
||||
// return this.loadStatus = 'nomore';
|
||||
}
|
||||
this.houseList = data;
|
||||
for (let i = 0; i < this.houseList.length; i++) {
|
||||
// 先转成字符串再转成对象,避免数组对象引用导致数据混乱
|
||||
let item = this.houseList[i]
|
||||
if(!item.faceUrl.includes(config.staticUrl)){
|
||||
item.image = config.staticUrl+item.faceUrl
|
||||
}else{
|
||||
item.image = item.faceUrl
|
||||
}
|
||||
if(item.type == 0){
|
||||
item.type = '整租'
|
||||
}else if(item.type == 1){
|
||||
item.type = '合租'
|
||||
}
|
||||
if(item.roomType == 1){
|
||||
item.roomType = '主卧'
|
||||
}else if(item.roomType == 2){
|
||||
item.roomType = '次卧'
|
||||
}else{
|
||||
item.roomType = '未知'
|
||||
}
|
||||
if(this.$u.test.isEmpty(item.houseNum)){
|
||||
item.houseNum = ''
|
||||
}
|
||||
if(this.$u.test.isEmpty(item.houseHall)){
|
||||
item.houseHall = ''
|
||||
}
|
||||
if(this.$u.test.isEmpty(item.toiletNum)){
|
||||
item.toiletNum = ''
|
||||
}
|
||||
// if(!item.faceUrl.includes(config.staticUrl)){
|
||||
// item.image = config.staticUrl+item.faceUrl
|
||||
// }else{
|
||||
// item.image = item.faceUrl
|
||||
// }
|
||||
this.flowList.push(item);
|
||||
}
|
||||
++ this.pageNum
|
||||
this.loadStatus = 'loadmore';
|
||||
});
|
||||
}).catch(err => {
|
||||
console.log("失败:", err)
|
||||
})
|
||||
},
|
||||
findVillageList() {
|
||||
let url = "/api/houseApi/findVillageList";
|
||||
@@ -213,6 +197,9 @@
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.search-list-page{
|
||||
padding-top: 175rpx;
|
||||
}
|
||||
.waterfall{
|
||||
// padding-top: 85rpx;
|
||||
}
|
||||
|
||||
26
pages/vr/vr.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<view class="vr-page">
|
||||
<web-view :src="src"></web-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
src: ""
|
||||
};
|
||||
},
|
||||
onLoad(options) {
|
||||
this.src = decodeURIComponent(options.url);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.vr-page,
|
||||
.vr-page web-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<view v-if="src">
|
||||
<web-view :webview-styles="wbStyles" :src="src" :fullscreen="false" />
|
||||
<web-view :webview-styles="wbStyles" :src="src" :fullscreen="false" bindmessage="handleGetMessage"/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -16,6 +16,11 @@ export default {
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleGetMessage(e){
|
||||
|
||||
}
|
||||
},
|
||||
onLoad(option) {
|
||||
console.log(option.title);
|
||||
this.title = option?.title
|
||||
|
||||
BIN
static/icon/parking.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
static/icon/sign.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
static/icon/个人商铺.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
static/icon/书签.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
static/icon/优惠商城.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
static/icon/住房C.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
static/icon/住房信息.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 204 KiB |
BIN
static/icon/厂房C.png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
static/icon/商铺C.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
static/icon/待付款.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
static/icon/水电费.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
static/icon/留言纸.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
static/icon/缴费记录.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/icon/账单.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
static/icon/账本.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
static/icon/退租.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
static/icon/预约.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
static/index/index_bg.png
Normal file
|
After Width: | Height: | Size: 355 KiB |
BIN
static/index/住房.png
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
BIN
static/index/停车场.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
static/index/公告.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
static/index/公告_slices/公告@2x.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
static/index/厂房.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
static/index/合同签约.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
static/index/商铺.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
static/index/图层 1129_slices/图层 1129@2x.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
static/index/图层 1130_slices/图层 1130@2x.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
static/index/图层 1131_slices/图层 1131@2x.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
static/index/图层 1132_slices/图层 1132@2x.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
static/index/图层 1134_slices/图层 1134@2x.png
Normal file
|
After Width: | Height: | Size: 949 KiB |
BIN
static/index/留言板.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
static/index/看房预约.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
static/index/组 3_slices/组 3@2x.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
static/index/组 4_slices/组 4@2x.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
static/index/组 5_slices/组 5@2x.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
static/index/组 6_slices/组 6@2x.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
static/index/退租申请.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
static/login/bg.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
static/login/图层 1154_slices.zip
Normal file
BIN
static/login/图层 1154_slices/bg.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
static/login/图层 1154_slices/图层 1154@2x.png
Normal file
|
After Width: | Height: | Size: 279 KiB |
|
Before Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 54 KiB |
@@ -4,12 +4,26 @@ module.exports = {
|
||||
devServer: {
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'https://sourcebyte.vip',
|
||||
target: 'http://localhost:8089',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {
|
||||
'^/api': '/api'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// module.exports = {
|
||||
// publicPath: './',
|
||||
// devServer: {
|
||||
// proxy: {
|
||||
// '/api': {
|
||||
// target: 'https://sourcebyte.vip',
|
||||
// changeOrigin: true,
|
||||
// pathRewrite: {
|
||||
// '^/api': '/api'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||