buddhism/pages/memorial/addMemorial.vue

707 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page">
<base-background />
<!-- 使用自定义导航栏组件 -->
<custom-navbar title="添加牌位" />
<view class="content">
<!-- 扫码获取SN和MAC -->
<view class="scan-section">
<view class="section-title">设备信息</view>
<view class="scan-container">
<view class="scan-btn" @click="handleScanCode">
<view class="qrcode-icon">
<image
mode="aspectFit"
src="https://api.ccttiot.com/smartmeter/img/static/uy7BNwAMIKwvstqFnRhs"
/>
</view>
<view class="scan-text">扫码获取设备信息</view>
</view>
</view>
<!-- 显示SN和MAC信息 -->
<view v-if="deviceInfo.sn || deviceInfo.mac" class="device-info">
<view v-if="deviceInfo.code" class="info-item">
<view class="info-label">牌位编号:</view>
<view class="info-value"
>{{ deviceInfo.code }}(牌位已添加编号)
</view>
</view>
<view v-if="deviceInfo.mac" class="info-item">
<view class="info-label">mac</view>
<view class="info-value">{{ deviceInfo.mac }}</view>
</view>
<view v-if="deviceInfo.sn" class="info-item">
<view class="info-label">sn</view>
<view class="info-value">{{ deviceInfo.sn }}</view>
</view>
</view>
</view>
<!-- 牌位信息表单 -->
<view class="form-section">
<view class="section-title">牌位信息</view>
<view class="form-container">
<!-- 牌位编号 -->
<view class="form-item">
<view class="label"
>牌位编号
<text class="required">*</text>
</view>
<input
v-model="formData.code"
class="input"
maxlength="20"
placeholder="请输入牌位编号"
/>
</view>
<!-- 区域选择 -->
<view class="form-item">
<view class="label"
>所属区域
<text class="required">*</text>
</view>
<view class="picker" @click="showRegionSelect">
<view class="picker-text">
{{ selectedRegionText || "请选择区域" }}
</view>
<view class="picker-arrow">></view>
</view>
</view>
</view>
</view>
<!-- 操作按钮 -->
<view class="button-container">
<view class="btn cancel-btn" @click="handleCancel">取消</view>
<view
:class="{ disabled: !canSubmit }"
class="btn confirm-btn"
@click="handleConfirm"
>确认添加
</view>
</view>
<!-- 列表渲染 -->
<view v-for="(item, index) in winB_List" :key="index">
<view>{{ item.mac }}</view>
<view>{{ item.sn }}</view>
</view>
</view>
<!-- 区域选择器 -->
<u-select
v-model="showRegionPicker"
:list="regionList"
mode="mutil-column-auto"
@cancel="onRegionCancel"
@confirm="onRegionConfirm"
></u-select>
</view>
</template>
<script>
import { createPagination } from "../../composables/winB_Pagination";
import { getMemorialList } from "../../api/memorial/memorial";
export default {
mixins: [
createPagination({
fetchData: getMemorialList,
mode: "loadMore", // 或 "pager"
pageSize: 5,
autoLoad: false, // 手动触发时设为 false
}),
],
created() {
// 条件就绪后触发首次加载
this.winB_UpdateParams();
},
data() {
return {
// 设备信息
deviceInfo: {
sn: "",
mac: "",
code: "",
id: "",
},
// 表单数据
formData: {
code: "",
id: "",
regionId: "",
},
// 区域相关数据
regionList: [], // 区域树形数据
showRegionPicker: false, // 控制区域选择器显示
selectedRegion: null, // 选中的区域信息
selectedRegionText: "", // 选中的区域显示文本
// 加载状态
loading: false,
};
},
computed: {
// 是否可以提交
canSubmit() {
return (
this.deviceInfo.sn &&
this.deviceInfo.mac &&
this.formData.code.trim() &&
this.selectedRegion
);
},
},
onReachBottom() {
this.winB_LoadMore();
},
async onLoad() {
// 页面加载时获取区域数据
await this.loadRegionData();
// 尝试从缓存中恢复区域选择
this.loadCachedRegion();
},
methods: {
// 扫码获取SN
async handleScanCode() {
try {
uni.showLoading({ title: "扫码中...", mask: true });
// 调用扫码功能
const res = await new Promise((resolve, reject) => {
uni.scanCode({
onlyFromCamera: true,
scanType: ["qrCode"],
success: (result) => {
resolve(result);
},
fail: (error) => {
reject(error);
},
});
});
uni.hideLoading();
if (res.result) {
// 解析二维码内容提取SN参数
let sn = null;
let queryParams = res.result.split("?")[1];
if (queryParams) {
let params = queryParams.split("&");
params.forEach((param) => {
let [key, value] = param.split("=");
if (key === "s") {
sn = value;
}
});
}
// 如果没有从URL参数中获取到SN尝试直接使用结果
if (!sn) {
sn = res.result.trim();
}
console.log("扫码获取到SN:", sn);
console.log("原始扫码结果:", res.result);
if (sn) {
// 通过SN获取设备信息
await this.getDeviceInfoBySn(sn);
} else {
uni.showToast({
title: "未找到有效的SN码",
icon: "none",
});
}
}
} catch (error) {
uni.hideLoading();
console.error("扫码失败:", error);
if (error.errMsg && error.errMsg.includes("cancel")) {
// 用户取消扫码,不显示错误提示
return;
}
uni.showToast({
title: "扫码失败,请重试",
icon: "none",
});
}
},
// 通过SN获取设备信息
async getDeviceInfoBySn(sn) {
try {
uni.showLoading({ title: "获取设备信息...", mask: true });
// 调用API获取设备信息
const res = await this.$request.get("/bst/memorial/getBySn", {
sn: sn,
});
uni.hideLoading();
console.log("@@@@@@@@@@@@@@@@@@@@", res);
if (res) {
const deviceData = res;
this.deviceInfo = {
sn: deviceData.sn || sn,
mac: deviceData.mac || "",
code: deviceData.code || "",
id: deviceData.id || "",
};
uni.showToast({
title: "设备信息获取成功",
icon: "success",
});
console.log("设备信息:", this.deviceInfo);
} else {
throw new Error(res?.msg || "获取设备信息失败");
}
} catch (error) {
uni.hideLoading();
console.error("获取设备信息失败:", error);
uni.showToast({
title: error.message || "获取设备信息失败",
icon: "none",
});
}
},
// 加载区域数据
async loadRegionData() {
try {
// 从缓存中获取templeId如果没有则使用默认值
const templeId = uni.getStorageSync("templeId") || "12";
const res = await this.$request.get(`/bst/region/listTree/${templeId}`);
if (res && res.data) {
// 转换数据格式为u-select需要的格式
this.regionList = this.transformRegionData(res.data);
console.log("区域数据加载成功:", this.regionList);
} else {
throw new Error("获取区域数据失败");
}
} catch (error) {
console.error("加载区域数据失败:", error);
uni.showToast({
title: "加载区域数据失败",
icon: "none",
});
}
},
// 转换区域数据格式
transformRegionData(data) {
if (!data || !data.children) return [];
return data.children.map((floor) => ({
label: floor.label,
value: floor.id,
children: floor.children
? floor.children.map((area) => ({
label: area.label,
value: area.id,
}))
: [],
}));
},
// 显示区域选择器
showRegionSelect() {
if (this.regionList.length === 0) {
uni.showToast({
title: "区域数据加载中,请稍后",
icon: "none",
});
return;
}
this.showRegionPicker = true;
},
// 区域选择确认
onRegionConfirm(e) {
console.log("区域选择结果:", e);
if (e && e.length >= 2) {
const [floor, area] = e;
this.selectedRegion = {
floorId: floor.value,
floorName: floor.label,
areaId: area.value,
areaName: area.label,
};
this.selectedRegionText = `${floor.label} - ${area.label}`;
this.formData.regionId = area.value;
// 缓存区域选择
this.cacheRegionSelection();
uni.showToast({
title: "区域选择成功",
icon: "success",
});
}
},
// 区域选择取消
onRegionCancel() {
this.showRegionPicker = false;
},
// 缓存区域选择
cacheRegionSelection() {
if (this.selectedRegion) {
uni.setStorageSync("lastSelectedRegion", this.selectedRegion);
uni.setStorageSync("lastSelectedRegionText", this.selectedRegionText);
}
},
// 从缓存加载区域选择
loadCachedRegion() {
try {
const cachedRegion = uni.getStorageSync("lastSelectedRegion");
const cachedRegionText = uni.getStorageSync("lastSelectedRegionText");
if (cachedRegion && cachedRegionText) {
this.selectedRegion = cachedRegion;
this.selectedRegionText = cachedRegionText;
this.formData.regionId = cachedRegion.areaId;
console.log("已恢复缓存的区域选择:", cachedRegion);
}
} catch (error) {
console.error("加载缓存区域失败:", error);
}
},
// 取消操作
handleCancel() {
uni.navigateBack();
},
// 确认添加
async handleConfirm() {
if (!this.canSubmit) {
uni.showToast({
title: "请完善必填信息",
icon: "none",
});
return;
}
// 表单验证
if (!this.validateForm()) {
return;
}
try {
uni.showLoading({ title: "添加中...", mask: true });
// 构建请求数据
const requestData = {
id: this.deviceInfo.id, // 使用设备ID
code: this.formData.code,
regionId: this.selectedRegion ? this.selectedRegion.areaId : "",
};
console.log("提交数据:", requestData);
// 调用API添加牌位
const res = await this.$request.put("/bst/memorial", requestData);
uni.hideLoading();
if (res && (res.code === 200 || res.status === 200)) {
uni.showToast({
title: "添加成功",
icon: "success",
});
// 延迟返回上一页
setTimeout(() => {
uni.navigateBack();
}, 1500);
} else {
throw new Error(res?.msg || "添加失败");
}
} catch (error) {
uni.hideLoading();
console.error("添加牌位失败:", error);
uni.showToast({
title: error.message || "添加失败,请重试",
icon: "none",
});
}
},
// 表单验证
validateForm() {
if (!this.formData.code.trim()) {
uni.showToast({
title: "请输入牌位编号",
icon: "none",
});
return false;
}
if (!this.selectedRegion) {
uni.showToast({
title: "请选择所属区域",
icon: "none",
});
return false;
}
return true;
},
},
};
</script>
<style lang="scss" scoped>
.page {
width: 100%;
min-height: 100vh;
background: #f5f5f5;
}
.content {
padding: 20rpx;
padding-bottom: 120rpx;
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
padding-left: 10rpx;
border-left: 6rpx solid #4a90e2;
}
.scan-section {
background: #fff;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 30rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
.scan-container {
margin-bottom: 30rpx;
}
.scan-btn {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 200rpx;
border: 3rpx dashed #4a90e2;
border-radius: 16rpx;
background: #f8fbff;
transition: all 0.3s ease;
&:active {
background: #e8f4ff;
transform: scale(0.98);
}
}
.qrcode-icon {
width: 60rpx;
height: 60rpx;
margin-bottom: 10rpx;
image {
width: 100%;
height: 100%;
}
}
.scan-text {
font-size: 28rpx;
color: #4a90e2;
font-weight: 500;
}
.device-info {
background: #f8f9fa;
border-radius: 12rpx;
padding: 20rpx;
border: 2rpx solid #e9ecef;
}
.info-item {
display: flex;
align-items: center;
margin-bottom: 15rpx;
&:last-child {
margin-bottom: 0;
}
}
.info-label {
font-size: 26rpx;
color: #666;
width: 140rpx;
flex-shrink: 0;
}
.info-value {
font-size: 26rpx;
color: #333;
font-weight: 500;
flex: 1;
word-break: break-all;
}
.form-section {
background: #fff;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 30rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
.form-container {
// 表单容器样式
}
.form-item {
margin-bottom: 30rpx;
&:last-child {
margin-bottom: 0;
}
}
.label {
font-size: 28rpx;
color: #666;
margin-bottom: 12rpx;
font-weight: 500;
}
.required {
color: #ff4757;
margin-left: 4rpx;
}
.input {
width: 100%;
height: 80rpx;
border: 2rpx solid #e5e5e5;
border-radius: 8rpx;
padding: 0 20rpx;
font-size: 28rpx;
color: #333;
box-sizing: border-box;
background: #fff;
&:focus {
border-color: #4a90e2;
}
}
.picker {
width: 100%;
height: 80rpx;
border: 2rpx solid #e5e5e5;
border-radius: 8rpx;
display: flex;
align-items: center;
padding: 0 20rpx;
background: #fff;
box-sizing: border-box;
}
.picker-text {
font-size: 28rpx;
color: #333;
flex: 1;
}
.picker-arrow {
color: #999;
font-size: 24rpx;
transform: rotate(90deg);
}
.textarea {
width: 100%;
min-height: 120rpx;
border: 2rpx solid #e5e5e5;
border-radius: 8rpx;
padding: 20rpx;
font-size: 28rpx;
color: #333;
box-sizing: border-box;
background: #fff;
resize: none;
&:focus {
border-color: #4a90e2;
}
}
.button-container {
display: flex;
gap: 20rpx;
padding: 0 20rpx;
}
.btn {
flex: 1;
height: 88rpx;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
font-weight: bold;
transition: all 0.3s ease;
}
.cancel-btn {
background: #f5f5f5;
color: #666;
border: 2rpx solid #e5e5e5;
&:active {
background: #e8e8e8;
}
}
.confirm-btn {
background: #4a90e2;
color: #fff;
box-shadow: 0 4rpx 12rpx rgba(74, 144, 226, 0.3);
&:active {
background: #357abd;
}
&.disabled {
background: #ccc;
color: #999;
box-shadow: none;
&:active {
background: #ccc;
}
}
}
</style>