1031 lines
31 KiB
Vue
1031 lines
31 KiB
Vue
<script setup lang="ts">
|
||
import { Goods, Shop, Document, Money } from '@element-plus/icons-vue';
|
||
import { getStats, TodayLatestOrderGoodsDTO, TopGoodsDTO } from '@/api/shop/stats';
|
||
import { getShopListApi, ShopDTO, getModeText } from '@/api/shop/shop';
|
||
import { getBorrowReturnDynamicListApi, BorrowReturnDynamicDTO } from '@/api/shop/order';
|
||
import { markRaw, onMounted, ref } from 'vue';
|
||
import { useWxStore } from '@/store/modules/wx';
|
||
import { ElDialog, ElForm, ElFormItem, ElInput, ElMessage } from 'element-plus';
|
||
import { bindQyUserApi } from '@/api/ab98/user';
|
||
import qrcode from '@/assets/qrcode.png';
|
||
import { getBasicInfoByCorpidApi } from '@/api/qy/corp';
|
||
import { storeToRefs } from 'pinia';
|
||
|
||
defineOptions({
|
||
name: "Welcome"
|
||
});
|
||
|
||
const wxStore = useWxStore();
|
||
|
||
const { authCorpBasicInfo } = storeToRefs(wxStore);
|
||
|
||
const shopList = ref<ShopDTO[]>([]);
|
||
const currentShop = ref<ShopDTO | null>(null);
|
||
const selectedShopId = ref<number | null>(null);
|
||
|
||
const shopData = ref<{
|
||
name: string;
|
||
icon: any; // 假设这里是 Element Plus 的图标组件
|
||
value: number;
|
||
}[]>([
|
||
]);
|
||
|
||
const unReturnedData = ref([
|
||
{ name: '未还商品', value: 0 },
|
||
{ name: '未还订单', value: 0 },
|
||
{ name: '未还金额', value: 0 }
|
||
]);
|
||
|
||
const deviceData = ref([
|
||
{ name: '总柜子', value: 0 },
|
||
{ name: '总格口', value: 0 },
|
||
{ name: '已关联', value: 0 },
|
||
{ name: '未关联', value: 0 },
|
||
{ name: '网关', value: 0 }
|
||
]);
|
||
|
||
const topGoods = ref<TopGoodsDTO[]>([]);
|
||
const todayLatestOrderGoods = ref<TodayLatestOrderGoodsDTO[]>([]);
|
||
const maxOccurrenceCount = ref(0);
|
||
|
||
// 借还动态数据
|
||
const borrowReturnDynamicList = ref<BorrowReturnDynamicDTO[]>([]);
|
||
const loading = ref(false);
|
||
|
||
const showDialog = ref(false);
|
||
const form = ref({ name: '', idCard: '' });
|
||
|
||
const rules = {
|
||
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
|
||
idCard: [
|
||
{ required: true, message: '请输入身份证号', trigger: 'blur' },
|
||
{ pattern: /^\d{17}[\dXx]$/, message: '身份证格式不正确', trigger: 'blur' }
|
||
]
|
||
};
|
||
|
||
const handleSubmit = async () => {
|
||
try {
|
||
const { data } = await bindQyUserApi({
|
||
qyUserId: wxStore.qyUser?.id,
|
||
name: form.value.name,
|
||
idNum: form.value.idCard
|
||
});
|
||
ElMessage.success('绑定成功');
|
||
showDialog.value = false;
|
||
} catch (error) {
|
||
ElMessage.error(error.message || '绑定失败');
|
||
}
|
||
};
|
||
|
||
const handleShopChange = (shopId: number) => {
|
||
const selectedShop = shopList.value.find(shop => shop.shopId === shopId);
|
||
if (selectedShop) {
|
||
currentShop.value = selectedShop;
|
||
// 重新获取选中商店的统计数据
|
||
fetchShopStats();
|
||
}
|
||
};
|
||
|
||
const fetchShopStats = async () => {
|
||
if (!currentShop.value) return;
|
||
|
||
try {
|
||
const { data } = await getStats(wxStore.corpid);
|
||
shopData.value = [
|
||
{ name: '商店', icon: markRaw(Shop), value: data.shopCount },
|
||
{ name: '商品总数量', icon: markRaw(Goods), value: data.goodsCount },
|
||
{ name: '商品总订单', icon: markRaw(Document), value: data.orderCount },
|
||
{ name: '商品总金额', icon: markRaw(Money), value: data.goodsTotalAmount }
|
||
];
|
||
unReturnedData.value = [
|
||
{ name: '未还商品', value: data.unReturnedGoodsCount },
|
||
{ name: '未还订单', value: data.unReturnedOrderCount },
|
||
{ name: '未还金额', value: data.unReturnedAmount }
|
||
];
|
||
deviceData.value = [
|
||
{ name: '总柜子', value: data.cabinetCount },
|
||
{ name: '总格口', value: data.cellCount },
|
||
{ name: '已关联', value: data.linkedCellCount },
|
||
{ name: '未关联', value: data.unmanagedCellCount },
|
||
{ name: '网关', value: data.gatewayCount }
|
||
];
|
||
topGoods.value = data.topGoods;
|
||
todayLatestOrderGoods.value = data.todayLatestOrderGoods;
|
||
maxOccurrenceCount.value = Math.max(...data.topGoods.map(item => item.occurrenceCount), 1);
|
||
} catch (error) {
|
||
console.error('获取统计数据失败:', error);
|
||
}
|
||
};
|
||
|
||
const fetchShopList = async () => {
|
||
try {
|
||
const { data } = await getShopListApi({ corpid: wxStore.corpid });
|
||
shopList.value = data;
|
||
if (data.length > 0) {
|
||
currentShop.value = data[0];
|
||
selectedShopId.value = data[0].shopId;
|
||
}
|
||
} catch (error) {
|
||
console.error('获取商店列表失败:', error);
|
||
}
|
||
};
|
||
|
||
const fetchCorpBasicInfo = async () => {
|
||
try {
|
||
const { data } = await getBasicInfoByCorpidApi(wxStore.corpid);
|
||
if (data) {
|
||
// 更新企业基本信息
|
||
wxStore.setAuthCorpBasicInfo(data);
|
||
}
|
||
} catch (error) {
|
||
console.error('获取企业基本信息失败:', error);
|
||
ElMessage.error('获取企业基本信息失败');
|
||
}
|
||
};
|
||
|
||
// 获取借还动态数据
|
||
const fetchBorrowReturnDynamic = async () => {
|
||
loading.value = true;
|
||
try {
|
||
const { data } = await getBorrowReturnDynamicListApi({
|
||
pageNum: 1,
|
||
pageSize: 20
|
||
});
|
||
if (data && data.rows) {
|
||
borrowReturnDynamicList.value = data.rows;
|
||
}
|
||
} catch (error) {
|
||
console.error('获取借还动态失败:', error);
|
||
ElMessage.error('获取借还动态失败');
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
// 格式化时间显示
|
||
const formatTime = (time: Date | string) => {
|
||
if (!time) return '';
|
||
const date = new Date(time);
|
||
return date.toLocaleString('zh-CN', {
|
||
month: '2-digit',
|
||
day: '2-digit',
|
||
hour: '2-digit',
|
||
minute: '2-digit'
|
||
});
|
||
};
|
||
|
||
// 获取动态类型图标
|
||
const getDynamicTypeIcon = (dynamicType: number) => {
|
||
return dynamicType === 0 ? 'el-icon-shopping-bag-1' : 'el-icon-refresh';
|
||
};
|
||
|
||
// 获取动态类型颜色
|
||
const getDynamicTypeColor = (dynamicType: number) => {
|
||
return dynamicType === 0 ? '#409EFF' : '#67C23A';
|
||
};
|
||
|
||
// 获取状态颜色
|
||
const getStatusColor = (status?: number) => {
|
||
if (status === undefined) return '#909399';
|
||
switch (status) {
|
||
case 0: return '#909399'; // 未退还
|
||
case 1: return '#E6A23C'; // 待审批
|
||
case 2: return '#67C23A'; // 已通过
|
||
case 3: return '#F56C6C'; // 已驳回
|
||
case 4: return '#409EFF'; // 开柜中
|
||
default: return '#909399';
|
||
}
|
||
};
|
||
|
||
// 处理图片字符串,将逗号分隔的图片URL转换为数组
|
||
const parseImages = (images?: string): string[] => {
|
||
if (!images) return [];
|
||
return images.split(',').map(img => img.trim()).filter(img => img.length > 0);
|
||
};
|
||
|
||
onMounted(async () => {
|
||
await fetchShopList();
|
||
// 获取企业基本信息
|
||
await fetchCorpBasicInfo();
|
||
|
||
try {
|
||
const { data } = await getStats(wxStore.corpid);
|
||
shopData.value = [
|
||
{ name: '商店', icon: markRaw(Shop), value: data.shopCount },
|
||
{ name: '商品总数量', icon: markRaw(Goods), value: data.goodsCount },
|
||
{ name: '商品总订单', icon: markRaw(Document), value: data.orderCount },
|
||
{ name: '商品总金额', icon: markRaw(Money), value: data.goodsTotalAmount }
|
||
];
|
||
unReturnedData.value = [
|
||
{ name: '未还商品', value: data.unReturnedGoodsCount },
|
||
{ name: '未还订单', value: data.unReturnedOrderCount },
|
||
{ name: '未还金额', value: data.unReturnedAmount }
|
||
];
|
||
deviceData.value = [
|
||
{ name: '总柜子', value: data.cabinetCount },
|
||
{ name: '总格口', value: data.cellCount },
|
||
{ name: '已关联', value: data.linkedCellCount },
|
||
{ name: '未关联', value: data.unmanagedCellCount },
|
||
{ name: '网关', value: data.gatewayCount }
|
||
];
|
||
topGoods.value = data.topGoods;
|
||
todayLatestOrderGoods.value = data.todayLatestOrderGoods;
|
||
maxOccurrenceCount.value = Math.max(...data.topGoods.map(item => item.occurrenceCount), 1);
|
||
} catch (error) {
|
||
console.error('获取统计数据失败:', error);
|
||
}
|
||
|
||
// 获取借还动态数据
|
||
await fetchBorrowReturnDynamic();
|
||
|
||
if (wxStore.qyUser && !wxStore.qyUser.ab98UserId) {
|
||
showDialog.value = true;
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<div class="welcome-container">
|
||
<el-row :gutter="12">
|
||
<el-col :span="17">
|
||
<!-- 商店选择容器 -->
|
||
<div class="section-container shop-selection-container" v-if="currentShop">
|
||
<div class="section-title">
|
||
<div class="title-bar"></div>
|
||
<div class="title-text">商家信息</div>
|
||
</div>
|
||
<div class="shop-content">
|
||
<div class="shop-info">
|
||
<el-image :src="currentShop.coverImg || '/src/assets/login/login-bg.png'" fit="cover"
|
||
class="shop-image" />
|
||
<div class="shop-details">
|
||
<div class="shop-name-container">
|
||
<h3 class="shop-name">{{ authCorpBasicInfo?.corpName || '' }}</h3>
|
||
<!-- <el-select
|
||
v-model="selectedShopId"
|
||
placeholder="选择商店"
|
||
class="shop-selector"
|
||
@change="handleShopChange"
|
||
>
|
||
<el-option
|
||
v-for="shop in shopList"
|
||
:key="shop.shopId"
|
||
:label="shop.shopName"
|
||
:value="shop.shopId"
|
||
/>
|
||
</el-select> -->
|
||
</div>
|
||
<!-- <p class="shop-mode">{{ getModeText(currentShop.mode) }}</p> -->
|
||
</div>
|
||
</div>
|
||
<div class="shop-qrcode">
|
||
<el-image :src="qrcode" fit="contain" class="qrcode-image" />
|
||
<p class="qrcode-text">扫码进入小程序</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 待办事项 -->
|
||
<div class="section-container todo-container">
|
||
<div class="section-title">
|
||
<div class="title-bar"></div>
|
||
<div class="title-text">数据统计</div>
|
||
</div>
|
||
<el-row :gutter="12" class="todo-section">
|
||
<el-col :span="6" v-for="item in shopData" :key="item.name">
|
||
<el-card shadow="never" class="todo-card">
|
||
<div class="todo-content">
|
||
<el-icon :size="30" class="todo-icon">
|
||
<component :is="item.icon" />
|
||
</el-icon>
|
||
<div class="todo-count">{{ item.value }}</div>
|
||
<div class="todo-name">{{ item.name }}</div>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
</div>
|
||
|
||
<el-row :gutter="12">
|
||
<el-col :span="12">
|
||
<div class="section-container shop-container">
|
||
<div class="section-title">
|
||
<div class="title-bar"></div>
|
||
<div class="title-text">未还统计</div>
|
||
</div>
|
||
<el-row :gutter="12" class="data-section">
|
||
<!-- 商店数据 -->
|
||
<el-col :span="8" v-for="item in unReturnedData" :key="item.name">
|
||
<el-card shadow="never" :body-style="{ padding: ' 20px 0' }" class="todo-card">
|
||
<div class="todo-content">
|
||
<div class="todo-count">{{ item.value }}</div>
|
||
<div class="todo-name">{{ item.name }}</div>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
</div>
|
||
</el-col>
|
||
|
||
<!-- 智能设备 -->
|
||
<el-col :span="12">
|
||
<div class="section-container device-container">
|
||
<div class="section-title">
|
||
<div class="title-bar"></div>
|
||
<div class="title-text">智能设备</div>
|
||
</div>
|
||
<el-row :gutter="12" class="data-section">
|
||
<el-col :span="4" v-for="item in deviceData" :key="item.name">
|
||
<el-card shadow="never" :body-style="{ padding: ' 20px 0' }" class="todo-card">
|
||
<div class="todo-content">
|
||
<div class="todo-count">{{ item.value }}</div>
|
||
<div class="todo-name">{{ item.name }}</div>
|
||
</div>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
</div>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<!-- 商品信息 -->
|
||
<el-row :gutter="12">
|
||
|
||
<!-- 今日最新订单 -->
|
||
<!--
|
||
<el-col :span="12">
|
||
<div class="section-container order-container">
|
||
<div class="section-title">
|
||
<div class="title-bar"></div>
|
||
<div class="title-text">今日数据</div>
|
||
</div>
|
||
<div class="goods-list">
|
||
<el-card shadow="never" class="goods-item" v-for="item in todayLatestOrderGoods"
|
||
:key="item.orderGoodsId" :body-style="{ padding: '0' }">
|
||
<div class="goods-item-content">
|
||
<div class="goods-left">
|
||
<el-image :src="item.coverImg" fit="contain" class="goods-image" />
|
||
<div class="goods-name">{{ item.goodsName }}</div>
|
||
</div>
|
||
<div class="goods-right">
|
||
<div class="goods-count">数量:{{ item.quantity }}</div>
|
||
<div class="goods-count">{{ item.totalAmount }}元</div>
|
||
<div class="goods-count buyer-name">{{ item.buyerName }}</div>
|
||
<div class="goods-count">{{ item.createTimeStr }}</div>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</div>
|
||
</div>
|
||
</el-col>
|
||
-->
|
||
</el-row>
|
||
</el-col>
|
||
<!-- 热门商品 -->
|
||
<!-- <el-col :span="7">
|
||
<div class="section-container goods-container">
|
||
<div class="section-title">
|
||
<div class="title-bar"></div>
|
||
<div class="title-text">借还排行</div>
|
||
</div>
|
||
<div class="goods-list">
|
||
<el-card shadow="never" class="goods-item" v-for="item in topGoods" :key="item.goodsId"
|
||
:body-style="{ padding: '0' }">
|
||
<div class="goods-item-content">
|
||
<div class="goods-left">
|
||
<el-image :src="item.coverImg" fit="contain" class="goods-image" />
|
||
<div class="goods-name">{{ item.goodsName }}</div>
|
||
</div>
|
||
<div class="goods-right">
|
||
<el-progress :percentage="(item.occurrenceCount / maxOccurrenceCount) * 100" :show-text="false"
|
||
:stroke-width="12" class="goods-progress" />
|
||
<div class="goods-count">{{ item.occurrenceCount }}次</div>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</div>
|
||
</div>
|
||
</el-col> -->
|
||
<!-- 借还动态 -->
|
||
<el-col :span="7">
|
||
<div class="section-container dynamic-container">
|
||
<div class="section-title">
|
||
<div class="title-bar"></div>
|
||
<div class="title-text">借还动态</div>
|
||
</div>
|
||
<div class="dynamic-content">
|
||
<el-timeline v-if="borrowReturnDynamicList.length > 0" class="dynamic-timeline">
|
||
<el-timeline-item v-for="item in borrowReturnDynamicList"
|
||
:key="`${item.orderGoodsId}-${item.dynamicType}`"
|
||
:timestamp="formatTime(item.dynamicType === 0 ? item.orderTime : item.operateTime)" placement="top"
|
||
:color="getDynamicTypeColor(item.dynamicType)">
|
||
<el-card shadow="hover" class="dynamic-card">
|
||
<div class="dynamic-card-content">
|
||
<div class="dynamic-header">
|
||
<el-icon :color="getDynamicTypeColor(item.dynamicType)" class="dynamic-icon">
|
||
<component :is="getDynamicTypeIcon(item.dynamicType)" />
|
||
</el-icon>
|
||
<span class="dynamic-type" :style="{ color: getDynamicTypeColor(item.dynamicType) }">
|
||
{{ item.dynamicTypeStr }}
|
||
</span>
|
||
<el-tag v-if="item.dynamicType === 1 && item.status !== undefined"
|
||
:color="getStatusColor(item.status)" size="small" class="status-tag">
|
||
{{ item.statusStr }}
|
||
</el-tag>
|
||
</div>
|
||
|
||
<div class="dynamic-info">
|
||
<!-- 商品图片和基本信息 -->
|
||
<div class="goods-info">
|
||
<el-image v-if="item.coverImg" :src="item.coverImg" fit="cover" class="goods-image"
|
||
:preview-src-list="[item.coverImg]" preview-teleported>
|
||
<template #error>
|
||
<div class="image-error">图片加载失败</div>
|
||
</template>
|
||
</el-image>
|
||
<div class="goods-details">
|
||
<span class="goods-name">{{ item.goodsName }}</span>
|
||
<span class="goods-price">¥{{ item.goodsPrice }}</span>
|
||
<div class="user-info">
|
||
<span class="user-name">{{ item.orderName }}</span>
|
||
<span class="user-mobile">{{ item.orderMobile }}</span>
|
||
</div>
|
||
<div class="location-info">
|
||
<span class="cabinet-name">{{ item.cabinetName }}</span>
|
||
<span class="cell-no">格口{{ item.cellNo }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div v-if="item.dynamicType === 1" class="approval-info">
|
||
<!-- 图片区域 - 归还图片和审核图片放在同一行 -->
|
||
<div class="images-row" v-if="item.images || item.auditImages">
|
||
<!-- 归还图片 -->
|
||
<div v-if="item.images" class="images-section">
|
||
<div class="images-label">归还图片:</div>
|
||
<div class="images-list">
|
||
<el-image v-for="(img, index) in parseImages(item.images)" :key="index" :src="img"
|
||
fit="cover" class="return-image" :preview-src-list="parseImages(item.images)"
|
||
preview-teleported>
|
||
<template #error>
|
||
<div class="image-error">图片加载失败</div>
|
||
</template>
|
||
</el-image>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 审核图片 -->
|
||
<div v-if="item.auditImages" class="images-section">
|
||
<div class="images-label">审核图片:</div>
|
||
<div class="images-list">
|
||
<el-image v-for="(img, index) in parseImages(item.auditImages)" :key="index" :src="img"
|
||
fit="cover" class="audit-image" :preview-src-list="parseImages(item.auditImages)"
|
||
preview-teleported>
|
||
<template #error>
|
||
<div class="image-error">图片加载失败</div>
|
||
</template>
|
||
</el-image>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div v-if="item.auditName" class="audit-info">
|
||
<span class="audit-label">审批人:</span>
|
||
<span class="audit-name">{{ item.auditName }}</span>
|
||
</div>
|
||
<div v-if="item.auditRemark && item.auditRemark != '自动审批'" class="remark-info">
|
||
<span class="remark-label">说明:</span>
|
||
<span class="audit-remark">{{ item.auditRemark }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-card>
|
||
</el-timeline-item>
|
||
</el-timeline>
|
||
|
||
<div v-else-if="loading" class="dynamic-empty">
|
||
<el-skeleton :rows="5" animated />
|
||
</div>
|
||
|
||
<div v-else class="dynamic-empty">
|
||
<el-empty description="暂无借还动态" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-col>
|
||
</el-row>
|
||
|
||
<el-dialog v-model="showDialog" title="请绑定汇邦云账号" :close-on-click-modal="false" width="30%">
|
||
<el-form :model="form" :rules="rules" label-width="80px">
|
||
<el-form-item label="姓名" prop="name">
|
||
<el-input v-model="form.name" />
|
||
</el-form-item>
|
||
<el-form-item label="身份证号" prop="idCard">
|
||
<el-input v-model="form.idCard" maxlength="18" show-word-limit />
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<el-button type="primary" @click="handleSubmit">提交</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped lang="scss">
|
||
:deep(.el-card) {
|
||
border: none; // 移除卡片边框;
|
||
}
|
||
|
||
.welcome-container {
|
||
|
||
.section-title {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 5px;
|
||
|
||
.title-bar {
|
||
width: 3px;
|
||
height: 16px;
|
||
background-color: var(--el-color-primary);
|
||
margin-right: 8px;
|
||
border-radius: 2px;
|
||
}
|
||
|
||
.title-text {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: var(--el-text-color-primary);
|
||
}
|
||
}
|
||
|
||
.section-container {
|
||
margin-bottom: 12px;
|
||
padding: 15px;
|
||
background-color: #fff;
|
||
border-radius: 4px;
|
||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.todo-section {
|
||
margin-bottom: 0;
|
||
|
||
.todo-card {
|
||
height: 100%;
|
||
border: none;
|
||
|
||
.todo-content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 10px 0;
|
||
|
||
.todo-icon {
|
||
margin-bottom: 10px;
|
||
color: var(--el-color-primary);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.todo-count {
|
||
font-size: 24px;
|
||
font-weight: bold;
|
||
margin-bottom: 5px;
|
||
text-align: center;
|
||
}
|
||
|
||
.todo-name {
|
||
font-size: 14px;
|
||
color: var(--el-text-color-secondary);
|
||
text-align: center;
|
||
}
|
||
|
||
.data-section {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.goods-card,
|
||
.order-card {
|
||
height: 100%;
|
||
border: none;
|
||
|
||
.goods-image,
|
||
.order-image {
|
||
width: 100%;
|
||
height: 140px;
|
||
border-radius: 4px 4px 0 0;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.goods-content,
|
||
.order-content {
|
||
padding: 10px;
|
||
|
||
.goods-name,
|
||
.order-name {
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
margin-bottom: 5px;
|
||
text-align: center;
|
||
}
|
||
|
||
.goods-count,
|
||
.order-info {
|
||
font-size: 12px;
|
||
color: var(--el-text-color-secondary);
|
||
text-align: center;
|
||
}
|
||
}
|
||
}
|
||
|
||
.goods-list {
|
||
.goods-item {
|
||
border: none;
|
||
|
||
.goods-item-content {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 3px;
|
||
|
||
.goods-left {
|
||
display: flex;
|
||
align-items: center;
|
||
flex: 1;
|
||
|
||
.goods-image {
|
||
width: 100px;
|
||
height: 80px;
|
||
border-radius: 4px;
|
||
margin-right: 12px;
|
||
/* box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); */
|
||
}
|
||
|
||
.goods-name {
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
|
||
.goods-right {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.goods-progress {
|
||
flex: 1;
|
||
margin-right: 2px;
|
||
}
|
||
|
||
.goods-count {
|
||
text-align: right;
|
||
font-size: 14px;
|
||
color: var(--el-text-color-primary);
|
||
}
|
||
|
||
.buyer-name {
|
||
padding-left: 10px;
|
||
flex-grow: 1;
|
||
text-align: left;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.goods-container {
|
||
margin-bottom: 0;
|
||
|
||
.goods-right {
|
||
width: 150px;
|
||
}
|
||
|
||
.goods-count {
|
||
width: 45px;
|
||
}
|
||
}
|
||
|
||
.order-container {
|
||
margin-bottom: 0;
|
||
|
||
.goods-right {
|
||
width: 250px;
|
||
}
|
||
|
||
.goods-count {
|
||
width: 60px;
|
||
}
|
||
}
|
||
|
||
.shop-selection-container {
|
||
padding: 20px;
|
||
margin-bottom: 12px;
|
||
|
||
.shop-content {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.shop-info {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
flex: 1;
|
||
|
||
.shop-image {
|
||
width: 240px;
|
||
height: 160px;
|
||
border-radius: 8px;
|
||
margin-left: 16px;
|
||
margin-right: 26px;
|
||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.shop-details {
|
||
padding-top: 16px;
|
||
|
||
.shop-name-container {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
margin-bottom: 8px;
|
||
|
||
.shop-name {
|
||
font-size: 20px;
|
||
font-weight: bold;
|
||
color: var(--el-text-color-primary);
|
||
margin: 0;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.shop-selector {
|
||
min-width: 200px;
|
||
|
||
:deep(.el-input__wrapper) {
|
||
border-radius: 4px;
|
||
border: 1px solid var(--el-border-color);
|
||
box-shadow: none;
|
||
|
||
&:hover {
|
||
border-color: var(--el-color-primary);
|
||
}
|
||
|
||
&.is-focus {
|
||
border-color: var(--el-color-primary);
|
||
box-shadow: 0 0 0 1px var(--el-color-primary);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.shop-mode {
|
||
font-size: 14px;
|
||
color: var(--el-text-color-secondary);
|
||
margin: 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
.shop-qrcode {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
margin-right: 20px;
|
||
|
||
.qrcode-image {
|
||
width: 160px;
|
||
height: 160px;
|
||
border-radius: 4px;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.qrcode-text {
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
color: var(--el-text-color-secondary);
|
||
margin: 0;
|
||
text-align: center;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 借还动态样式
|
||
.dynamic-container {
|
||
margin-bottom: 0;
|
||
height: 88vh;
|
||
overflow-y: auto;
|
||
|
||
.dynamic-content {
|
||
.dynamic-timeline {
|
||
padding: 0;
|
||
|
||
:deep(.el-timeline-item) {
|
||
.el-timeline-item__timestamp {
|
||
font-size: 12px;
|
||
color: var(--el-text-color-secondary);
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.el-timeline-item__node {
|
||
width: 12px;
|
||
height: 12px;
|
||
}
|
||
}
|
||
}
|
||
|
||
.dynamic-card {
|
||
margin-bottom: 12px;
|
||
border: 1px solid var(--el-border-color);
|
||
|
||
.dynamic-card-content {
|
||
.dynamic-header {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 8px;
|
||
padding-bottom: 8px;
|
||
border-bottom: 1px solid var(--el-border-color-light);
|
||
|
||
.dynamic-icon {
|
||
font-size: 16px;
|
||
margin-right: 8px;
|
||
}
|
||
|
||
.dynamic-type {
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
margin-right: 8px;
|
||
}
|
||
|
||
.status-tag {
|
||
margin-left: auto;
|
||
color: white;
|
||
border: none;
|
||
}
|
||
}
|
||
|
||
.dynamic-info {
|
||
.goods-info {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
margin-bottom: 8px;
|
||
|
||
.goods-image {
|
||
width: 120px;
|
||
height: 90px;
|
||
border-radius: 4px;
|
||
margin-right: 12px;
|
||
flex-shrink: 0;
|
||
cursor: pointer;
|
||
border: 1px solid var(--el-border-color-light);
|
||
}
|
||
|
||
.goods-details {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
min-height: 60px;
|
||
|
||
.goods-name {
|
||
font-size: 14px;
|
||
font-weight: bold;
|
||
color: var(--el-text-color-primary);
|
||
margin-bottom: 4px;
|
||
line-height: 1.4;
|
||
display: -webkit-box;
|
||
-webkit-line-clamp: 2;
|
||
-webkit-box-orient: vertical;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.goods-price {
|
||
font-size: 14px;
|
||
color: var(--el-color-primary);
|
||
font-weight: bold;
|
||
align-self: flex-start;
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.user-info {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 4px;
|
||
|
||
.user-name,
|
||
.user-mobile {
|
||
font-size: 12px;
|
||
color: var(--el-text-color-secondary);
|
||
}
|
||
}
|
||
|
||
.location-info {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
|
||
.cabinet-name,
|
||
.cell-no {
|
||
font-size: 12px;
|
||
color: var(--el-text-color-secondary);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.user-info,
|
||
.location-info {
|
||
display: none;
|
||
}
|
||
|
||
.approval-info {
|
||
background-color: var(--el-fill-color-light);
|
||
border-radius: 4px;
|
||
padding: 12px;
|
||
margin-top: 8px;
|
||
|
||
.images-row {
|
||
display: flex;
|
||
gap: 20px;
|
||
margin-bottom: 12px;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.images-section {
|
||
flex: 1;
|
||
min-width: 0;
|
||
|
||
.images-label {
|
||
font-size: 12px;
|
||
font-weight: bold;
|
||
color: var(--el-text-color-secondary);
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.images-list {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 6px;
|
||
|
||
.return-image,
|
||
.audit-image {
|
||
width: 110px;
|
||
height: 70px;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
border: 1px solid var(--el-border-color-light);
|
||
flex-shrink: 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
.audit-info,
|
||
.remark-info {
|
||
font-size: 12px;
|
||
color: var(--el-text-color-secondary);
|
||
|
||
.audit-label,
|
||
.remark-label {
|
||
font-weight: bold;
|
||
}
|
||
|
||
.audit-name,
|
||
.audit-remark {
|
||
color: var(--el-text-color-primary);
|
||
}
|
||
}
|
||
|
||
.remark-info {
|
||
margin-top: 4px;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.image-error {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background-color: var(--el-fill-color-light);
|
||
color: var(--el-text-color-secondary);
|
||
font-size: 12px;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
.dynamic-empty {
|
||
text-align: center;
|
||
padding: 40px 0;
|
||
|
||
:deep(.el-empty) {
|
||
.el-empty__description {
|
||
font-size: 14px;
|
||
color: var(--el-text-color-secondary);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style> |