wangrong
2026-09-29 8d3e9c9480ebc4ae95bdb5854de80d068c467343
Merge branch 'fix-home-logo'
9个文件已修改
1个文件已添加
155 ■■■■■ 已修改文件
.env 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/bak.png 补丁 | 查看 | 原始文档 | blame | 历史
public/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/maps/hooks/use-map.ts 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/operation/views/wastesale.vue 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/report/components/screen-map-panel.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/report/views/screen/carbon.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/report/views/screen/map.vue 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/report/views/screen/overview.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/modules/report/views/screen/participation.vue 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env
@@ -1,5 +1,5 @@
# 应用名称
VITE_NAME = " WOMP "
VITE_NAME = " 无废校园 "
# 网络超时请求时间
VITE_TIMEOUT = 30000
public/bak.png
public/logo.png

src/modules/maps/hooks/use-map.ts
@@ -4,6 +4,52 @@
export const MAP_TK = '51915011aa0997aa2ddd7e38504fa8bc';
export const MAP_LOAD = { v: '4.0', tk: MAP_TK };
export const DEFAULT_CENTER: LngLat = [121.280637, 32.125178];
export const DEFAULT_ZOOM = 16;
export const MAP_ZOOM_KEY = 'map.zoomlevel';
export const MAP_COORD_KEY = 'map.coordinates';
function paramText(raw: unknown): string {
    if (raw == null) return '';
    if (typeof raw === 'string' || typeof raw === 'number') return String(raw).trim();
    if (Array.isArray(raw)) return raw.map(e => String(e).trim()).join(',');
    return '';
}
export function parseMapZoom(raw: unknown, fallback = DEFAULT_ZOOM) {
    const n = Number(paramText(raw));
    return Number.isFinite(n) && n > 0 ? n : fallback;
}
export function parseMapCenter(raw: unknown, fallback: LngLat = DEFAULT_CENTER): LngLat {
    const text = paramText(raw);
    const parts = text.split(/[,,]/).map(s => Number(s.trim()));
    if (parts.length >= 2 && Number.isFinite(parts[0]) && Number.isFinite(parts[1])) {
        return [parts[0], parts[1]];
    }
    return fallback;
}
/** 从 base_sys_param 读取学校地图默认视角:map.zoomlevel、map.coordinates(lon,lat) */
export async function loadMapView(service: any): Promise<{ center: LngLat; zoom: number }> {
    const read = async (key: string) => {
        try {
            if (service?.base?.sys?.param?.stringbykey) {
                return await service.base.sys.param.stringbykey({ key });
            }
            return await service.request({
                url: 'admin/base/sys/param/stringbykey',
                params: { key }
            });
        } catch {
            return '';
        }
    };
    const [zoomRaw, coordRaw] = await Promise.all([read(MAP_ZOOM_KEY), read(MAP_COORD_KEY)]);
    return {
        center: parseMapCenter(coordRaw),
        zoom: parseMapZoom(zoomRaw)
    };
}
export function pinIcon(color: string) {
    const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="28" height="40" viewBox="0 0 28 40"><path fill="${color}" stroke="#fff" stroke-width="1.5" d="M14 1C7.4 1 2 6.4 2 13c0 8.8 12 25 12 25s12-16.2 12-25C26 6.4 20.6 1 14 1z"/><circle cx="14" cy="13" r="5" fill="#fff"/></svg>`;
src/modules/operation/views/wastesale.vue
@@ -139,7 +139,7 @@
            required: true
        },
        {
            label: t('重量'),
            label: t('重量(kg)'),
            prop: "weight",
            hook: "number",
            component: {
@@ -233,7 +233,7 @@
            sortable: "custom",
            component: { name: "cl-date-text" }
        },
        { label: t('重量'), prop: "weight", minWidth: 140, sortable: "custom" },
        { label: t('重量(kg)'), prop: "weight", minWidth: 140, sortable: "custom" },
        { label: t('单价'), prop: "unitPrice", minWidth: 140, sortable: "custom" },
        { label: t('总价'), prop: "totalPrice", minWidth: 140, sortable: "custom" },
        {
src/modules/report/components/screen-map-panel.vue
@@ -11,9 +11,16 @@
            </div>
        </div>
        <!-- 地图主体 -->
        <!-- 地图主体:等参数就绪再创建,避免天地图只在初始化时吃 center/zoom -->
        <div class="map-panel__map">
            <tdt-map :center="center" :zoom="zoom" :controls="controls" :loadConfig="MAP_LOAD">
            <tdt-map
                v-if="viewReady"
                :center="center"
                :zoom="zoom"
                :controls="controls"
                :loadConfig="MAP_LOAD"
                @init="onMapInit"
            >
                <tdt-marker
                    v-for="item in list"
                    :key="keyOf(item)"
@@ -40,12 +47,15 @@
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { TdtMap, TdtMarker, type LngLat } from 'vue-tianditu2';
import { useCool } from '/@/cool';
import {
    DEFAULT_CENTER,
    DEFAULT_ZOOM,
    MAP_LOAD,
    SORTER_ICON,
    VEHICLE_ICON,
    formatTime,
    loadMapView,
    siteIcon,
    useMapsApi
} from '../../maps/hooks/use-map';
@@ -97,12 +107,14 @@
    }
};
const { service } = useCool();
const api = useMapsApi();
const layer = ref<LayerKey>('site');
const list = ref<any[]>([]);
const center = ref<LngLat>(DEFAULT_CENTER);
const zoom = ref(12);
const zoom = ref(DEFAULT_ZOOM);
const viewReady = ref(false);
const lastUpdate = ref('');
const controls = ['Zoom', 'Scale'];
@@ -131,14 +143,29 @@
    return cfg.value.icon(item);
}
function applyView(map: any) {
    const [lon, lat] = center.value;
    if (!map || !Number.isFinite(lon) || !Number.isFinite(lat)) return;
    const TMap = (window as any).T;
    const lnglat = TMap?.LngLat ? new TMap.LngLat(lon, lat) : [lon, lat];
    if (typeof map.centerAndZoom === 'function') {
        map.centerAndZoom(lnglat, zoom.value);
    } else {
        map.panTo?.(lnglat);
        map.setZoom?.(zoom.value);
    }
    map.checkResize?.();
}
function onMapInit(map: any) {
    applyView(map);
    window.setTimeout(() => applyView(map), 200);
}
async function load() {
    const res = await cfg.value.load();
    list.value = Array.isArray(res) ? res : [];
    lastUpdate.value = formatTime(new Date());
    if (list.value[0]) {
        center.value = pos(list.value[0]);
        zoom.value = 13;
    }
}
// 车辆 / 分拣员为实时位置,30s 轮询;站点是静态台账,不轮询
@@ -162,6 +189,10 @@
});
onMounted(async () => {
    const view = await loadMapView(service);
    center.value = view.center;
    zoom.value = view.zoom;
    viewReady.value = true;
    await load();
    startPolling();
});
src/modules/report/views/screen/carbon.vue
@@ -1,6 +1,6 @@
<template>
    <div class="screen-page">
        <div class="kpi-grid" style="--kpi-cols: 5">
        <div class="kpi-grid" style="--kpi-cols: 3">
            <kpi-card v-for="item in kpis" :key="item.label" v-bind="item" />
        </div>
@@ -58,11 +58,9 @@
);
const kpis = computed(() => [
    { field: 'kpis.totalCarbonTon', label: '累计碳减排', value: data.value.kpis.totalCarbonTon, suffix: '吨CO₂e', fixed: 1 },
    { field: 'kpis.periodCarbonTon', label: `${rangeLabel.value}碳减排`, value: data.value.kpis.periodCarbonTon, suffix: '吨CO₂e', fixed: 2 },
    { field: 'kpis.totalWeightTon', label: '累计资源回收', value: data.value.kpis.totalWeightTon, suffix: '吨', fixed: 1 },
    { field: 'kpis.totalParticipants', label: '累计参与师生', value: data.value.kpis.totalParticipants, suffix: '人', fixed: 0 },
    { field: 'kpis.greenActions', label: '累计环保行为', value: data.value.kpis.greenActions, suffix: '次', fixed: 0 }
    { field: 'kpis.periodWeightTon', label: `${rangeLabel.value}资源回收`, value: data.value.kpis.periodWeightTon, suffix: '吨', fixed: 2, hint: '当前时间范围' },
    { field: 'kpis.newParticipants', label: `${rangeLabel.value}参与师生`, value: data.value.kpis.newParticipants, suffix: '人', fixed: 0, hint: '区间内出现过的去重用户' },
    { field: 'kpis.greenActions', label: `${rangeLabel.value}环保行为`, value: data.value.kpis.greenActions, suffix: '次', fixed: 0, hint: '区间内已完成订单数' }
]);
const carbonTrendDemo = computed(() =>
@@ -81,7 +79,7 @@
        },
        yAxis: {
            type: 'value',
            name: '吨CO₂e',
            name: 'tCO₂e',
            nameTextStyle: { color: mutedColor.value },
            splitLine: { lineStyle: { color: splitColor.value, type: 'dashed' } },
            axisLabel: { color: mutedColor.value },
@@ -112,7 +110,7 @@
    },
    yAxis: {
        type: 'value',
        name: '吨CO₂e',
        name: 'tCO₂e',
        nameTextStyle: { color: mutedColor.value },
        splitLine: { lineStyle: { color: splitColor.value, type: 'dashed' } },
        axisLabel: { color: mutedColor.value },
src/modules/report/views/screen/map.vue
@@ -97,21 +97,21 @@
const itemMetric = ref<'weight' | 'value' | 'carbon'>('weight');
const mixOptions = [
    { label: '重量', value: 'weight' },
    { label: '价值', value: 'value' },
    { label: '数量', value: 'count' }
    { label: '重量(kg)', value: 'weight' },
    { label: '价值(元)', value: 'value' },
    { label: '计数(次)', value: 'count' }
];
const trendOptions = [
    { label: '重量', value: 'weight' },
    { label: '价值', value: 'value' },
    { label: '碳减排', value: 'carbon' }
    { label: '重量(kg)', value: 'weight' },
    { label: '价值(元)', value: 'value' },
    { label: '碳减排(kgCO₂e)', value: 'carbon' }
];
const itemOptions = [
    { label: '重量', value: 'weight' },
    { label: '价值', value: 'value' },
    { label: '碳减排', value: 'carbon' }
    { label: '重量(kg)', value: 'weight' },
    { label: '价值(元)', value: 'value' },
    { label: '碳减排(kgCO₂e)', value: 'carbon' }
];
const rangeLabel = computed(
@@ -123,7 +123,7 @@
    { field: 'kpis.periodWeightTon', label: `${rangeLabel.value}回收量`, value: data.value.kpis.periodWeightTon, suffix: '吨', fixed: 2 },
    { field: 'kpis.resourceRate', label: '资源化率', value: data.value.kpis.resourceRate, suffix: '%', fixed: 1 },
    { field: 'kpis.periodValue', label: '回收价值', value: data.value.kpis.periodValue, suffix: '元', fixed: 0 },
    { field: 'kpis.periodCarbonTon', label: '碳减排', value: data.value.kpis.periodCarbonTon, suffix: '吨CO₂e', fixed: 2 },
    { field: 'kpis.periodCarbonTon', label: '碳减排(tCO₂e)', value: data.value.kpis.periodCarbonTon, suffix: 'tCO₂e', fixed: 2 },
    { field: 'kpis.totalWeightTon', label: '累计回收量', value: data.value.kpis.totalWeightTon, suffix: '吨', fixed: 1 },
    { field: 'kpis.totalParticipants', label: '累计参与人数', value: data.value.kpis.totalParticipants, suffix: '人', fixed: 0 },
    { field: 'kpis.totalPoints', label: '累计碳积分', value: data.value.kpis.totalPoints, suffix: '分', fixed: 0 }
src/modules/report/views/screen/overview.vue
@@ -63,15 +63,15 @@
const trendMetric = ref<'weight' | 'value' | 'carbon'>('weight');
const mixOptions = [
    { label: '重量', value: 'weight' },
    { label: '价值', value: 'value' },
    { label: '数量', value: 'count' }
    { label: '重量(kg)', value: 'weight' },
    { label: '价值(元)', value: 'value' },
    { label: '计数(次)', value: 'count' }
];
const trendOptions = [
    { label: '重量', value: 'weight' },
    { label: '价值', value: 'value' },
    { label: '碳减排', value: 'carbon' }
    { label: '重量(kg)', value: 'weight' },
    { label: '价值(元)', value: 'value' },
    { label: '碳减排(kgCO₂e)', value: 'carbon' }
];
const rangeLabel = computed(
@@ -79,13 +79,13 @@
);
const kpis = computed(() => [
    { field: 'kpis.periodWeightTon', label: `${rangeLabel.value}回收量`, value: data.value.kpis.periodWeightTon, suffix: '吨', fixed: 2, hint: '当前时间范围' },
    { field: 'kpis.periodWeightTon', label: `${rangeLabel.value}回收量`, value: data.value.kpis.periodWeightTon, suffix: 't', fixed: 2, hint: '当前时间范围' },
    { field: 'kpis.resourceRate', label: '资源化率', value: data.value.kpis.resourceRate, suffix: '%', fixed: 1, hint: '可回收物重量/总重量,不含大件' },
    { field: 'kpis.periodValue', label: '回收价值', value: data.value.kpis.periodValue, suffix: '元', fixed: 0, hint: '日表估算销售额' },
    { field: 'kpis.periodCarbonTon', label: '碳减排', value: data.value.kpis.periodCarbonTon, suffix: '吨CO₂e', fixed: 2, hint: '分类重量 × 碳减因数' },
    { field: 'kpis.totalWeightTon', label: '累计回收量', value: data.value.kpis.totalWeightTon, suffix: '吨', fixed: 1, hint: '上线以来累计' },
    { field: 'kpis.totalParticipants', label: '累计参与人数', value: data.value.kpis.totalParticipants, suffix: '人', fixed: 0, hint: '去重校园用户' },
    { field: 'kpis.totalPoints', label: '累计碳积分', value: data.value.kpis.totalPoints, suffix: '分', fixed: 0, hint: '账户余额合计' }
    { field: 'kpis.periodCarbonTon', label: '碳减排', value: data.value.kpis.periodCarbonTon, suffix: 'tCO₂e', fixed: 2, hint: '分类重量 × 碳减因数' },
    { field: 'kpis.totalWeightTon', label: '累计回收量', value: data.value.kpis.totalWeightTon, suffix: 't', fixed: 1, hint: '上线以来累计' },
    { field: 'kpis.totalPoints', label: '累计碳积分', value: data.value.kpis.totalPoints, suffix: '分', fixed: 0, hint: '账户余额合计' },
    { field: 'kpis.totalParticipants', label: '累计参与人数', value: data.value.kpis.totalParticipants, suffix: '人', fixed: 0, hint: '去重校园用户' }
]);
const mixOption = computed(() => ({
src/modules/report/views/screen/participation.vue
@@ -96,7 +96,7 @@
    { label: '回收重量', value: 'weight' },
    { label: '人均回收量', value: 'weightPerCapita' },
    { label: '人均积分', value: 'pointPerCapita' },
    { label: '碳减排', value: 'carbon' }
    { label: '碳减排(kgCO₂e)', value: 'carbon' }
];
const rangeLabel = computed(