日报等
This commit is contained in:
parent
46a3d45f97
commit
800899ab70
|
@ -10,10 +10,11 @@ export function listStore(query) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询店铺详细
|
// 查询店铺详细
|
||||||
export function getStore(storeId) {
|
export function getStore(storeId,data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/store/' + storeId,
|
url: '/system/store/' + storeId,
|
||||||
method: 'get'
|
method: 'get',
|
||||||
|
params: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,11 @@ export function fastSearch(query) {
|
||||||
|
|
||||||
|
|
||||||
// 查询用户详细
|
// 查询用户详细
|
||||||
export function getUser(userId) {
|
export function getUser(userId, query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/user/user/' + parseStrEmpty(userId),
|
url: '/user/user/' + parseStrEmpty(userId),
|
||||||
method: 'get'
|
method: 'get',
|
||||||
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -166,8 +166,7 @@
|
||||||
<router-link
|
<router-link
|
||||||
v-if="deviceData.userId"
|
v-if="deviceData.userId"
|
||||||
:to="'/user/detail/' + deviceData.userId"
|
:to="'/user/detail/' + deviceData.userId"
|
||||||
class="link-type"
|
class="link-type">
|
||||||
>
|
|
||||||
<span>{{ deviceData.userName }}</span>
|
<span>{{ deviceData.userName }}</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
<span v-else>--</span>
|
<span v-else>--</span>
|
||||||
|
|
|
@ -323,6 +323,7 @@ import {listStore} from "@/api/system/store";
|
||||||
import {listUser} from "@/api/system/user";
|
import {listUser} from "@/api/system/user";
|
||||||
import QrCode from "@/components/QrCode/index.vue";
|
import QrCode from "@/components/QrCode/index.vue";
|
||||||
import { getDomain } from "@/api/common/common";
|
import { getDomain } from "@/api/common/common";
|
||||||
|
import { deviceSwitch } from "@/api/system/device";
|
||||||
|
|
||||||
// 默认排序字段
|
// 默认排序字段
|
||||||
const defaultSort = {
|
const defaultSort = {
|
||||||
|
@ -415,6 +416,7 @@ export default {
|
||||||
rules: {
|
rules: {
|
||||||
},
|
},
|
||||||
domain: '', // 域名
|
domain: '', // 域名
|
||||||
|
oldForm: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
@ -532,6 +534,7 @@ export default {
|
||||||
const equipmentId = row.equipmentId || this.ids
|
const equipmentId = row.equipmentId || this.ids
|
||||||
getEquipment(equipmentId).then(response => {
|
getEquipment(equipmentId).then(response => {
|
||||||
this.form = response.data;
|
this.form = response.data;
|
||||||
|
this.oldForm = { ...response.data };
|
||||||
this.open = true;
|
this.open = true;
|
||||||
this.title = "修改设施";
|
this.title = "修改设施";
|
||||||
});
|
});
|
||||||
|
@ -540,22 +543,43 @@ export default {
|
||||||
submitForm() {
|
submitForm() {
|
||||||
this.$refs["form"].validate(valid => {
|
this.$refs["form"].validate(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (this.form.equipmentId != null) {
|
if (this.form.deviceId &&
|
||||||
updateEquipment(this.form).then(response => {
|
this.form.unlockMode !== this.oldForm?.unlockMode) {
|
||||||
this.$modal.msgSuccess("修改成功");
|
const open = this.form.unlockMode === "2";
|
||||||
this.open = false;
|
deviceSwitch({
|
||||||
this.getList();
|
deviceId: this.form.deviceId,
|
||||||
|
open: open
|
||||||
|
}).then(() => {
|
||||||
|
this.saveForm();
|
||||||
|
}).catch(() => {
|
||||||
|
this.$modal.msgError("设备开关操作失败");
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
addEquipment(this.form).then(response => {
|
this.saveForm();
|
||||||
this.$modal.msgSuccess("新增成功");
|
|
||||||
this.open = false;
|
|
||||||
this.getList();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/** 保存表单 */
|
||||||
|
saveForm() {
|
||||||
|
let data = {
|
||||||
|
...this.form
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.form.equipmentId != null) {
|
||||||
|
updateEquipment(data).then(response => {
|
||||||
|
this.$modal.msgSuccess("修改成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addEquipment(data).then(response => {
|
||||||
|
this.$modal.msgSuccess("新增成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
const equipmentIds = row.equipmentId || this.ids;
|
const equipmentIds = row.equipmentId || this.ids;
|
||||||
|
|
|
@ -574,9 +574,14 @@ export default {
|
||||||
}
|
}
|
||||||
return feeRules.map(rule => rule.explain).filter(Boolean).join(',');
|
return feeRules.map(rule => rule.explain).filter(Boolean).join(',');
|
||||||
},
|
},
|
||||||
/** 跳转到详情页面 */
|
/** 查看详情按钮操作 */
|
||||||
handleDetail(row) {
|
handleDetail(row) {
|
||||||
this.$router.push(`/system/equipmentDetail/index/${row.roomId}`);
|
this.$router.push({
|
||||||
|
path: `/system/equipmentDetail/index/${row.roomId}`,
|
||||||
|
query: {
|
||||||
|
type: 'equipment'
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
/** 获取套餐选项 */
|
/** 获取套餐选项 */
|
||||||
getRuleOptions(merchantId) {
|
getRuleOptions(merchantId) {
|
||||||
|
|
|
@ -458,8 +458,8 @@ export default {
|
||||||
/** 查询订单列表 */
|
/** 查询订单列表 */
|
||||||
getList() {
|
getList() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
console.log(this.userId,'this.userId');
|
// console.log(this.userId,'this.userId');
|
||||||
console.log(this.merchantId,'this.merchantId');
|
// console.log(this.merchantId,'this.merchantId');
|
||||||
listOrder(this.queryParams).then(response => {
|
listOrder(this.queryParams).then(response => {
|
||||||
this.orderList = response.rows;
|
this.orderList = response.rows;
|
||||||
this.total = response.total;
|
this.total = response.total;
|
||||||
|
|
|
@ -1,171 +1,193 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<el-card class="box-card" shadow="hover">
|
<div class="detail-container">
|
||||||
<!-- 标题和操作按钮 -->
|
<el-card class="box-card" shadow="hover">
|
||||||
<div class="card-header">
|
<!-- 标题和操作按钮 -->
|
||||||
<div class="header-title">
|
<div class="card-header">
|
||||||
<span class="title">订单详情</span>
|
<div class="header-title">
|
||||||
<dict-tag :options="dict.type.ss_order_status" :value="order.status"/>
|
<span class="title">订单详情</span>
|
||||||
</div>
|
<dict-tag :options="dict.type.ss_order_status" :value="order.status"/>
|
||||||
<div class="operation-buttons">
|
</div>
|
||||||
<el-button
|
<div class="operation-buttons">
|
||||||
type="primary"
|
<el-button
|
||||||
icon="el-icon-card"
|
type="primary"
|
||||||
size="small"
|
icon="el-icon-card"
|
||||||
@click="handleRefund"
|
size="small"
|
||||||
v-has-permi="['system:room:refund']"
|
@click="handleRefund"
|
||||||
>退款</el-button>
|
v-has-permi="['system:room:refund']"
|
||||||
<el-button
|
>退款</el-button>
|
||||||
type="danger"
|
<el-button
|
||||||
icon="el-icon-close"
|
type="danger"
|
||||||
size="small"
|
icon="el-icon-close"
|
||||||
@click="handleClose"
|
size="small"
|
||||||
v-has-permi="['system:room:close']"
|
@click="handleClose"
|
||||||
>结束订单</el-button>
|
v-has-permi="['system:room:close']"
|
||||||
|
>结束订单</el-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 左侧详情信息 -->
|
||||||
|
<el-row :span="24">
|
||||||
|
<el-col :span="20">
|
||||||
|
<div class="detail-left">
|
||||||
|
<!-- 所有info-section -->
|
||||||
|
<div class="info-sections">
|
||||||
|
<!-- 基本信息 -->
|
||||||
|
<div class="info-section">
|
||||||
|
<h3>
|
||||||
|
<i class="el-icon-info"></i>
|
||||||
|
基本信息
|
||||||
|
</h3>
|
||||||
|
<el-descriptions :column="3" border>
|
||||||
|
<el-descriptions-item label="订单号">{{ order.orderNo }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="用户">
|
||||||
|
<router-link :to="`/user/detail/${order.userId}`" class="link-type">
|
||||||
|
{{ order.userName }}
|
||||||
|
</router-link>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="预约时间">
|
||||||
|
<template v-if="order.reserveStartTime && order.reserveEndTime">
|
||||||
|
{{ parseTime(order.reserveStartTime) }} 至 {{ parseTime(order.reserveEndTime) }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
--
|
||||||
|
</template>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="房间/设施">
|
||||||
|
<router-link :to="`/system/roomDetail/index/${order.roomId}`" class="link-type">
|
||||||
|
{{ order.roomName }}
|
||||||
|
</router-link>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="店铺">
|
||||||
|
<router-link :to="`/system/storeDetail/index/${order.storeId}`" class="link-type">
|
||||||
|
{{ order.storeName }}
|
||||||
|
</router-link>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="大门">
|
||||||
|
<router-link
|
||||||
|
v-if="order.gateSn"
|
||||||
|
:to="`/system/deviceDetail/index/${order.gateId}`"
|
||||||
|
class="link-type">
|
||||||
|
{{ order.gateSn }}
|
||||||
|
</router-link>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 套餐信息 -->
|
||||||
|
<div class="info-section">
|
||||||
|
<h3>
|
||||||
|
<i class="el-icon-goods"></i>
|
||||||
|
套餐信息
|
||||||
|
</h3>
|
||||||
|
<el-descriptions :column="3" border>
|
||||||
|
<el-descriptions-item label="收费模式">
|
||||||
|
<dict-tag :options="dict.type.ss_fee_rule_mode" :value="order.mode"/>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="套餐名称">{{ order.ruleName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="套餐时长">{{ order.duration }} 小时</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 商户信息 -->
|
||||||
|
<div class="info-section">
|
||||||
|
<h3>
|
||||||
|
<i class="el-icon-office-building"></i>
|
||||||
|
商户信息
|
||||||
|
</h3>
|
||||||
|
<el-descriptions :column="3" border>
|
||||||
|
<el-descriptions-item label="商户名称">
|
||||||
|
<router-link :to="`/user/detail/${order.merchantId}`" class="link-type">
|
||||||
|
{{ order.merchantName }}
|
||||||
|
</router-link>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="商户ID">{{ order.merchantId }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 支付信息 -->
|
||||||
|
<div class="info-section">
|
||||||
|
<h3>
|
||||||
|
<i class="el-icon-money"></i>
|
||||||
|
支付信息
|
||||||
|
</h3>
|
||||||
|
<el-descriptions :column="3" border>
|
||||||
|
<el-descriptions-item label="支付方式">
|
||||||
|
<dict-tag :options="dict.type.ss_pay_type" :value="order.payType"/>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="支付状态">
|
||||||
|
<dict-tag :options="dict.type.et_order_pay_status" :value="order.paid"/>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="支付时间">
|
||||||
|
{{ parseTime(order.payTime) }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="订单金额">{{ order.totalFee | dv }} 元</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="实付金额">{{ order.payFee | dv }} 元</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="手续费">{{ order.handlingCharge | dv }} 元</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="平台服务费">{{ order.platformServiceFee | dv }} 元</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="押金扣除">{{ order.depositDeduction | dv }} 元</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="扣除金额">{{ order.deductionAmount | dv }} 元</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="4">
|
||||||
|
<!-- 右侧操作履历 -->
|
||||||
|
<div class="detail-right">
|
||||||
|
<div class="info-sections history-section">
|
||||||
|
<h3>
|
||||||
|
<i class="el-icon-time" style="color: #E6A23C;"></i>
|
||||||
|
操作履历
|
||||||
|
</h3>
|
||||||
|
<el-timeline class="padding0">
|
||||||
|
<el-timeline-item
|
||||||
|
v-for="activity in order.orderOpers"
|
||||||
|
:key="activity.operId"
|
||||||
|
:type="getTimelineItemType(activity.operType)"
|
||||||
|
:timestamp="activity.createTime"
|
||||||
|
:color="getTimelineItemColor(activity.operType)"
|
||||||
|
>
|
||||||
|
<div class="timeline-content">
|
||||||
|
<span class="operation-type" :style="{ color: getTimelineItemColor(activity.operType) }">
|
||||||
|
{{ dict.type.ss_order_oper_type[activity.operType].label }}
|
||||||
|
</span>
|
||||||
|
<el-tooltip placement="right" effect="light" popper-class="operation-tooltip">
|
||||||
|
<div slot="content">
|
||||||
|
<div>{{ activity.details }}</div>
|
||||||
|
<div v-if="activity.beforeAmount !== activity.afterAmount">
|
||||||
|
金额变更: {{ activity.beforeAmount }}元 -> {{ activity.afterAmount }}元
|
||||||
|
</div>
|
||||||
|
<div>操作人: {{ activity.operPhone }}</div>
|
||||||
|
</div>
|
||||||
|
<i
|
||||||
|
class="el-icon-info tooltip-icon"
|
||||||
|
:style="{ color: getTimelineItemColor(activity.operType) }"
|
||||||
|
></i>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</el-timeline-item>
|
||||||
|
</el-timeline>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 分账明细标签页 -->
|
||||||
|
<el-card class="box-card detail-tabs" shadow="hover">
|
||||||
|
<el-tabs v-model="activeTab">
|
||||||
|
<el-tab-pane label="分账明细" name="detail" :lazy="true">
|
||||||
|
<detail v-if="order.orderNo != null"
|
||||||
|
:query="{
|
||||||
|
orderNo: order.orderNo
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 基本信息 -->
|
|
||||||
<div class="info-section">
|
|
||||||
<h3>
|
|
||||||
<i class="el-icon-info"></i>
|
|
||||||
基本信息
|
|
||||||
</h3>
|
|
||||||
<el-descriptions :column="3" border>
|
|
||||||
<el-descriptions-item label="订单号">{{ order.orderNo }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="用户">
|
|
||||||
<router-link :to="`/user/detail/${order.userId}`" class="link-type">
|
|
||||||
{{ order.userName }}
|
|
||||||
</router-link>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="预约时间">
|
|
||||||
<template v-if="order.reserveStartTime && order.reserveEndTime">
|
|
||||||
{{ parseTime(order.reserveStartTime) }} 至 {{ parseTime(order.reserveEndTime) }}
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
--
|
|
||||||
</template>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="房间/设施">
|
|
||||||
<router-link :to="`/system/roomDetail/index/${order.roomId}`" class="link-type">
|
|
||||||
{{ order.roomName }}
|
|
||||||
</router-link>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="店铺">
|
|
||||||
<router-link :to="`/system/storeDetail/index/${order.storeId}`" class="link-type">
|
|
||||||
{{ order.storeName }}
|
|
||||||
</router-link>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="大门">
|
|
||||||
<router-link
|
|
||||||
v-if="order.gateSn"
|
|
||||||
:to="`/system/deviceDetail/index/${order.gateId}`"
|
|
||||||
class="link-type">
|
|
||||||
{{ order.gateSn }}
|
|
||||||
</router-link>
|
|
||||||
</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 用户信息 -->
|
|
||||||
<!-- <div class="info-section">-->
|
|
||||||
<!-- <h3>-->
|
|
||||||
<!-- <i class="el-icon-user"></i>-->
|
|
||||||
<!-- 用户信息-->
|
|
||||||
<!-- </h3>-->
|
|
||||||
<!-- <el-descriptions :column="3" border>-->
|
|
||||||
<!-- <el-descriptions-item label="用户名">-->
|
|
||||||
<!-- <router-link :to="`/user/detail/${order.userId}`" class="link-type">-->
|
|
||||||
<!-- {{ order.userName }}-->
|
|
||||||
<!-- </router-link>-->
|
|
||||||
<!-- </el-descriptions-item>-->
|
|
||||||
<!-- <el-descriptions-item label="用户ID">{{ order.userId }}</el-descriptions-item>-->
|
|
||||||
<!-- </el-descriptions>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
|
|
||||||
<!-- 套餐信息 -->
|
|
||||||
<div class="info-section">
|
|
||||||
<h3>
|
|
||||||
<i class="el-icon-goods"></i>
|
|
||||||
套餐信息
|
|
||||||
</h3>
|
|
||||||
<el-descriptions :column="3" border>
|
|
||||||
<el-descriptions-item label="收费模式">
|
|
||||||
<dict-tag :options="dict.type.ss_fee_rule_mode" :value="order.mode"/>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="套餐名称">{{ order.ruleName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="套餐时长">{{ order.duration }} 小时</el-descriptions-item>
|
|
||||||
<!-- <el-descriptions-item label="套餐ID">{{ order.ruleId }}</el-descriptions-item>-->
|
|
||||||
</el-descriptions>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 设备信息 -->
|
|
||||||
<!-- <div class="info-section">-->
|
|
||||||
<!-- <h3>-->
|
|
||||||
<!-- <i class="el-icon-cpu"></i>-->
|
|
||||||
<!-- 设备信息-->
|
|
||||||
<!-- </h3>-->
|
|
||||||
<!-- <el-descriptions :column="3" border>-->
|
|
||||||
<!-- <el-descriptions-item label="设备MAC">{{ order.deviceMac }}</el-descriptions-item>-->
|
|
||||||
<!-- <el-descriptions-item label="设备SN">{{ order.deviceSn }}</el-descriptions-item>-->
|
|
||||||
<!-- <el-descriptions-item label="设备ID">{{ order.deviceId }}</el-descriptions-item>-->
|
|
||||||
<!-- </el-descriptions>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
|
|
||||||
<!-- 商户信息 -->
|
|
||||||
<div class="info-section">
|
|
||||||
<h3>
|
|
||||||
<i class="el-icon-office-building"></i>
|
|
||||||
商户信息
|
|
||||||
</h3>
|
|
||||||
<el-descriptions :column="3" border>
|
|
||||||
<el-descriptions-item label="商户名称">
|
|
||||||
<router-link :to="`/user/detail/${order.merchantId}`" class="link-type">
|
|
||||||
{{ order.merchantName }}
|
|
||||||
</router-link>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="商户ID">{{ order.merchantId }}</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 支付信息 -->
|
|
||||||
<div class="info-section">
|
|
||||||
<h3>
|
|
||||||
<i class="el-icon-money"></i>
|
|
||||||
支付信息
|
|
||||||
</h3>
|
|
||||||
<el-descriptions :column="3" border>
|
|
||||||
<el-descriptions-item label="支付方式">
|
|
||||||
<dict-tag :options="dict.type.ss_pay_type" :value="order.payType"/>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="支付状态">
|
|
||||||
<dict-tag :options="dict.type.et_order_pay_status" :value="order.paid"/>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="支付时间">
|
|
||||||
{{ parseTime(order.payTime) }}
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="订单金额">{{ order.totalFee | dv }} 元</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="实付金额">{{ order.payFee | dv }} 元</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="手续费">{{ order.handlingCharge | dv }} 元</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="平台服务费">{{ order.platformServiceFee | dv }} 元</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="押金扣除">{{ order.depositDeduction | dv }} 元</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="扣除金额">{{ order.deductionAmount | dv }} 元</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<!-- 标签页 -->
|
|
||||||
<el-card class="box-card detail-tabs" shadow="hover">
|
|
||||||
<el-tabs v-model="activeTab">
|
|
||||||
<el-tab-pane label="分账明细" name="detail" :lazy="true">
|
|
||||||
<detail v-if="order.orderNo != null"
|
|
||||||
:query="{
|
|
||||||
orderNo: order.orderNo
|
|
||||||
}"/>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<!-- 退款弹窗 -->
|
<!-- 退款弹窗 -->
|
||||||
<refund-dialog :show.sync="showRefund" :pay-id="order.payId" :amount="order.payFee" @success="getDetail(orderId)" />
|
<refund-dialog :show.sync="showRefund" :pay-id="order.payId" :amount="order.payFee" @success="getDetail(orderId)" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -180,7 +202,7 @@ import Log from "@/views/system/commandLog/index.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "OrderDetail",
|
name: "OrderDetail",
|
||||||
dicts: ['ss_order_status', 'ss_pay_type', 'et_order_pay_status', 'ss_fee_rule_mode'],
|
dicts: ['ss_order_status', 'ss_pay_type', 'et_order_pay_status', 'ss_fee_rule_mode', 'ss_order_oper_type'],
|
||||||
components: {
|
components: {
|
||||||
Log,
|
Log,
|
||||||
RefundDialog,
|
RefundDialog,
|
||||||
|
@ -238,7 +260,69 @@ export default {
|
||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
},
|
},
|
||||||
|
|
||||||
parseTime
|
/** 获取时间轴节点的类型 */
|
||||||
|
getTimelineItemType(operType) {
|
||||||
|
const typeMap = {
|
||||||
|
'1': 'primary', // 下单
|
||||||
|
'2': 'success', // 支付
|
||||||
|
'3': 'warning', // 更换包间
|
||||||
|
'4': 'info', // 结束订单
|
||||||
|
'6': 'warning', // 退款
|
||||||
|
'7': 'danger', // 用户取消
|
||||||
|
'8': 'danger' // 系统自动取消
|
||||||
|
};
|
||||||
|
return typeMap[operType] || 'info';
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 获取时间轴节点的颜色 */
|
||||||
|
getTimelineItemColor(operType) {
|
||||||
|
const colorMap = {
|
||||||
|
'1': '#409EFF', // 下单 - 蓝色
|
||||||
|
'2': '#67C23A', // 支付 - 绿色
|
||||||
|
'3': '#E6A23C', // 更换包间 - 黄色
|
||||||
|
'4': '#909399', // 结束订单 - 灰色
|
||||||
|
'6': '#E6A23C', // 退款 - 黄色
|
||||||
|
'7': '#F56C6C', // 用户取消 - 红色
|
||||||
|
'8': '#F56C6C' // 系统自动取消 - 红色
|
||||||
|
};
|
||||||
|
return colorMap[operType] || '#909399';
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 获取操作图标 */
|
||||||
|
getOperationIcon(operType) {
|
||||||
|
const iconMap = {
|
||||||
|
'1': 'el-icon-plus', // 下单 - 加号图标
|
||||||
|
'2': 'el-icon-check', // 支付 - 对勾图标
|
||||||
|
'3': 'el-icon-refresh', // 更换包间 - 刷新图标
|
||||||
|
'4': 'el-icon-circle-close', // 结束订单 - 关闭圆圈图标
|
||||||
|
'6': 'el-icon-back', // 退款 - 返回图标
|
||||||
|
'7': 'el-icon-close', // 用户取消 - 关闭图标
|
||||||
|
'8': 'el-icon-warning' // 系统自动取消 - 警告图标
|
||||||
|
};
|
||||||
|
return iconMap[operType] || 'el-icon-info';
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 获取提示内容 */
|
||||||
|
getTooltipContent(activity) {
|
||||||
|
let content = [];
|
||||||
|
|
||||||
|
// 添加操作详情
|
||||||
|
if (activity.details) {
|
||||||
|
content.push(activity.details);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加金额变更信息
|
||||||
|
if (activity.beforeAmount !== activity.afterAmount) {
|
||||||
|
content.push(`金额变更: ${activity.beforeAmount}元 -> ${activity.afterAmount}元`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加操作人信息
|
||||||
|
if (activity.operPhone) {
|
||||||
|
content.push(`操作人: ${activity.operPhone}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return content.join('\n');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -251,6 +335,9 @@ export default {
|
||||||
|
|
||||||
.box-card {
|
.box-card {
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,6 +345,8 @@ export default {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
|
||||||
.header-title {
|
.header-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -278,11 +367,20 @@ export default {
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.info-section {
|
.info-sections {
|
||||||
padding-top: 20px;
|
padding: 0 20px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
box-shadow: 0 1px 4px rgba(0,0,0,0.05);
|
}
|
||||||
|
|
||||||
|
.info-section {
|
||||||
|
padding: 20px 0;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
& + .info-section {
|
||||||
|
border-top: 1px solid #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
margin: 0 0 16px;
|
margin: 0 0 16px;
|
||||||
|
@ -298,10 +396,6 @@ export default {
|
||||||
color: #409EFF;
|
color: #409EFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:first-of-type {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-tabs {
|
.detail-tabs {
|
||||||
|
@ -329,4 +423,102 @@ export default {
|
||||||
padding: 12px 16px;
|
padding: 12px 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.detail-container {
|
||||||
|
width: 100%;
|
||||||
|
min-height: calc(100vh - 132px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-left {
|
||||||
|
.box-card {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-right {
|
||||||
|
|
||||||
|
.history-section {
|
||||||
|
h3 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding0{
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
.history-section {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
:deep(.el-timeline) {
|
||||||
|
padding: 20px;
|
||||||
|
margin: 0 -20px;
|
||||||
|
|
||||||
|
.el-timeline-item__content {
|
||||||
|
.timeline-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operation-type {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: help;
|
||||||
|
opacity: 0.8;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
display: inline-block;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
line-height: 16px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-timeline-item__timestamp {
|
||||||
|
color: #909399;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.4;
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-timeline-item__node {
|
||||||
|
background-color: #fff;
|
||||||
|
border: 2px solid currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-timeline-item__tail {
|
||||||
|
border-left: 2px solid #e4e7ed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 添加全局样式 */
|
||||||
|
:deep(.operation-tooltip) {
|
||||||
|
.el-tooltip__popper {
|
||||||
|
max-width: 300px;
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
div {
|
||||||
|
margin: 4px 0;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
type="success"
|
type="success"
|
||||||
icon="el-icon-unlock"
|
icon="el-icon-unlock"
|
||||||
size="small"
|
size="small"
|
||||||
|
v-if="!isEquipment"
|
||||||
@click="handleOpenDoor"
|
@click="handleOpenDoor"
|
||||||
>开房间门</el-button>
|
>开门</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
icon="el-icon-unlock"
|
icon="el-icon-unlock"
|
||||||
|
@ -342,6 +343,7 @@ import room from "@/views/system/room/index.vue";
|
||||||
import QrCode from '@/components/QrCode'
|
import QrCode from '@/components/QrCode'
|
||||||
import { getDomain } from "@/api/common/common";
|
import { getDomain } from "@/api/common/common";
|
||||||
import Log from "@/views/system/commandLog/index.vue";
|
import Log from "@/views/system/commandLog/index.vue";
|
||||||
|
import { deviceSwitch } from "@/api/system/device";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'RoomDetail',
|
name: 'RoomDetail',
|
||||||
|
@ -402,6 +404,7 @@ export default {
|
||||||
explain: undefined,
|
explain: undefined,
|
||||||
mode: undefined
|
mode: undefined
|
||||||
},
|
},
|
||||||
|
isEquipment: false, // 是否为设施详情
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -411,6 +414,7 @@ export default {
|
||||||
this.getDictData()
|
this.getDictData()
|
||||||
this.getStoreOptions()
|
this.getStoreOptions()
|
||||||
this.getDomain2()
|
this.getDomain2()
|
||||||
|
this.isEquipment = this.$route.query.type === 'equipment';
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -487,18 +491,12 @@ export default {
|
||||||
|
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
handleUpdate() {
|
handleUpdate() {
|
||||||
this.reset();
|
|
||||||
// 深拷贝房间数据
|
|
||||||
this.form = JSON.parse(JSON.stringify(this.room));
|
|
||||||
// 处理图片回显
|
|
||||||
if (Array.isArray(this.form.pictures) && this.form.pictures.length > 0) {
|
|
||||||
this.form.picture = this.form.pictures.join(',');
|
|
||||||
} else {
|
|
||||||
this.form.picture = '';
|
|
||||||
this.form.pictures = [];
|
|
||||||
}
|
|
||||||
this.open = true;
|
this.open = true;
|
||||||
this.title = "修改房间/设施";
|
this.title = "修改" + (this.isEquipment ? "设施" : "房间");
|
||||||
|
this.form = {
|
||||||
|
...this.room,
|
||||||
|
pictures: this.room.pictures || []
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
// 取消按钮
|
// 取消按钮
|
||||||
|
@ -532,38 +530,45 @@ export default {
|
||||||
this.loadRuleList();
|
this.loadRuleList();
|
||||||
},
|
},
|
||||||
|
|
||||||
/** 提交按钮 */
|
/** 表单提交 */
|
||||||
submitForm() {
|
submitForm() {
|
||||||
this.$refs["form"].validate(valid => {
|
this.$refs["form"].validate(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
const submitData = { ...this.form };
|
// 如果是设施且修改了开锁方式,先发送开关命令
|
||||||
// 处理图片数据格式
|
if (this.isEquipment &&
|
||||||
if (submitData.picture) {
|
this.form.deviceId &&
|
||||||
// 将图片数组转换为逗号分隔的字符串
|
this.form.unlockMode !== this.room.unlockMode) {
|
||||||
submitData.pictures = submitData.picture.split(',').filter(Boolean);
|
// 通电开锁(1)时发送断电命令(false),断电开锁(2)时发送通电命令(true)
|
||||||
submitData.picture = submitData.pictures.join(',');
|
const open = this.form.unlockMode === "2";
|
||||||
} else {
|
deviceSwitch({
|
||||||
submitData.pictures = [];
|
deviceId: this.form.deviceId,
|
||||||
submitData.picture = '';
|
open: open
|
||||||
}
|
}).then(() => {
|
||||||
|
// 开关命令成功后,保存配置
|
||||||
updateRoom(submitData).then(response => {
|
this.saveForm();
|
||||||
this.$modal.msgSuccess("修改成功");
|
}).catch(() => {
|
||||||
this.open = false;
|
this.$modal.msgError("设备开关操作失败");
|
||||||
// 更新成功后重新获取详情并刷新页面
|
|
||||||
this.getDetail().then(() => {
|
|
||||||
// 确保图片数据更新到视图
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.$refs.carousel) {
|
|
||||||
this.$refs.carousel.setActiveItem(0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
} else {
|
||||||
|
// 不需要发送开关命令,直接保存
|
||||||
|
this.saveForm();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/** 保存表单 */
|
||||||
|
saveForm() {
|
||||||
|
let data = {
|
||||||
|
...this.form
|
||||||
|
};
|
||||||
|
updateRoom(data).then(response => {
|
||||||
|
this.$modal.msgSuccess("修改成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getDetail();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/** 获取状态对应的类型 */
|
/** 获取状态对应的类型 */
|
||||||
getStatusType(status) {
|
getStatusType(status) {
|
||||||
const statusMap = {
|
const statusMap = {
|
||||||
|
|
|
@ -213,15 +213,17 @@
|
||||||
<!-- 图表和地图区域 -->
|
<!-- 图表和地图区域 -->
|
||||||
<el-row :gutter="20" class="chart-section">
|
<el-row :gutter="20" class="chart-section">
|
||||||
<el-col :span="16">
|
<el-col :span="16">
|
||||||
<el-card class="chart-card" shadow="hover">
|
<el-card class="box-card" shadow="hover">
|
||||||
<div slot="header" class="card-header">
|
<div slot="header" class="card-header">
|
||||||
<span class="title">营收趋势</span>
|
<span>营收趋势</span>
|
||||||
<el-radio-group v-model="chartTimeRange" size="small" @change="handleChartRangeChange">
|
<div class="date-range">
|
||||||
<el-radio-button label="week">近7天</el-radio-button>
|
<el-radio-group v-model="dateRange" size="small" @change="handleDateRangeChange">
|
||||||
<el-radio-button label="month">近30天</el-radio-button>
|
<el-radio-button label="7">近7天</el-radio-button>
|
||||||
</el-radio-group>
|
<el-radio-button label="30">近30天</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-container" ref="incomeChart"></div>
|
<div id="incomeChart" style="width: 100%; height: 400px;"></div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
|
@ -333,7 +335,8 @@ import {
|
||||||
bindGateApi,
|
bindGateApi,
|
||||||
unbindDevice,
|
unbindDevice,
|
||||||
gateAuth,
|
gateAuth,
|
||||||
openGate
|
openGate,
|
||||||
|
updateStore
|
||||||
} from "@/api/system/store";
|
} from "@/api/system/store";
|
||||||
import {getDevice} from "@/api/system/device";
|
import {getDevice} from "@/api/system/device";
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
|
@ -348,6 +351,7 @@ import toilet from '@/views/system/toilet/index.vue';
|
||||||
import BindGateDialog from './components/BindGateDialog.vue';
|
import BindGateDialog from './components/BindGateDialog.vue';
|
||||||
import QrCode from '@/components/QrCode';
|
import QrCode from '@/components/QrCode';
|
||||||
import { getDomain } from "@/api/common/common";
|
import { getDomain } from "@/api/common/common";
|
||||||
|
import { deviceSwitch } from "@/api/system/device";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'StoreDetail',
|
name: 'StoreDetail',
|
||||||
|
@ -400,7 +404,8 @@ export default {
|
||||||
unlockTime: [
|
unlockTime: [
|
||||||
{ required: true, message: "请输入开锁时长", trigger: "blur" }
|
{ required: true, message: "请输入开锁时长", trigger: "blur" }
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
dateRange: '7', // 默认7天
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
@ -418,6 +423,12 @@ export default {
|
||||||
this.$refs.incomeChart.addEventListener('scroll', this.handleScroll);
|
this.$refs.incomeChart.addEventListener('scroll', this.handleScroll);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// 监听窗口大小变化,重绘图表
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
if (this.incomeChart) {
|
||||||
|
this.incomeChart.resize();
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
if (this.incomeChart) {
|
if (this.incomeChart) {
|
||||||
|
@ -428,7 +439,7 @@ export default {
|
||||||
this.map.destroy();
|
this.map.destroy();
|
||||||
this.map = null;
|
this.map = null;
|
||||||
}
|
}
|
||||||
window.removeEventListener('resize', this.resizeChart);
|
window.removeEventListener('resize', this.handleResize);
|
||||||
if (this.$refs.incomeChart) {
|
if (this.$refs.incomeChart) {
|
||||||
this.$refs.incomeChart.removeEventListener('scroll', this.handleScroll);
|
this.$refs.incomeChart.removeEventListener('scroll', this.handleScroll);
|
||||||
}
|
}
|
||||||
|
@ -529,21 +540,30 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getStoreData() {
|
getStoreData() {
|
||||||
getStore(this.storeId).then(response => {
|
// 格式化日期
|
||||||
|
const formatDate = (date) => {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取时间范围
|
||||||
|
const end = new Date();
|
||||||
|
const start = new Date();
|
||||||
|
start.setDate(start.getDate() - Number(this.dateRange));
|
||||||
|
|
||||||
|
// 构建请求参数
|
||||||
|
const params = {
|
||||||
|
startTime: formatDate(start),
|
||||||
|
endTime: formatDate(end)
|
||||||
|
};
|
||||||
|
|
||||||
|
getStore(this.storeId, params).then(response => {
|
||||||
this.storeData = response.data;
|
this.storeData = response.data;
|
||||||
this.gateForm = {
|
// 初始化收入趋势图表
|
||||||
unlockMode: response.data.unlockMode || "1",
|
|
||||||
unlockCondition: response.data.unlockCondition || "3",
|
|
||||||
unlockTime: response.data.unlockTime || 0
|
|
||||||
};
|
|
||||||
// 重新初始化地图
|
|
||||||
if (this.map) {
|
|
||||||
this.map.clearMap();
|
|
||||||
this.map.destroy();
|
|
||||||
this.map = null;
|
|
||||||
}
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.initMap();
|
this.initIncomeChart();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -698,26 +718,141 @@ export default {
|
||||||
submitGateConfig() {
|
submitGateConfig() {
|
||||||
this.$refs["gateForm"].validate(valid => {
|
this.$refs["gateForm"].validate(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
gateAuth({
|
// 先发送开关命令
|
||||||
storeId: this.storeData.storeId,
|
if (this.storeData.gateId) {
|
||||||
unlockMode: this.gateForm.unlockMode,
|
// 通电开锁(1)时发送断电命令(false),断电开锁(2)时发送通电命令(true)
|
||||||
unlockCondition: this.gateForm.unlockCondition,
|
const open = this.gateForm.unlockMode === "2";
|
||||||
unlockTime: this.gateForm.unlockTime
|
deviceSwitch({
|
||||||
}).then(() => {
|
deviceId: this.storeData.gateId,
|
||||||
this.$modal.msgSuccess("配置成功");
|
open: open
|
||||||
this.gateConfigVisible = false;
|
}).then(() => {
|
||||||
this.getStoreData(); // 刷新店铺数据
|
// 开关命令成功后,保存配置
|
||||||
});
|
this.saveGateConfig();
|
||||||
|
}).catch(() => {
|
||||||
|
this.$modal.msgError("设备开关操作失败");
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.$modal.msgError("未找到大门设备");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/** 保存大门配置 */
|
||||||
|
saveGateConfig() {
|
||||||
|
gateAuth({
|
||||||
|
storeId: this.storeData.storeId,
|
||||||
|
unlockMode: this.gateForm.unlockMode,
|
||||||
|
unlockCondition: this.gateForm.unlockCondition,
|
||||||
|
unlockTime: this.gateForm.unlockTime
|
||||||
|
}).then(() => {
|
||||||
|
this.$modal.msgSuccess("配置成功");
|
||||||
|
this.gateConfigVisible = false;
|
||||||
|
this.getStoreData(); // 刷新店铺数据
|
||||||
|
});
|
||||||
|
},
|
||||||
handleOpenGate() {
|
handleOpenGate() {
|
||||||
this.$modal.confirm('是否确认为"' + this.storeData.name + '"开门?').then(() => {
|
this.$modal.confirm('是否确认为"' + this.storeData.name + '"开门?').then(() => {
|
||||||
return openGate(this.storeData.storeId);
|
return openGate(this.storeData.storeId);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$modal.msgSuccess("开门成功");
|
this.$modal.msgSuccess("开门成功");
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
}
|
},
|
||||||
|
/** 初始化收入趋势图表 */
|
||||||
|
initIncomeChart() {
|
||||||
|
if (this.incomeChart) {
|
||||||
|
this.incomeChart.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.incomeChart = echarts.init(document.getElementById('incomeChart'));
|
||||||
|
|
||||||
|
// 处理数据
|
||||||
|
const days = this.storeData.inComeList.map(item => {
|
||||||
|
// 将日期格式从 "2025-01-19" 转换为 "01-19"
|
||||||
|
return item.day.substring(5); // 从第5个字符开始截取,去掉年份
|
||||||
|
});
|
||||||
|
const incomes = this.storeData.inComeList.map(item => item.orderIncome);
|
||||||
|
const orderNums = this.storeData.inComeList.map(item => item.orderNum || 0);
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['营收金额', '订单数量']
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: days,
|
||||||
|
axisLabel: {
|
||||||
|
rotate: 45
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
name: '营收金额(元)',
|
||||||
|
position: 'left'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
name: '订单数量',
|
||||||
|
position: 'right'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '营收金额',
|
||||||
|
type: 'line',
|
||||||
|
smooth: true,
|
||||||
|
data: incomes,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#409EFF'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '订单数量',
|
||||||
|
type: 'bar',
|
||||||
|
yAxisIndex: 1,
|
||||||
|
data: orderNums,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#67C23A'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
this.incomeChart.setOption(option);
|
||||||
|
},
|
||||||
|
/** 切换日期范围 */
|
||||||
|
handleDateRangeChange(days) {
|
||||||
|
this.dateRange = days;
|
||||||
|
const end = new Date();
|
||||||
|
const start = new Date();
|
||||||
|
start.setDate(start.getDate() - days);
|
||||||
|
|
||||||
|
// 格式化日期
|
||||||
|
const formatDate = (date) => {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 使用 getStoreData 方法获取数据
|
||||||
|
this.getStoreData({
|
||||||
|
startTime: formatDate(start),
|
||||||
|
endTime: formatDate(end)
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -836,42 +971,6 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-descriptions) {
|
|
||||||
padding: 20px;
|
|
||||||
background-color: #fff;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
|
|
||||||
|
|
||||||
.el-descriptions__label {
|
|
||||||
font-weight: 500;
|
|
||||||
color: #606266;
|
|
||||||
min-width: 90px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-descriptions__content {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-descriptions__body {
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-descriptions-item__label {
|
|
||||||
background-color: #f5f7fa;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-descriptions-item__content {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-text {
|
|
||||||
color: #606266;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-card {
|
.info-card {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
@ -1120,4 +1219,16 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-range {
|
||||||
|
.el-radio-group {
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -247,6 +247,7 @@ import { listStore } from "@/api/system/store";
|
||||||
import { $showColumns } from '@/utils/mixins';
|
import { $showColumns } from '@/utils/mixins';
|
||||||
import QrCode from "@/components/QrCode/index.vue";
|
import QrCode from "@/components/QrCode/index.vue";
|
||||||
import { getDomain } from "@/api/common/common";
|
import { getDomain } from "@/api/common/common";
|
||||||
|
import { deviceSwitch } from "@/api/system/device";
|
||||||
|
|
||||||
// 默认排序字段
|
// 默认排序字段
|
||||||
const defaultSort = {
|
const defaultSort = {
|
||||||
|
@ -326,7 +327,9 @@ export default {
|
||||||
rules: {
|
rules: {
|
||||||
},
|
},
|
||||||
// 店铺选项
|
// 店铺选项
|
||||||
storeOptions: []
|
storeOptions: [],
|
||||||
|
// 保存旧的开锁方式,用于比较是否修改
|
||||||
|
oldForm: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
@ -414,6 +417,8 @@ export default {
|
||||||
const toiletId = row.toiletId || this.ids
|
const toiletId = row.toiletId || this.ids
|
||||||
getToilet(toiletId).then(response => {
|
getToilet(toiletId).then(response => {
|
||||||
this.form = response.data;
|
this.form = response.data;
|
||||||
|
// 保存旧的开锁方式,用于比较是否修改
|
||||||
|
this.oldForm = { ...response.data };
|
||||||
this.open = true;
|
this.open = true;
|
||||||
this.title = "修改卫生间";
|
this.title = "修改卫生间";
|
||||||
});
|
});
|
||||||
|
@ -422,22 +427,47 @@ export default {
|
||||||
submitForm() {
|
submitForm() {
|
||||||
this.$refs["form"].validate(valid => {
|
this.$refs["form"].validate(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (this.form.toiletId != null) {
|
// 如果修改了开锁方式,先发送开关命令
|
||||||
updateToilet(this.form).then(response => {
|
if (this.form.deviceId &&
|
||||||
this.$modal.msgSuccess("修改成功");
|
this.form.unlockMode !== this.oldForm?.unlockMode) {
|
||||||
this.open = false;
|
// 通电开锁(1)时发送断电命令(false),断电开锁(2)时发送通电命令(true)
|
||||||
this.getList();
|
const open = this.form.unlockMode === "2";
|
||||||
|
deviceSwitch({
|
||||||
|
deviceId: this.form.deviceId,
|
||||||
|
open: open
|
||||||
|
}).then(() => {
|
||||||
|
// 开关命令成功后,保存配置
|
||||||
|
this.saveForm();
|
||||||
|
}).catch(() => {
|
||||||
|
this.$modal.msgError("设备开关操作失败");
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
addToilet(this.form).then(response => {
|
// 不需要发送开关命令,直接保存
|
||||||
this.$modal.msgSuccess("新增成功");
|
this.saveForm();
|
||||||
this.open = false;
|
|
||||||
this.getList();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/** 保存表单 */
|
||||||
|
saveForm() {
|
||||||
|
let data = {
|
||||||
|
...this.form
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.form.toiletId != null) {
|
||||||
|
updateToilet(data).then(response => {
|
||||||
|
this.$modal.msgSuccess("修改成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addToilet(data).then(response => {
|
||||||
|
this.$modal.msgSuccess("新增成功");
|
||||||
|
this.open = false;
|
||||||
|
this.getList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
/** 删除按钮操作 */
|
/** 删除按钮操作 */
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
const toiletIds = row.toiletId || this.ids;
|
const toiletIds = row.toiletId || this.ids;
|
||||||
|
|
|
@ -31,9 +31,9 @@
|
||||||
<div>用户详情</div>
|
<div>用户详情</div>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row type="flex" justify="end" class="mb-2">
|
<el-row type="flex" justify="end" class="mb-2">
|
||||||
<el-button type="primary" icon="el-icon-edit" size="mini" @click="handleUpdate"
|
<!-- <el-button type="primary" icon="el-icon-edit" size="mini" @click="handleUpdate"
|
||||||
v-hasPermi="['system:smUser:edit']">修改</el-button>
|
v-hasPermi="['system:smUser:edit']">修改</el-button>-->
|
||||||
<el-button type="primary" icon="el-icon-setting" size="mini" @click="handleUpdateRisk"
|
<el-button type="text" icon="el-icon-setting" size="mini" @click="handleUpdateRisk"
|
||||||
v-hasPermi="['system:smUser:edit']">配置</el-button>
|
v-hasPermi="['system:smUser:edit']">配置</el-button>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
@ -93,7 +93,7 @@
|
||||||
<div class="filter-section">
|
<div class="filter-section">
|
||||||
<el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期"
|
<el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期"
|
||||||
end-placeholder="结束日期" :picker-options="pickerOptions" value-format="yyyy-MM-dd"
|
end-placeholder="结束日期" :picker-options="pickerOptions" value-format="yyyy-MM-dd"
|
||||||
@change="loadDailyReport" />
|
@change="handleDateRangeChange" />
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-container">
|
<div class="chart-container">
|
||||||
<div ref="dailyChart" style="width: 100%; height: 300px"></div>
|
<div ref="dailyChart" style="width: 100%; height: 300px"></div>
|
||||||
|
@ -461,10 +461,36 @@ export default {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleDateRangeChange(dates) {
|
||||||
|
if (!dates) {
|
||||||
|
// 如果清空日期,使用默认7天
|
||||||
|
const end = new Date();
|
||||||
|
const start = new Date();
|
||||||
|
start.setDate(start.getDate() - 7);
|
||||||
|
this.dateRange = [this.formatDate(start), this.formatDate(end)];
|
||||||
|
} else {
|
||||||
|
// dates 是一个数组 [startDate, endDate]
|
||||||
|
this.dateRange = dates;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 getDetail 方法获取数据
|
||||||
|
this.getDetail();
|
||||||
|
},
|
||||||
|
|
||||||
getDetail() {
|
getDetail() {
|
||||||
|
// 构建请求参数
|
||||||
|
const params = {
|
||||||
|
startDate: this.dateRange[0],
|
||||||
|
endDate: this.dateRange[1]
|
||||||
|
};
|
||||||
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
getUser(this.$route.params.userId).then(response => {
|
getUser(this.$route.params.userId, params).then(response => {
|
||||||
this.detail = response.data;
|
this.detail = response.data;
|
||||||
|
// 初始化收入趋势图表
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.initDailyChart();
|
||||||
|
});
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
|
@ -534,20 +560,36 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
loadDailyReport() {
|
loadDailyReport() {
|
||||||
this.dailyReportData = Array.from({ length: 7 }, (_, i) => {
|
if (!this.dateRange) return;
|
||||||
const date = new Date();
|
|
||||||
date.setDate(date.getDate() - i);
|
// 格式化日期参数
|
||||||
return {
|
const [startDate, endDate] = this.dateRange;
|
||||||
date: this.formatDate(date),
|
|
||||||
rechargeAmount: Math.floor(Math.random() * 10000),
|
// 获取用户数据,传入日期参数
|
||||||
consumeAmount: Math.floor(Math.random() * 8000),
|
getUser(this.$route.params.userId, {
|
||||||
orderCount: Math.floor(Math.random() * 100)
|
startDate,
|
||||||
};
|
endDate
|
||||||
}).reverse();
|
}).then(response => {
|
||||||
|
this.detail = response.data;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.initDailyChart();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
initDailyChart() {
|
||||||
|
if (!this.dailyChart) {
|
||||||
|
this.dailyChart = echarts.init(this.$refs.dailyChart);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 API 返回的数据
|
||||||
|
const days = this.detail.inComeList.map(item => item.day.substring(5)); // 只显示 MM-dd
|
||||||
|
const incomes = this.detail.inComeList.map(item => item.orderIncome);
|
||||||
|
const orderNums = this.detail.inComeList.map(item => item.orderNum);
|
||||||
|
|
||||||
const option = {
|
const option = {
|
||||||
title: {
|
title: {
|
||||||
text: '日报表统计'
|
text: '收入统计'
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
|
@ -556,7 +598,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
data: ['充值金额', '消费金额', '订单数']
|
data: ['收入金额']
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
left: '3%',
|
left: '3%',
|
||||||
|
@ -566,47 +608,45 @@ export default {
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
data: this.dailyReportData.map(item => item.date)
|
boundaryGap: true,
|
||||||
|
data: days,
|
||||||
|
axisLabel: {
|
||||||
|
rotate: 45
|
||||||
|
}
|
||||||
},
|
},
|
||||||
yAxis: [
|
yAxis: {
|
||||||
{
|
type: 'value',
|
||||||
type: 'value',
|
axisLabel: {
|
||||||
name: '金额',
|
formatter: '{value}元'
|
||||||
axisLabel: {
|
|
||||||
formatter: '{value} 元'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
splitLine: {
|
||||||
type: 'value',
|
show: true,
|
||||||
name: '订单数',
|
lineStyle: {
|
||||||
axisLabel: {
|
type: 'dashed'
|
||||||
formatter: '{value}'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '充值金额',
|
name: '收入金额',
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
data: this.dailyReportData.map(item => item.rechargeAmount)
|
itemStyle: {
|
||||||
},
|
normal: {
|
||||||
{
|
color: '#409EFF',
|
||||||
name: '消费金额',
|
barBorderRadius: [4, 4, 0, 0]
|
||||||
type: 'bar',
|
}
|
||||||
data: this.dailyReportData.map(item => item.consumeAmount)
|
},
|
||||||
},
|
data: incomes,
|
||||||
{
|
label: {
|
||||||
name: '订单数',
|
show: true,
|
||||||
type: 'line',
|
position: 'top',
|
||||||
yAxisIndex: 1,
|
formatter: '{c}元'
|
||||||
data: this.dailyReportData.map(item => item.orderCount)
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.dailyChart) {
|
this.dailyChart.setOption(option);
|
||||||
this.dailyChart.setOption(option);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
loadMonthlyReport() {
|
loadMonthlyReport() {
|
||||||
|
@ -827,7 +867,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.report-container {
|
.report-container {
|
||||||
padding: 15px;
|
padding: 15px 15px 15px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-section {
|
.filter-section {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user