Compare commits
No commits in common. "dev" and "main" have entirely different histories.
2
.env
2
.env
@ -17,4 +17,4 @@ VITE_GLOB_AMAP_SECURITY_JS_CODE = 'b85d17b7e0fa98864d495a9a52f162e4'
|
||||
VITE_GLOB_AMAP_KEY = '0e6910fae6848722b0e57f0c01597499'
|
||||
|
||||
# 图片上传展示路径
|
||||
VITE_APP_IMAGE_URL = 'https://www.cx.cdzhuojing.cn/file/static-objects/img-file/'
|
||||
VITE_APP_IMAGE_URL = 'https://www.cdzhuojing.cn/file/static-objects/img-file/'
|
||||
@ -8,9 +8,8 @@ VITE_ROUTER_MODE = hash
|
||||
# 默认情况下,vite 会假设你的应用是被部署在一个域名的根路径上,所以这里 VITE_PUBLIC_PATH 为 '/'
|
||||
VITE_PUBLIC_PATH = './'
|
||||
|
||||
# https://www.cx.cdzhuojing.cn/ebike
|
||||
# http://192.168.1.18:10010
|
||||
# https://www.cdzhuojing.cn/ebike
|
||||
# 请求路径 管理系统/开发环境
|
||||
VITE_APP_BASE_URL = 'https://www.cx.cdzhuojing.cn/ebike'
|
||||
VITE_APP_BASE_URL = 'https://www.cdzhuojing.cn/ebike'
|
||||
|
||||
|
||||
|
||||
@ -11,5 +11,5 @@ VITE_ROUTER_MODE = hash
|
||||
VITE_PUBLIC_PATH = '/'
|
||||
|
||||
# 请求路径 管理系统/开发环境
|
||||
VITE_APP_BASE_URL = 'https://www.cx.cdzhuojing.cn/ebike'
|
||||
VITE_APP_BASE_URL = 'https://www.cdzhuojing.cn/ebike'
|
||||
|
||||
|
||||
@ -39,7 +39,6 @@
|
||||
"@codemirror/lang-vue": "^0.1.3",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@fingerprintjs/fingerprintjs": "^4.6.2",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@visactor/vchart": "^1.11.0",
|
||||
"@visactor/vchart-arco-theme": "^1.11.0",
|
||||
"@vueuse/core": "^12.4.0",
|
||||
@ -48,10 +47,8 @@
|
||||
"axios": "^1.6.8",
|
||||
"codemirror": "^6.0.1",
|
||||
"driver.js": "^1.3.1",
|
||||
"file-saver": "^2.0.5",
|
||||
"fingerprintjs2": "^2.1.4",
|
||||
"jsbarcode": "^3.11.6",
|
||||
"jszip": "^3.10.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.3.0",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
|
||||
@ -73,9 +73,9 @@ service.interceptors.response.use(
|
||||
}
|
||||
},
|
||||
function (error: any) {
|
||||
// console.log(error);
|
||||
localStorage.removeItem("user-info");
|
||||
router.replace("/login");
|
||||
// TUDU:这里逻辑不符合当前系统,后续改
|
||||
// localStorage.removeItem("user-info");
|
||||
// router.push("/login");
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
import axios from "@/api";
|
||||
import { ApplyChangeCarListParams, ProcessUserReportParams } from "./types";
|
||||
|
||||
// 申请换车点列表
|
||||
|
||||
export const getApplyChangeCarListAPI = (params: ApplyChangeCarListParams) => {
|
||||
return axios({
|
||||
url: "/operations/ebikeReportRecord/page",
|
||||
method: "get",
|
||||
params
|
||||
});
|
||||
};
|
||||
|
||||
// 处理用户上报记录
|
||||
export const handleApplyChangeCarAPI = (data: ProcessUserReportParams) => {
|
||||
return axios({
|
||||
url: "/operations/ebikeReportRecord/dealReportRecord",
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
@ -1,25 +0,0 @@
|
||||
interface ListType {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
}
|
||||
|
||||
// 申请换车点列表参数
|
||||
export interface ApplyChangeCarListParams extends ListType {
|
||||
recordStatus?: number;
|
||||
}
|
||||
|
||||
// 处理用户上报记录参数
|
||||
type Coordinate = [number, number];
|
||||
interface RegionPolygon {
|
||||
type: "polygon" | "point";
|
||||
coordinates: Coordinate[];
|
||||
}
|
||||
export interface ProcessUserReportParams {
|
||||
recordId: string;
|
||||
staffId: string;
|
||||
recordStatus: 1 | 2; //处理状态 1-同意申请 2-拒绝申请
|
||||
recordReason?: string;
|
||||
siteName?: string;
|
||||
sitePolygon?: RegionPolygon;
|
||||
siteType?: number;
|
||||
}
|
||||
@ -13,11 +13,8 @@ export const getUserRefundListAPI = (data: RefundLisType) => {
|
||||
// 获取退款订单详情
|
||||
export const getRefundOrderDetailAPI = (refundId: string) => {
|
||||
return axios({
|
||||
url: "operations/ebikeRefundReview/refundOrderDetail",
|
||||
method: "get",
|
||||
params: {
|
||||
refundId
|
||||
}
|
||||
url: "operations/ebikeRefundReview/refundOrderDetail/" + refundId,
|
||||
method: "get"
|
||||
});
|
||||
};
|
||||
|
||||
@ -29,41 +26,3 @@ export const reviewRefundApplicationAPI = (data: reviewRefundApplicationType) =>
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
// 获取骑行中与待支付的订单列表
|
||||
export const getUserOrderListAPI = (params: { bikeCode: string; pageNum: number; pageSize: number }) => {
|
||||
return axios({
|
||||
url: "operations/statistics/getDiffOperatorOrderList",
|
||||
method: "get",
|
||||
params
|
||||
});
|
||||
};
|
||||
|
||||
//根据车辆编号修改当前订单金额
|
||||
export const updateOrderAmountByBikeCodeAPI = (data: { bikeCode: string; price: number }) => {
|
||||
return axios({
|
||||
url: "operations/statistics/updateOrderAmount",
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
// 结束用户骑行订单
|
||||
export const endUserRideOrderAPI = (data: { bikeCode: string }) => {
|
||||
return axios({
|
||||
url: "operations/statistics/closeOrder",
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
// 车辆详情
|
||||
export const getBikeDetailAPI = (bikeCode: string) => {
|
||||
return axios({
|
||||
url: "operations/ebikeBikeOrder/bikeInfo",
|
||||
method: "get",
|
||||
params: {
|
||||
bikeCode
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -11,7 +11,7 @@ export interface RefundLisType {
|
||||
|
||||
export interface reviewRefundApplicationType {
|
||||
staffId: string;
|
||||
reviewId: string;
|
||||
refundId: number;
|
||||
operate: number;
|
||||
reason?: string;
|
||||
refundMethod: number;
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
import axios from "@/api";
|
||||
import { OperatorConfigFormType } from "./types";
|
||||
|
||||
// 运营商配置添加更新
|
||||
export const addOrUpdateOperatorConfigAPI = (data: OperatorConfigFormType) => {
|
||||
return axios({
|
||||
url: "/operations/ebikeCarrierConfiguration/saveOrUpdate",
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
//根据运营商id查询配置信息
|
||||
export const getOperatorConfigByOperatorIdAPI = (operatorId: string) => {
|
||||
return axios({
|
||||
url: "/operations/ebikeCarrierConfiguration/getByOperatorId",
|
||||
method: "get",
|
||||
params: { operatorId }
|
||||
});
|
||||
};
|
||||
@ -1,8 +0,0 @@
|
||||
//运营商配置添加更新配置
|
||||
export interface OperatorConfigFormType {
|
||||
operatorId: string; //运营商id
|
||||
dispatchDuration: number | undefined; //配置项时长
|
||||
rideDuration: number | undefined; //配置项骑行时长
|
||||
inspectionIntervalDuration: number | undefined; //巡检间隔时长(日)
|
||||
operatorPhone: string; //运营商手机号
|
||||
}
|
||||
@ -11,8 +11,7 @@ import {
|
||||
AddDictFormType,
|
||||
DictItemListParams,
|
||||
AddDictItemFormType,
|
||||
saveImageType,
|
||||
OnlineUpdateParams
|
||||
saveImageType
|
||||
} from "./types";
|
||||
|
||||
// 获取菜单数据
|
||||
@ -365,12 +364,3 @@ export const updateImageAPI = (data: saveImageType) => {
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
// 在线模块升级
|
||||
export const onlineUpgradeAPI = (data: OnlineUpdateParams) => {
|
||||
return axios({
|
||||
url: "/operations/ebikeEcuInfo/upgrade",
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
@ -99,13 +99,3 @@ export interface saveImageType {
|
||||
imgCode?: string; // 图片编码
|
||||
fileUrl: string; // 图片地址
|
||||
}
|
||||
|
||||
// 远程升级
|
||||
export interface OnlineUpdateParams {
|
||||
ecuSn?: string
|
||||
bikeCode?: string
|
||||
ecuBrand: string
|
||||
url: string
|
||||
fullUpgrade: boolean
|
||||
type: number
|
||||
}
|
||||
|
||||
1
src/components.d.ts
vendored
1
src/components.d.ts
vendored
@ -7,6 +7,7 @@ export {}
|
||||
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
copy: typeof import('./components/s-layout-search/index copy.vue')['default']
|
||||
'Index copy': typeof import('./components/s-layout-search/index copy.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
import { ref, Ref } from "vue";
|
||||
import JSZip from "jszip";
|
||||
import { saveAs } from "file-saver";
|
||||
|
||||
type DownloadStatus = "idle" | "loading" | "success" | "error";
|
||||
|
||||
@ -58,48 +56,35 @@ export function useImageDownloader(): any {
|
||||
};
|
||||
|
||||
// 批量下载(并行)
|
||||
const downloadImages = async (urls: string[], customFileNames?: string[]): Promise<void> => {
|
||||
// 可选:更新状态(如果你用 Vue 的 ref)
|
||||
// downloadStatus.value = "loading";
|
||||
const downloadImages = async (urls: string[], customFileNames?: string[]): Promise<DownloadResult[]> => {
|
||||
downloadStatus.value = "loading";
|
||||
batchResults.value = [];
|
||||
|
||||
const zip = new JSZip();
|
||||
const errors: string[] = [];
|
||||
|
||||
// 并发获取所有图片(可加并发控制,但 30 个一般没问题)
|
||||
await Promise.all(
|
||||
urls.map(async (url, index) => {
|
||||
const promises = urls.map(async (url, index) => {
|
||||
try {
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
||||
const blob = await res.blob();
|
||||
let fileName = customFileNames?.[index] || extractFileName(url);
|
||||
// 防止文件名重复(简单处理)
|
||||
if (zip.file(fileName)) {
|
||||
const ext = fileName.includes(".") ? fileName.split(".").pop() : "";
|
||||
const name = fileName.replace(new RegExp(`\\.${ext}$`), "");
|
||||
fileName = `${name}_${Date.now()}.${ext || "jpg"}`;
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||
const blob = await response.blob();
|
||||
const link = document.createElement("a");
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = customFileNames?.[index] || extractFileName(url);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(link.href);
|
||||
return { url, status: "success" } as DownloadResult;
|
||||
} catch (error) {
|
||||
console.error(`Failed to download ${url}:`, error);
|
||||
return { url, status: "error", message: (error as Error).message } as DownloadResult;
|
||||
}
|
||||
zip.file(fileName, blob);
|
||||
} catch (err) {
|
||||
console.error("Download failed:", url, err);
|
||||
errors.push(url);
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
// 生成 ZIP Blob
|
||||
const zipBlob = await zip.generateAsync({ type: "blob" });
|
||||
|
||||
// 触发下载 —— 这是安全的、用户可见的一次性下载
|
||||
saveAs(zipBlob, "车辆二维码.zip");
|
||||
|
||||
// 可选:提示错误
|
||||
if (errors.length > 0) {
|
||||
alert(`成功打包 ${urls.length - errors.length} 张图片。\n失败:${errors.length} 张`);
|
||||
}
|
||||
|
||||
// downloadStatus.value = "success";
|
||||
const results = await Promise.all(promises);
|
||||
batchResults.value = results;
|
||||
downloadStatus.value = "success";
|
||||
return results;
|
||||
};
|
||||
|
||||
return {
|
||||
downloadStatus,
|
||||
batchResults,
|
||||
|
||||
@ -132,8 +132,7 @@ const handleDownloadImage = async (record: any) => {
|
||||
// 批量下载
|
||||
const batchDownload = async () => {
|
||||
const urls = select_list.value.map(item => item.bikeQr);
|
||||
const names = select_list.value.map(item => `车辆二维码-${item.bikeQrCode}.png`);
|
||||
console.log(urls, names);
|
||||
const names = select_list.value.map(item => `电池二维码-${item.bikeQrCode}.png`);
|
||||
|
||||
await downloadImages(urls, names);
|
||||
};
|
||||
|
||||
@ -13,7 +13,6 @@ const emits = defineEmits(["ok"]);
|
||||
const open = ref<boolean>(false);
|
||||
|
||||
// 地图实例
|
||||
const applyPoint = reactive({ lng: undefined, lat: undefined });
|
||||
const map = shallowRef<any>(null);
|
||||
const mouseTool = shallowRef<any>(null);
|
||||
const polyEditor = shallowRef<any>(null);
|
||||
@ -24,7 +23,6 @@ const type = ref<string>("add");
|
||||
const currentPolygon = shallowRef<any>(null); // 当前唯一多边形实例
|
||||
const operationArea = ref<any[]>([]); // 运营区边界坐标
|
||||
const operationPolygon = shallowRef<any>(null); // 运营区多边形实例
|
||||
const applyPointMarker = shallowRef<any>(null); // 申请点 Marker
|
||||
let originalPath: any[] = []; // 保存原始路径用于恢复
|
||||
|
||||
const options__polygon = {
|
||||
@ -107,14 +105,9 @@ const initMap = () => {
|
||||
center = [104.066541, 30.572269]; // 默认成都坐标
|
||||
}
|
||||
|
||||
// 申请点位居中
|
||||
if (applyPoint.lat && applyPoint.lng) {
|
||||
center = [applyPoint.lng, applyPoint.lat];
|
||||
}
|
||||
|
||||
// 创建地图实例
|
||||
map.value = new mapRes.Map("container", {
|
||||
zoom: applyPoint.lat && applyPoint.lng ? 14 : 12,
|
||||
zoom: 12,
|
||||
center: center
|
||||
});
|
||||
|
||||
@ -133,37 +126,12 @@ const initMap = () => {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 绘制申请点 Marker
|
||||
*/
|
||||
function drawApplyPointMarker() {
|
||||
if (!map.value || !applyPoint.lng || !applyPoint.lat) return;
|
||||
|
||||
// 清除旧的 Marker
|
||||
if (applyPointMarker.value) {
|
||||
map.value.remove(applyPointMarker.value);
|
||||
}
|
||||
|
||||
applyPointMarker.value = new mapAmap.value.Marker({
|
||||
position: [applyPoint.lng, applyPoint.lat],
|
||||
title: "申请点位",
|
||||
icon: "https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png", // 蓝色默认图标
|
||||
zIndex: 999
|
||||
});
|
||||
|
||||
map.value.add(applyPointMarker.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开地图
|
||||
**/
|
||||
async function openMap(parmas: any) {
|
||||
console.log("openMap parmas:", parmas);
|
||||
const { regionPoints, sitePoints } = parmas;
|
||||
if (parmas?.applyPoints) {
|
||||
applyPoint.lat = parmas.applyPoints.latitude;
|
||||
applyPoint.lng = parmas.applyPoints.longitude;
|
||||
}
|
||||
|
||||
// 设置运营区边界
|
||||
if (regionPoints?.length > 0) {
|
||||
@ -177,11 +145,6 @@ async function openMap(parmas: any) {
|
||||
// 清除之前的所有内容
|
||||
clearAll();
|
||||
|
||||
// 绘制申请点的点位信息
|
||||
if (applyPoint.lat && applyPoint.lng) {
|
||||
drawApplyPointMarker();
|
||||
}
|
||||
|
||||
// 编辑
|
||||
if (sitePoints) {
|
||||
path.value = sitePoints;
|
||||
@ -572,11 +535,6 @@ function afterClose() {
|
||||
if (currentPolygon.value) {
|
||||
map.value.remove(currentPolygon.value);
|
||||
}
|
||||
// 移除申请点 Marker
|
||||
if (applyPointMarker.value) {
|
||||
map.value.remove(applyPointMarker.value);
|
||||
applyPointMarker.value = null;
|
||||
}
|
||||
if (operationPolygon.value) {
|
||||
map.value.remove(operationPolygon.value);
|
||||
}
|
||||
@ -591,12 +549,9 @@ function afterClose() {
|
||||
path.value = [];
|
||||
currentPolygon.value = null;
|
||||
operationPolygon.value = null;
|
||||
applyPointMarker.value = null; // 👈 新增
|
||||
polyEditor.value = null;
|
||||
mouseTool.value = null;
|
||||
operationArea.value = []; // 清空运营区数据
|
||||
applyPoint.lat = undefined;
|
||||
applyPoint.lng = undefined;
|
||||
type.value = "add";
|
||||
}
|
||||
|
||||
|
||||
@ -1,69 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
declare global {
|
||||
interface Window {
|
||||
_AMapSecurityConfig: any;
|
||||
}
|
||||
}
|
||||
import AMapLoader from "@amap/amap-jsapi-loader";
|
||||
|
||||
const { VITE_GLOB_AMAP_KEY, VITE_GLOB_AMAP_SECURITY_JS_CODE, VITE_APP_IMAGE_URL } = import.meta.env;
|
||||
|
||||
const mapAmap = shallowRef<any>(null);
|
||||
const map = shallowRef<any>(null);
|
||||
|
||||
/**
|
||||
* 地图容器初始化
|
||||
**/
|
||||
const initMap = (location: any) => {
|
||||
window._AMapSecurityConfig = {
|
||||
securityJsCode: VITE_GLOB_AMAP_SECURITY_JS_CODE
|
||||
};
|
||||
AMapLoader.load({
|
||||
key: VITE_GLOB_AMAP_KEY,
|
||||
version: "2.0",
|
||||
plugins: [
|
||||
"AMap.Marker",
|
||||
"AMap.Pixel",
|
||||
"AMap.Polyline",
|
||||
"AMap.Geolocation",
|
||||
"AMap.MouseTool",
|
||||
"AMap.Polygon",
|
||||
"AMap.PolygonEditor"
|
||||
]
|
||||
}).then((mapRes: any) => {
|
||||
mapAmap.value = mapRes;
|
||||
const applyPoint = location || {};
|
||||
|
||||
// 创建地图实例
|
||||
map.value = new mapRes.Map("container", {
|
||||
zoom: applyPoint.latitude && applyPoint.longitude ? 14 : 12,
|
||||
center: applyPoint.latitude && applyPoint.longitude ? [applyPoint.longitude, applyPoint.latitude] : undefined
|
||||
});
|
||||
|
||||
const customIcon = new mapAmap.value.Icon({
|
||||
size: new mapAmap.value.Size(50, 60), // 图标占据的地图像素区域(影响点击区域)
|
||||
imageSize: new mapAmap.value.Size(40, 40), // 图片实际显示的宽高(决定视觉大小)
|
||||
image: `${VITE_APP_IMAGE_URL}45cdabf8a98f4268b84f25df5f2c97b6.png`
|
||||
});
|
||||
|
||||
const marker = new mapAmap.value.Marker({
|
||||
position: [applyPoint.longitude, applyPoint.latitude],
|
||||
title: "申请点位",
|
||||
icon: customIcon,
|
||||
zIndex: 999
|
||||
});
|
||||
|
||||
map.value.add(marker);
|
||||
});
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
initMap
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="container" style="height: 100%; width: 100%"></div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@ -1,437 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import { getApplyChangeCarListAPI, handleApplyChangeCarAPI } from "@/api/modules/declare";
|
||||
import { deepClone, dictTranslate } from "@/utils";
|
||||
import { getAllRegionAPI, getRegionDetailAPI } from "@/api/modules/region/index";
|
||||
import { useSystemStore } from "@/store/modules/system";
|
||||
import { getOperatorAllListAPI } from "@/api/modules/system";
|
||||
import { useUserInfoStore } from "@/store/modules/user-info";
|
||||
import SiteMap from "@/views/component/SiteMap/SiteMap.vue";
|
||||
import { PointDataHandler } from "@/utils/map-tools";
|
||||
|
||||
const userStores = useUserInfoStore();
|
||||
const system = useSystemStore();
|
||||
const form = ref({
|
||||
recordStatus: undefined
|
||||
});
|
||||
const regionStatusList = ref<any>([]);
|
||||
const operatorAllList = ref<any>([]);
|
||||
const operation_list = ref<any>([]);
|
||||
const siteType_list = ref<any>([]);
|
||||
|
||||
// 列表
|
||||
const moduleList = ref([]);
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
current: 1,
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
showPageSize: true,
|
||||
showTotal: true
|
||||
});
|
||||
|
||||
// 模态框
|
||||
const open = ref<boolean>(false);
|
||||
const title = ref<string>("审核");
|
||||
const RegionalMapRef = ref<any>(null);
|
||||
const loadingOk = ref<boolean>(false);
|
||||
const addFormRef = ref();
|
||||
const addForm = ref<any>({
|
||||
recordId: "",
|
||||
recordReason: "",
|
||||
latitude: undefined,
|
||||
longitude: undefined,
|
||||
staffId: "",
|
||||
operatorId: "",
|
||||
siteName: "",
|
||||
regionId: "",
|
||||
siteType: "",
|
||||
sitePolygon: {
|
||||
type: "Polygon",
|
||||
coordinates: []
|
||||
}
|
||||
});
|
||||
const rules = {
|
||||
siteName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入站点名称",
|
||||
trigger: "blur"
|
||||
}
|
||||
],
|
||||
regionId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择运营区",
|
||||
trigger: "change"
|
||||
}
|
||||
],
|
||||
siteType: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择运营区",
|
||||
trigger: "change"
|
||||
}
|
||||
],
|
||||
operatorId: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择运营商",
|
||||
trigger: "change"
|
||||
}
|
||||
],
|
||||
"sitePolygon.coordinates": [
|
||||
{
|
||||
required: true,
|
||||
validator: (value: any, cb: any) => {
|
||||
console.log(value);
|
||||
if (value.length === 0) {
|
||||
cb("请编辑区域电子围栏");
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
const search = () => {
|
||||
pagination.value.current = 1;
|
||||
getApplyChangeCarList();
|
||||
};
|
||||
const reset = () => {
|
||||
form.value = {
|
||||
recordStatus: undefined
|
||||
};
|
||||
search();
|
||||
};
|
||||
|
||||
// 获取所有运营商列表
|
||||
const getAllOperatorList = async () => {
|
||||
return new Promise<void>(async resolve => {
|
||||
try {
|
||||
const res: any = await getOperatorAllListAPI();
|
||||
if (res.code === 200) {
|
||||
operatorAllList.value = res.data;
|
||||
resolve();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取运营商列表失败:", error);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 获取所有区域列表
|
||||
const getAllRegion = async () => {
|
||||
return new Promise<void>(async resolve => {
|
||||
try {
|
||||
const res: any = await getAllRegionAPI();
|
||||
if (res.code === 200) {
|
||||
operation_list.value = res.data;
|
||||
resolve();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取运营商列表失败:", error);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
};
|
||||
const handlePageChange = (page: number) => {
|
||||
pagination.value.current = page;
|
||||
getApplyChangeCarList();
|
||||
};
|
||||
|
||||
const handlePageSizeChange = (pageSize: number) => {
|
||||
pagination.value.pageSize = pageSize;
|
||||
pagination.value.current = 1;
|
||||
getApplyChangeCarList();
|
||||
};
|
||||
|
||||
// tag颜色
|
||||
const tagColor = (record: any) => {
|
||||
const { recordStatus } = record;
|
||||
|
||||
switch (recordStatus) {
|
||||
case 0:
|
||||
return "gray";
|
||||
case 1:
|
||||
return "green";
|
||||
case 2:
|
||||
return "red";
|
||||
default:
|
||||
return "gray";
|
||||
}
|
||||
};
|
||||
|
||||
const getApplyChangeCarList = async () => {
|
||||
loading.value = true;
|
||||
const query: any = {
|
||||
pageNum: pagination.value.current,
|
||||
pageSize: pagination.value.pageSize
|
||||
};
|
||||
if (form.value.recordStatus) {
|
||||
query.recordStatus = form.value.recordStatus;
|
||||
}
|
||||
try {
|
||||
const res: any = await getApplyChangeCarListAPI(query);
|
||||
if (res.code !== 200) {
|
||||
return;
|
||||
}
|
||||
const { records, pageNumber, pageSize } = res.data;
|
||||
pagination.value.current = pageNumber;
|
||||
pagination.value.pageSize = pageSize;
|
||||
pagination.value.total = res.data.totalRow;
|
||||
moduleList.value = records;
|
||||
} catch (error) {
|
||||
console.error("获取列表失败:", error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
//翻译字典值
|
||||
const dictFormat = (list: any[], key: string, value: string | number, valueKey: string = "dicValueName") => {
|
||||
return dictTranslate(list, key, value, valueKey);
|
||||
};
|
||||
const handleApplyChangeCar = (record: any) => {
|
||||
open.value = true;
|
||||
// console.log(record);
|
||||
const { operatorId, regionId, location, recordId } = record;
|
||||
addForm.value.recordId = recordId;
|
||||
addForm.value.operatorId = operatorId;
|
||||
addForm.value.regionId = regionId;
|
||||
addForm.value.longitude = location.longitude;
|
||||
addForm.value.latitude = location.latitude;
|
||||
};
|
||||
|
||||
// 审核弹窗
|
||||
const resetForm = () => {
|
||||
addForm.value = deepClone({
|
||||
recordId: "",
|
||||
recordReason: "",
|
||||
staffId: "",
|
||||
operatorId: "",
|
||||
siteName: "",
|
||||
regionId: "",
|
||||
latitude: undefined,
|
||||
longitude: undefined,
|
||||
siteType: "",
|
||||
sitePolygon: {
|
||||
type: "Polygon",
|
||||
coordinates: []
|
||||
}
|
||||
});
|
||||
if (addFormRef.value) {
|
||||
addFormRef.value.resetFields();
|
||||
}
|
||||
};
|
||||
|
||||
// 添加
|
||||
const handleOpenMap = async () => {
|
||||
// 获取运营区域的点位
|
||||
if (!addForm.value.regionId) {
|
||||
arcoMessage("warning", "请先选择运营区域");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await getRegionDetailAPI(addForm.value.regionId);
|
||||
if (res) {
|
||||
const { regionPolygon } = res.data;
|
||||
// console.log(regionPolygon);
|
||||
let path: any =
|
||||
addForm.value.sitePolygon.coordinates.length === 0
|
||||
? {
|
||||
regionPoints: PointDataHandler.restoreForDisplay(regionPolygon.coordinates),
|
||||
sitePoints: null
|
||||
}
|
||||
: {
|
||||
regionPoints: PointDataHandler.restoreForDisplay(regionPolygon.coordinates),
|
||||
sitePoints: deepClone(addForm.value.sitePolygon.coordinates)
|
||||
};
|
||||
|
||||
path.applyPoints = {
|
||||
latitude: addForm.value.latitude,
|
||||
longitude: addForm.value.longitude
|
||||
};
|
||||
RegionalMapRef.value?.openMap(path);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error("获取区域点位失败:", error);
|
||||
arcoMessage("error", "获取区域点位失败");
|
||||
}
|
||||
};
|
||||
|
||||
// 确认审核
|
||||
const checkOrder = async (recordStatus: number) => {
|
||||
const { staffId } = userStores.account;
|
||||
let parmas: any = {};
|
||||
if (recordStatus === 1) {
|
||||
let status = await addFormRef.value.validate();
|
||||
if (status) return false;
|
||||
const coordinates = PointDataHandler.prepareForUpload(addForm.value.sitePolygon.coordinates);
|
||||
parmas = deepClone({
|
||||
recordId: addForm.value.recordId,
|
||||
staffId,
|
||||
recordStatus,
|
||||
recordReason: addForm.value.recordReason,
|
||||
siteName: addForm.value.siteName,
|
||||
siteType: addForm.value.siteType,
|
||||
sitePolygon: {
|
||||
type: "Polygon",
|
||||
coordinates
|
||||
}
|
||||
});
|
||||
} else {
|
||||
parmas = deepClone({
|
||||
recordId: addForm.value.recordId,
|
||||
staffId,
|
||||
recordStatus,
|
||||
recordReason: addForm.value.recordReason
|
||||
});
|
||||
}
|
||||
loadingOk.value = true;
|
||||
try {
|
||||
const res = await handleApplyChangeCarAPI(parmas);
|
||||
arcoMessage("success", "已审核");
|
||||
resetForm();
|
||||
open.value = false;
|
||||
search();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
} finally {
|
||||
loadingOk.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const afterClose = () => {
|
||||
open.value = false;
|
||||
resetForm();
|
||||
};
|
||||
//获取地图点位
|
||||
const getPoint = (paths: any[]) => {
|
||||
addForm.value.sitePolygon.coordinates = paths;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getApplyChangeCarList();
|
||||
});
|
||||
|
||||
onBeforeMount(async () => {
|
||||
regionStatusList.value = deepClone(system.getDictByCode("ApplicationVehicleStatus"));
|
||||
siteType_list.value = deepClone(system.getDictByCode("siteType"));
|
||||
await getAllOperatorList();
|
||||
await getAllRegion();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="snow-page">
|
||||
<div class="snow-inner">
|
||||
<s-layout-tools>
|
||||
<template #left>
|
||||
<a-space wrap>
|
||||
<a-select :style="{ width: '250px' }" placeholder="审核状态" v-model="form.recordStatus" allow-clear>
|
||||
<a-option v-for="it in regionStatusList" :key="it.dicValue" :value="it.dicValue">{{ it.dicValueName }}</a-option>
|
||||
</a-select>
|
||||
<a-button type="primary" @click="search">
|
||||
<template #icon><icon-search /></template>
|
||||
<span>查询</span>
|
||||
</a-button>
|
||||
<a-button @click="reset">
|
||||
<template #icon><icon-refresh /></template>
|
||||
<span>重置</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</s-layout-tools>
|
||||
<a-table
|
||||
row-key="refundId"
|
||||
:data="moduleList"
|
||||
:bordered="{ cell: true }"
|
||||
:loading="loading"
|
||||
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
|
||||
:pagination="pagination"
|
||||
@page-change="handlePageChange"
|
||||
@page-size-change="handlePageSizeChange"
|
||||
>
|
||||
<template #columns>
|
||||
<a-table-column title="序号" :width="60" align="center">
|
||||
<template #cell="cell">
|
||||
<span>{{ (pagination.current - 1) * pagination.pageSize + cell.rowIndex + 1 }}</span>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="申请地址" data-index="address" align="center">
|
||||
<template #cell="{ record }">
|
||||
{{ record.address || "--" }}
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="审核备注" data-index="recordReason" align="center">
|
||||
<template #cell="{ record }">
|
||||
{{ record.recordReason || "--" }}
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="申请时间" data-index="createTime" align="center"></a-table-column>
|
||||
<a-table-column title="审核时间" data-index="recordTime" align="center"></a-table-column>
|
||||
<a-table-column title="审核状态" data-index="recordStatus" align="center">
|
||||
<template #cell="{ record }">
|
||||
<a-tag :color="tagColor(record)" bordered>{{
|
||||
dictFormat(regionStatusList, "dicValue", record.recordStatus)
|
||||
}}</a-tag>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="操作" align="center" :fixed="'right'">
|
||||
<template #cell="{ record }">
|
||||
<a-space>
|
||||
<a-button v-if="record.recordStatus === 0" type="primary" size="mini" @click="handleApplyChangeCar(record)">
|
||||
<span>审核</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
<!-- 模态框 -->
|
||||
<a-modal v-model:visible="open" :width="900" @close="afterClose" @cancel="afterClose">
|
||||
<template #title> {{ title }} </template>
|
||||
<a-form ref="addFormRef" :model="addForm" :rules="rules">
|
||||
<a-form-item label="站点名称" field="siteName" validate-trigger="blur">
|
||||
<a-input placeholder="请输入站点名称" allow-clear v-model="addForm.siteName" />
|
||||
</a-form-item>
|
||||
<a-form-item field="operatorId" label="运营商" validate-trigger="change">
|
||||
<a-select v-model="addForm.operatorId" placeholder="请选择运营商" disabled>
|
||||
<a-option v-for="it in operatorAllList" :key="it.operatorId" :value="it.operatorId">{{ it.operatorName }}</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item field="regionId" label="运营区域" validate-trigger="change">
|
||||
<a-select v-model="addForm.regionId" placeholder="请选择运营区域" allow-search disabled>
|
||||
<a-option v-for="it in operation_list" :key="it.regionId" :value="it.regionId">{{ it.regionName }}</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item field="siteType" label="运营区域类型" validate-trigger="change">
|
||||
<a-radio-group v-model="addForm.siteType">
|
||||
<a-radio v-for="it in siteType_list" :key="it.dicId" :value="it.dicValue">{{ it.dicValueName }}</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="站点电子围栏" field="sitePolygon.coordinates" validate-trigger="blur">
|
||||
<a-tag bordered color="orange" v-if="addForm.sitePolygon.coordinates.length === 0">未绘制</a-tag>
|
||||
<a-tag bordered color="green" v-else>已绘制</a-tag>
|
||||
<a-link @click="handleOpenMap" style="margin-left: 15px">编辑地图</a-link>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<template #footer>
|
||||
<div style="margin-bottom: 20px">
|
||||
<a-textarea v-model="addForm.recordReason" placeholder="审核意见" allow-clear class="textarea_box" />
|
||||
</div>
|
||||
<div class="footer-btn">
|
||||
<a-button type="primary" status="danger" @click="checkOrder(2)" :loading="loadingOk">驳回</a-button>
|
||||
<a-button type="primary" style="margin-left: 50px" status="success" @click="checkOrder(1)" :loading="loadingOk">
|
||||
通过
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
</a-modal>
|
||||
<SiteMap ref="RegionalMapRef" @ok="getPoint" />
|
||||
</div>
|
||||
</template>
|
||||
@ -52,8 +52,8 @@ let userStores = useUserInfoStore();
|
||||
const routeStore = useRouteConfigStore();
|
||||
const router = useRouter();
|
||||
const form = ref({
|
||||
username: "",
|
||||
password: ""
|
||||
username: "admin1",
|
||||
password: "123456"
|
||||
});
|
||||
const rules = ref({
|
||||
username: [
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
<div class="login">
|
||||
<LoginBanner v-if="isPc" />
|
||||
<div class="login_box">
|
||||
<div class="login_title">欢迎登录电单车管理系统</div>
|
||||
<div class="login_title_desc">高效管理电单车运营,实时掌握车辆动态</div>
|
||||
<div class="login_title_desc">智能调度,助力城市绿色出行</div>
|
||||
<div class="login_title">Welcome Back</div>
|
||||
<div class="login_title_desc">国际化,路由配置,状态管理应有尽有</div>
|
||||
<div class="login_title_desc">丰富的的页面模板,覆盖大多数典型业务场景</div>
|
||||
<LoginForm @isLoading="state => (loading = state)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,77 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import { deepClone } from "@/utils";
|
||||
import { updateOrderAmountByBikeCodeAPI } from "@/api/modules/order";
|
||||
|
||||
const formData = ref({
|
||||
bikeCode: "",
|
||||
orderId: "",
|
||||
actualAmount: 0,
|
||||
price: 0
|
||||
});
|
||||
|
||||
const init = (data: any) => {
|
||||
formData.value = {
|
||||
...deepClone(data),
|
||||
price: 0
|
||||
};
|
||||
};
|
||||
const updateOrderAmountByBikeCode = async () => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const res: any = await updateOrderAmountByBikeCodeAPI({
|
||||
bikeCode: formData.value.bikeCode,
|
||||
price: formData.value.price
|
||||
});
|
||||
resolve(res.data);
|
||||
} catch (error) {
|
||||
console.error("修改订单金额失败:", error);
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
init,
|
||||
updateOrderAmountByBikeCode
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<a-row class="grid-demo" :gutter="[24, 40]">
|
||||
<a-col :span="12">
|
||||
<div>车辆编号:{{ formData.bikeCode }}</div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<div>订单编号:{{ formData.orderId }}</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row class="grid-demo" :gutter="[24, 40]">
|
||||
<a-col :span="12">
|
||||
<div>实付金额:{{ formData.actualAmount }}元</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row class="grid-demo" :gutter="[24, 40]">
|
||||
<a-col :span="12">
|
||||
<div>
|
||||
修改金额:
|
||||
<a-input-number
|
||||
v-model="formData.price"
|
||||
:style="{ width: '200px' }"
|
||||
placeholder="Please Enter"
|
||||
:default-value="0"
|
||||
:min="0"
|
||||
:step="0.5"
|
||||
:precision="2"
|
||||
class="input-demo"
|
||||
/>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,54 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import { deepClone } from "@/utils";
|
||||
import { endUserRideOrderAPI } from "@/api/modules/order";
|
||||
|
||||
const formData = ref({
|
||||
bikeCode: "",
|
||||
orderId: "",
|
||||
actualAmount: 0,
|
||||
price: 0
|
||||
});
|
||||
|
||||
const init = (data: any) => {
|
||||
formData.value = {
|
||||
...deepClone(data),
|
||||
price: 0
|
||||
};
|
||||
};
|
||||
const endUserRideOrder = async () => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const res: any = await endUserRideOrderAPI({
|
||||
bikeCode: formData.value.bikeCode
|
||||
});
|
||||
resolve(res.data);
|
||||
} catch (error) {
|
||||
console.error("修改订单金额失败:", error);
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
init,
|
||||
endUserRideOrder
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div>
|
||||
<a-row class="grid-demo" :gutter="[24, 40]">
|
||||
<a-col :span="12">
|
||||
<div>车辆编号:{{ formData.bikeCode }}</div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<div>订单编号:{{ formData.orderId }}</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@ -1,279 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import { getUserOrderListAPI, getBikeDetailAPI } from "@/api/modules/order";
|
||||
import { dictTranslate } from "@/utils";
|
||||
import { getOperatorAllListAPI } from "@/api/modules/system";
|
||||
import changePriceModal from "./components/changePriceModal.vue";
|
||||
import closeBikeModal from "./components/closeBikeModal.vue";
|
||||
import { Message } from "@arco-design/web-vue";
|
||||
import bikeMap from "../../component/bikeMap/bikeMap.vue";
|
||||
|
||||
const form = ref<any>({
|
||||
bikeCode: ""
|
||||
});
|
||||
|
||||
// 列表
|
||||
const operatorAllList = ref<any>([]);
|
||||
const moduleList = ref([]);
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
current: 1,
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
showPageSize: true,
|
||||
showTotal: true
|
||||
});
|
||||
|
||||
// 模态框
|
||||
const open = ref<boolean>(false);
|
||||
const title = ref<string>("");
|
||||
const componenType = ref<string>("changePrice");
|
||||
const closeBikeModalRef = ref<any>(null);
|
||||
const changePriceModalRef = ref<any>(null);
|
||||
const bikeMapRef = ref<any>(null);
|
||||
const loadingOk = ref(false);
|
||||
|
||||
const search = () => {
|
||||
pagination.value.current = 1;
|
||||
getUserOrderList();
|
||||
};
|
||||
const reset = () => {
|
||||
form.value = {
|
||||
bikeCode: ""
|
||||
};
|
||||
search();
|
||||
};
|
||||
|
||||
const getUserOrderList = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res: any = await getUserOrderListAPI({
|
||||
bikeCode: form.value.bikeCode,
|
||||
pageNum: pagination.value.current,
|
||||
pageSize: pagination.value.pageSize
|
||||
});
|
||||
loading.value = false;
|
||||
if (res.code !== 200) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { records, pageNumber, pageSize } = res.data;
|
||||
pagination.value.current = pageNumber;
|
||||
pagination.value.pageSize = pageSize;
|
||||
pagination.value.total = res.data.totalRow;
|
||||
moduleList.value = records;
|
||||
} catch (error) {
|
||||
console.error("获取列表失败:", error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
pagination.value.current = page;
|
||||
getUserOrderList();
|
||||
};
|
||||
|
||||
const handlePageSizeChange = (pageSize: number) => {
|
||||
pagination.value.pageSize = pageSize;
|
||||
pagination.value.current = 1;
|
||||
getUserOrderList();
|
||||
};
|
||||
|
||||
//翻译字典值
|
||||
const dictFormat = (list: any[], key: string, value: string | number, valueKey: string = "dicValueName") => {
|
||||
return dictTranslate(list, key, value, valueKey);
|
||||
};
|
||||
|
||||
// 获取所有运营商列表
|
||||
const getAllOperatorList = async () => {
|
||||
return new Promise<void>(async resolve => {
|
||||
try {
|
||||
const res: any = await getOperatorAllListAPI();
|
||||
if (res.code === 200) {
|
||||
operatorAllList.value = res.data;
|
||||
resolve();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取运营商列表失败:", error);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const afterClose = () => {
|
||||
open.value = false;
|
||||
};
|
||||
|
||||
const handleOpenModal = async (record: any, type: string) => {
|
||||
Message.loading("正在获取车辆详情...");
|
||||
try {
|
||||
const { data } = await getBikeDetailAPI(record.bikeCode);
|
||||
const { location } = data;
|
||||
bikeMapRef.value.initMap(location);
|
||||
componenType.value = type;
|
||||
open.value = true;
|
||||
if (type === "changePrice") {
|
||||
title.value = "修改价格";
|
||||
changePriceModalRef.value.init(record);
|
||||
} else if (type === "closeBike") {
|
||||
closeBikeModalRef.value.init(record);
|
||||
title.value = "远程锁车";
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取车辆详情失败:", error);
|
||||
return;
|
||||
} finally {
|
||||
Message.clear();
|
||||
}
|
||||
};
|
||||
|
||||
const comfirmChangePrice = async () => {
|
||||
loadingOk.value = true;
|
||||
try {
|
||||
await changePriceModalRef.value.updateOrderAmountByBikeCode();
|
||||
arcoMessage("success", "修改订单金额成功");
|
||||
afterClose();
|
||||
getUserOrderList();
|
||||
} catch (error) {
|
||||
console.error("修改订单金额失败:", error);
|
||||
} finally {
|
||||
loadingOk.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const comfirmClostBike = async () => {
|
||||
try {
|
||||
await closeBikeModalRef.value.endUserRideOrder();
|
||||
arcoMessage("success", "远程锁车成功");
|
||||
afterClose();
|
||||
getUserOrderList();
|
||||
} catch (error) {
|
||||
console.error("远程锁车失败:", error);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getUserOrderList();
|
||||
});
|
||||
|
||||
onBeforeMount(async () => {
|
||||
await getAllOperatorList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="snow-page">
|
||||
<div class="snow-inner">
|
||||
<s-layout-tools>
|
||||
<template #left>
|
||||
<a-space wrap>
|
||||
<a-input :style="{ width: '200px' }" v-model="form.bikeCode" placeholder="车辆编号" allow-clear />
|
||||
<a-button type="primary" @click="search">
|
||||
<template #icon><icon-search /></template>
|
||||
<span>查询</span>
|
||||
</a-button>
|
||||
<a-button @click="reset">
|
||||
<template #icon><icon-refresh /></template>
|
||||
<span>重置</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</s-layout-tools>
|
||||
<a-table
|
||||
row-key="refundId"
|
||||
:data="moduleList"
|
||||
:bordered="{ cell: true }"
|
||||
:loading="loading"
|
||||
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
|
||||
:pagination="pagination"
|
||||
@page-change="handlePageChange"
|
||||
@page-size-change="handlePageSizeChange"
|
||||
>
|
||||
<template #columns>
|
||||
<a-table-column title="序号" :width="60" align="center">
|
||||
<template #cell="cell">
|
||||
<span>{{ (pagination.current - 1) * pagination.pageSize + cell.rowIndex + 1 }}</span>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="车辆编号" data-index="bikeCode" align="center"></a-table-column>
|
||||
<a-table-column title="订单编号" data-index="orderId" align="center"></a-table-column>
|
||||
<a-table-column title="运营商" data-index="operatorId" align="center">
|
||||
<template #cell="{ record }">
|
||||
<span>{{ dictFormat(operatorAllList, "operatorId", record.operatorId, "operatorName") }}</span>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="实付金额" data-index="actualAmount" align="center">
|
||||
<template #cell="{ record }">
|
||||
<span>{{ record.actualAmount }} 元</span>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="订单创建时间" data-index="startTime" align="center"></a-table-column>
|
||||
<a-table-column title="操作" align="center" :fixed="'right'">
|
||||
<template #cell="{ record }">
|
||||
<a-space>
|
||||
<a-button type="primary" size="mini" @click="handleOpenModal(record, 'changePrice')">
|
||||
<span>修改价格</span>
|
||||
</a-button>
|
||||
<a-button status="danger" type="primary" size="mini" @click="handleOpenModal(record, 'closeBike')">
|
||||
<span>远程锁车</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
|
||||
<!-- 模态框 -->
|
||||
<a-modal v-model:visible="open" :width="900" @close="afterClose">
|
||||
<template #title> {{ title }} </template>
|
||||
<div class="container">
|
||||
<div class="mapContent">
|
||||
<bikeMap ref="bikeMapRef" />
|
||||
</div>
|
||||
<div v-show="componenType === 'changePrice'">
|
||||
<changePriceModal ref="changePriceModalRef" />
|
||||
</div>
|
||||
<div v-show="componenType === 'closeBike'">
|
||||
<closeBikeModal ref="closeBikeModalRef" />
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="footer-btn">
|
||||
<a-button
|
||||
v-if="componenType === 'changePrice'"
|
||||
type="primary"
|
||||
style="margin-right: 20px"
|
||||
:loading="loadingOk"
|
||||
@click="comfirmChangePrice"
|
||||
>
|
||||
确认修改
|
||||
</a-button>
|
||||
<a-button
|
||||
v-else-if="componenType === 'closeBike'"
|
||||
type="primary"
|
||||
style="margin-right: 20px"
|
||||
@click="comfirmClostBike"
|
||||
:loading="loadingOk"
|
||||
>
|
||||
确认锁车
|
||||
</a-button>
|
||||
<a-button @click="afterClose">取消</a-button>
|
||||
</div>
|
||||
</template>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mapContent {
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.footer-btn {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
@ -20,7 +20,6 @@ const moduleList = ref([]);
|
||||
const loading = ref(false);
|
||||
const pagination = ref({
|
||||
current: 1,
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
showPageSize: true,
|
||||
showTotal: true
|
||||
@ -32,7 +31,7 @@ const title = ref<string>("");
|
||||
const loadingOk = ref<boolean>(false);
|
||||
const addFormRef = ref();
|
||||
const addForm = ref<any>({
|
||||
reviewId: "",
|
||||
refundId: "",
|
||||
reason: "",
|
||||
operate: -1,
|
||||
refundMethod: 0
|
||||
@ -88,11 +87,11 @@ const getUserRefundList = async () => {
|
||||
if (res.code !== 200) {
|
||||
return;
|
||||
}
|
||||
console.log(res);
|
||||
|
||||
const { records, pageNumber, pageSize } = res.data;
|
||||
pagination.value.current = pageNumber;
|
||||
pagination.value.pageSize = pageSize;
|
||||
pagination.value.total = res.data.totalRow;
|
||||
moduleList.value = records;
|
||||
} catch (error) {
|
||||
console.error("获取员工列表失败:", error);
|
||||
@ -103,20 +102,20 @@ const getUserRefundList = async () => {
|
||||
|
||||
const auditOrder = (record: any) => {
|
||||
title.value = "退款审核";
|
||||
getRefundOrderDetail(record.refundId, record.reviewId);
|
||||
getRefundOrderDetail(record.refundId);
|
||||
};
|
||||
|
||||
const handleDetail = (record: any) => {
|
||||
title.value = "退款详情";
|
||||
getRefundOrderDetail(record.refundId, record.reviewId);
|
||||
getRefundOrderDetail(record.refundId);
|
||||
};
|
||||
const getRefundOrderDetail = async (refundId: string, reviewId: string) => {
|
||||
const getRefundOrderDetail = async (refundId: string) => {
|
||||
try {
|
||||
const res: any = await getRefundOrderDetailAPI(refundId);
|
||||
if (res.code == 200) {
|
||||
open.value = true;
|
||||
refundDetail.value = res.data;
|
||||
addForm.value.reviewId = reviewId;
|
||||
addForm.value.refundId = refundId;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取退款订单详情失败:", error);
|
||||
@ -128,6 +127,7 @@ const checkOrder = async (operate: number) => {
|
||||
const userInfo = localStorage.getItem("user-info");
|
||||
let staffId = "";
|
||||
if (userInfo) {
|
||||
console.log(JSON.parse(userInfo));
|
||||
staffId = JSON.parse(userInfo).account.staffId;
|
||||
} else {
|
||||
console.warn("未找到 user-info 信息");
|
||||
@ -135,7 +135,7 @@ const checkOrder = async (operate: number) => {
|
||||
|
||||
try {
|
||||
const res: any = await reviewRefundApplicationAPI({
|
||||
reviewId: addForm.value.reviewId,
|
||||
refundId: addForm.value.refundId,
|
||||
operate,
|
||||
staffId,
|
||||
reason: addForm.value.reason,
|
||||
@ -226,11 +226,11 @@ onBeforeMount(async () => {
|
||||
<a-table-column title="订单编号" data-index="orderId" align="center"></a-table-column>
|
||||
<a-table-column title="用户手机号" data-index="mobile" align="center"></a-table-column>
|
||||
<a-table-column title="申请退款金额" data-index="refundApply" align="center"></a-table-column>
|
||||
<!-- <a-table-column title="订单状态" data-index="processStatus" align="center">
|
||||
<a-table-column title="订单状态" data-index="processStatus" align="center">
|
||||
<template #cell="{ record }">
|
||||
<span>{{ dictFormat(inventoryTypeList, "dicValue", record.orderStatus) }}</span>
|
||||
</template>
|
||||
</a-table-column> -->
|
||||
</a-table-column>
|
||||
<a-table-column title="处理状态" data-index="processStatus" align="center">
|
||||
<template #cell="{ record }">
|
||||
<span>{{ dictFormat(refundStatusList, "dicValue", record.processStatus) }}</span>
|
||||
|
||||
@ -1,3 +1,85 @@
|
||||
<template>
|
||||
<div class="snow-page">
|
||||
<div class="snow-inner">
|
||||
<s-layout-tools>
|
||||
<template #right>
|
||||
<a-space wrap>
|
||||
<a-button type="primary" @click="onAdd">
|
||||
<template #icon><icon-plus /></template>
|
||||
<span>新增</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</s-layout-tools>
|
||||
<a-table
|
||||
row-key="id"
|
||||
:data="moduleList"
|
||||
:bordered="{ cell: true }"
|
||||
:loading="loading"
|
||||
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
|
||||
:pagination="pagination"
|
||||
@page-change="handlePageChange"
|
||||
@page-size-change="handlePageSizeChange"
|
||||
>
|
||||
<template #columns>
|
||||
<a-table-column title="中控SN码" data-index="ecuSn" align="center"></a-table-column>
|
||||
<a-table-column title="中控编号" data-index="ecuCode" align="center"></a-table-column>
|
||||
<a-table-column title="运营商" data-index="operatorId" align="center">
|
||||
<template #cell="{ record }">
|
||||
<span>{{ dictFormat(operatorAllList, "operatorId", record.operatorId, "operatorName") }}</span>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="中控品牌" data-index="ecuBrand" align="center">
|
||||
<template #cell="{ record }">
|
||||
<span>{{ dictFormat(ecuBrandList, "dicValue", record.ecuBrand) }}</span>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="创建时间" data-index="createdAt" :width="180" align="center"></a-table-column>
|
||||
<!-- TUDO: 暂时不做操作功能 -->
|
||||
<!-- <a-table-column title="操作" :width="280" align="center" :fixed="'right'">
|
||||
<template #cell="{ record }">
|
||||
<a-space>
|
||||
<a-button type="primary" size="mini" :disabled="record.sysRole">
|
||||
<template #icon><icon-edit /></template>
|
||||
<span>修改</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table-column> -->
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
<!-- 模态框 -->
|
||||
<a-modal v-model:visible="open" @close="afterClose" @before-ok="handleOk" @cancel="afterClose">
|
||||
<template #title> {{ title }} </template>
|
||||
<a-form ref="addFormRef" :model="addForm" :rules="rules" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }">
|
||||
<a-form-item field="ecuCode" label="中控编号" validate-trigger="blur">
|
||||
<a-input v-model="addForm.ecuCode" placeholder="请输入中控编号" />
|
||||
</a-form-item>
|
||||
<a-form-item field="ecuSn" label="中控SN码" validate-trigger="blur">
|
||||
<a-input v-model="addForm.ecuSn" placeholder="请输入中控SN码" />
|
||||
</a-form-item>
|
||||
<a-form-item field="operatorId" label="运营商">
|
||||
<a-select v-model="addForm.operatorId" placeholder="请选择运营商" validate-trigger="change">
|
||||
<a-option v-for="it in operatorAllList" :key="it.operatorId" :value="it.operatorId">{{ it.operatorName }}</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item field="ecuBrand" label="中控品牌">
|
||||
<a-select v-model="addForm.ecuBrand" placeholder="请选择中控品牌" validate-trigger="change">
|
||||
<a-option v-for="it in ecuBrandList" :key="it.dicId" :value="it.dicValue">{{ it.dicValueName }}</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item field="bindBattery" label="是否绑定电池">
|
||||
<a-radio-group v-model="addForm.bindBattery">
|
||||
<a-radio :value="true">是</a-radio>
|
||||
<a-radio :value="false">否</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getOperatorAllListAPI } from "@/api/modules/system";
|
||||
import { useSystemStore } from "@/store/modules/system";
|
||||
@ -157,85 +239,5 @@ onBeforeMount(async () => {
|
||||
await getAllOperatorList();
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="snow-page">
|
||||
<div class="snow-inner">
|
||||
<s-layout-tools>
|
||||
<template #right>
|
||||
<a-space wrap>
|
||||
<a-button type="primary" @click="onAdd">
|
||||
<template #icon><icon-plus /></template>
|
||||
<span>新增</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</s-layout-tools>
|
||||
<a-table
|
||||
row-key="id"
|
||||
:data="moduleList"
|
||||
:bordered="{ cell: true }"
|
||||
:loading="loading"
|
||||
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
|
||||
:pagination="pagination"
|
||||
@page-change="handlePageChange"
|
||||
@page-size-change="handlePageSizeChange"
|
||||
>
|
||||
<template #columns>
|
||||
<a-table-column title="中控SN码" data-index="ecuSn" align="center"></a-table-column>
|
||||
<a-table-column title="中控编号" data-index="ecuCode" align="center"></a-table-column>
|
||||
<a-table-column title="运营商" data-index="operatorId" align="center">
|
||||
<template #cell="{ record }">
|
||||
<span>{{ dictFormat(operatorAllList, "operatorId", record.operatorId, "operatorName") }}</span>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="中控品牌" data-index="ecuBrand" align="center">
|
||||
<template #cell="{ record }">
|
||||
<span>{{ dictFormat(ecuBrandList, "dicValue", record.ecuBrand) }}</span>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="创建时间" data-index="createdAt" :width="180" align="center"></a-table-column>
|
||||
<!-- TUDO: 暂时不做操作功能 -->
|
||||
<!-- <a-table-column title="操作" :width="280" align="center" :fixed="'right'">
|
||||
<template #cell="{ record }">
|
||||
<a-space>
|
||||
<a-button type="primary" size="mini" :disabled="record.sysRole">
|
||||
<template #icon><icon-edit /></template>
|
||||
<span>修改</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table-column> -->
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
<!-- 模态框 -->
|
||||
<a-modal v-model:visible="open" @close="afterClose" @before-ok="handleOk" @cancel="afterClose">
|
||||
<template #title> {{ title }} </template>
|
||||
<a-form ref="addFormRef" :model="addForm" :rules="rules" :label-col-props="{ span: 6 }" :wrapper-col-props="{ span: 18 }">
|
||||
<a-form-item field="ecuCode" label="中控编号" validate-trigger="blur">
|
||||
<a-input v-model="addForm.ecuCode" placeholder="请输入中控编号" />
|
||||
</a-form-item>
|
||||
<a-form-item field="ecuSn" label="中控SN码" validate-trigger="blur">
|
||||
<a-input v-model="addForm.ecuSn" placeholder="请输入中控SN码" />
|
||||
</a-form-item>
|
||||
<a-form-item field="operatorId" label="运营商">
|
||||
<a-select v-model="addForm.operatorId" placeholder="请选择运营商" validate-trigger="change">
|
||||
<a-option v-for="it in operatorAllList" :key="it.operatorId" :value="it.operatorId">{{ it.operatorName }}</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item field="ecuBrand" label="中控品牌">
|
||||
<a-select v-model="addForm.ecuBrand" placeholder="请选择中控品牌" validate-trigger="change">
|
||||
<a-option v-for="it in ecuBrandList" :key="it.dicId" :value="it.dicValue">{{ it.dicValueName }}</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item field="bindBattery" label="是否绑定电池">
|
||||
<a-radio-group v-model="addForm.bindBattery">
|
||||
<a-radio :value="true">是</a-radio>
|
||||
<a-radio :value="false">否</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -1,162 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { getOperatorAllListAPI } from "@/api/modules/system";
|
||||
import { addOrUpdateOperatorConfigAPI, getOperatorConfigByOperatorIdAPI } from "@/api/modules/serviceConfiguration";
|
||||
import { OperatorConfigFormType } from "@/api/modules/serviceConfiguration/types";
|
||||
import { deepClone } from "@/utils";
|
||||
|
||||
const operatorAllList = ref<any>([]);
|
||||
const addFormRef = ref<any>(null);
|
||||
const addForm = ref<OperatorConfigFormType>({
|
||||
operatorId: "",
|
||||
dispatchDuration: undefined,
|
||||
rideDuration: undefined,
|
||||
inspectionIntervalDuration: undefined,
|
||||
operatorPhone: ""
|
||||
});
|
||||
const rules = {
|
||||
operatorId: [{ required: true, message: "请选择运营商", trigger: "change" }],
|
||||
dispatchDuration: [{ required: true, message: "请输入配置项时长", trigger: "change" }],
|
||||
rideDuration: [{ required: true, message: "请输入配置项骑行时长", trigger: "change" }],
|
||||
inspectionIntervalDuration: [{ required: true, message: "请输入配置项时长", trigger: "change" }],
|
||||
operatorPhone: [{ required: true, message: "请输入运营商手机号", trigger: "change" }]
|
||||
};
|
||||
const isLoading = ref<boolean>(false);
|
||||
|
||||
// 获取所有运营商列表
|
||||
const getAllOperatorList = async () => {
|
||||
return new Promise<void>(async resolve => {
|
||||
try {
|
||||
const res: any = await getOperatorAllListAPI();
|
||||
if (res.code === 200) {
|
||||
operatorAllList.value = res.data;
|
||||
resolve();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取运营商列表失败:", error);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 提交表单
|
||||
async function submit() {
|
||||
let state = await addFormRef.value.validate();
|
||||
if (state) return false; // 校验不通过
|
||||
|
||||
isLoading.value = true;
|
||||
const params = deepClone(addForm.value);
|
||||
try {
|
||||
const res: any = await addOrUpdateOperatorConfigAPI(params);
|
||||
arcoMessage("success", "保存成功");
|
||||
} catch (error) {
|
||||
console.error("保存失败:", error);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => addForm.value.operatorId,
|
||||
async newOperatorId => {
|
||||
if (newOperatorId) {
|
||||
try {
|
||||
const { data }: any = await getOperatorConfigByOperatorIdAPI(newOperatorId);
|
||||
if (data) {
|
||||
addForm.value = { ...addForm.value, ...data };
|
||||
} else {
|
||||
addForm.value = {
|
||||
operatorId: newOperatorId,
|
||||
dispatchDuration: undefined,
|
||||
rideDuration: undefined,
|
||||
inspectionIntervalDuration: undefined,
|
||||
operatorPhone: ""
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取运营商配置失败:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(async () => {
|
||||
await getAllOperatorList();
|
||||
addForm.value.operatorId = operatorAllList.value.length > 0 ? operatorAllList.value[0].operatorId : "";
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="snow-page">
|
||||
<div class="snow-inner">
|
||||
<div class="header">运营商配置</div>
|
||||
<div class="form_bar">
|
||||
<a-form ref="addFormRef" :model="addForm" :rules="rules">
|
||||
<a-form-item field="operatorId" label="运营商:" validate-trigger="blur">
|
||||
<a-select v-model="addForm.operatorId" :style="{ width: '320px' }" placeholder="请选择">
|
||||
<a-option v-for="it in operatorAllList" :key="it.operatorId" :value="it.operatorId">{{ it.operatorName }}</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="dispatchDuration"
|
||||
label="时长配置(h):"
|
||||
validate-trigger="blur"
|
||||
tooltip="车辆多长时间无单生成调度工单"
|
||||
>
|
||||
<a-input-number
|
||||
v-model="addForm.dispatchDuration"
|
||||
:style="{ width: '320px' }"
|
||||
placeholder="请输入配置项时长"
|
||||
:min="0"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
field="rideDuration"
|
||||
label="骑行时长配置(h):"
|
||||
validate-trigger="blur"
|
||||
tooltip="调度完成后多长时间内骑行是有效的"
|
||||
>
|
||||
<a-input-number
|
||||
v-model="addForm.rideDuration"
|
||||
:style="{ width: '320px' }"
|
||||
placeholder="请输入骑行时长配置"
|
||||
:min="0"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item field="inspectionIntervalDuration" label="巡检间隔时长(日):" validate-trigger="blur">
|
||||
<a-input-number
|
||||
v-model="addForm.inspectionIntervalDuration"
|
||||
:style="{ width: '320px' }"
|
||||
placeholder="请输入巡检间隔时长"
|
||||
:min="0"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item field="operatorPhone" label="联系电话:" validate-trigger="blur">
|
||||
<a-input :style="{ width: '320px' }" placeholder="请输入联系电话" allow-clear v-model="addForm.operatorPhone" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<a-button type="primary" :loading="isLoading" @click="submit">{{ isLoading ? "正在保存中..." : "保存" }}</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
width: 100%;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 50px;
|
||||
}
|
||||
.form_bar {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
@ -405,8 +405,7 @@ const onDetailUpdate = (record: any) => {
|
||||
deatilForm.value.dicValueId = record.dicValueId;
|
||||
deatilForm.value.dicValueName = record.dicValueName;
|
||||
deatilForm.value.dicValue = record.dicValue;
|
||||
deatilForm.value.dicIcon = record.dicIcon;
|
||||
deatilForm.value.dicId = record.dicId;
|
||||
deatilForm.value.dicId = recordData.value.dicId;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -16,10 +16,10 @@ const form = ref({
|
||||
|
||||
const pagination = ref({
|
||||
current: 1,
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
showPageSize: true,
|
||||
showTotal: true
|
||||
showTotal: true,
|
||||
total: 0
|
||||
});
|
||||
|
||||
/**
|
||||
@ -100,17 +100,9 @@ const onAdd = () => {
|
||||
fileList.value = [];
|
||||
};
|
||||
|
||||
const search = () => {
|
||||
pagination.value.current = 1;
|
||||
getImageList();
|
||||
};
|
||||
const search = () => {};
|
||||
|
||||
const reset = () => {
|
||||
form.value = {
|
||||
imgName: ""
|
||||
};
|
||||
search();
|
||||
};
|
||||
const reset = () => {};
|
||||
|
||||
// 删除
|
||||
const onDelete = async (record: any) => {
|
||||
@ -170,16 +162,6 @@ const handleOk = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 复制图片链接到剪贴板
|
||||
async function copyFileUrl(record: any) {
|
||||
const { fileUrl } = record;
|
||||
console.log(navigator.clipboard);
|
||||
if (navigator.clipboard) {
|
||||
const res: any = await navigator.clipboard.writeText(fileUrl);
|
||||
arcoMessage("success", "复制成功");
|
||||
}
|
||||
}
|
||||
|
||||
async function getImageList() {
|
||||
loading.value = true;
|
||||
try {
|
||||
@ -204,17 +186,6 @@ async function getImageList() {
|
||||
}
|
||||
}
|
||||
|
||||
const handlePageSizeChange = (pageSize: number) => {
|
||||
pagination.value.pageSize = pageSize;
|
||||
pagination.value.current = 1;
|
||||
getImageList();
|
||||
};
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
pagination.value.current = page;
|
||||
getImageList();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getImageList();
|
||||
});
|
||||
@ -253,10 +224,6 @@ onMounted(() => {
|
||||
:bordered="{ cell: true }"
|
||||
row-key="id"
|
||||
:loading="loading"
|
||||
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
|
||||
:pagination="pagination"
|
||||
@page-change="handlePageChange"
|
||||
@page-size-change="handlePageSizeChange"
|
||||
>
|
||||
<template #columns>
|
||||
<a-table-column align="center" title="图片名称" data-index="imgName" :ellipsis="true" :tooltip="true"></a-table-column>
|
||||
@ -270,11 +237,7 @@ onMounted(() => {
|
||||
/>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="图片后缀" align="center" data-index="fileUrl" :ellipsis="true" :tooltip="true">
|
||||
<template #cell="{ record }">
|
||||
<a-link @click="copyFileUrl(record)">{{ record.fileUrl }}</a-link>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="图片后缀" align="center" data-index="fileUrl" :ellipsis="true" :tooltip="true"></a-table-column>
|
||||
<a-table-column
|
||||
title="创建时间"
|
||||
align="center"
|
||||
@ -323,7 +286,7 @@ onMounted(() => {
|
||||
Authorization: `${token}`
|
||||
}"
|
||||
:data="{
|
||||
imgCode: addForm.imgCode ? addForm.imgCode : ''
|
||||
fileType: 'ebikeImg'
|
||||
}"
|
||||
@error="fileError"
|
||||
:on-before-remove="deleteFile"
|
||||
@ -334,6 +297,4 @@ onMounted(() => {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
//
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@ -1,208 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { onlineUpgradeAPI } from "@/api/modules/system";
|
||||
import { deepClone, dictTranslate } from "@/utils";
|
||||
import { useSystemStore } from "@/store/modules/system";
|
||||
import { useUserInfoStore } from "@/store/modules/user-info";
|
||||
import axios from "axios";
|
||||
const { VITE_APP_BASE_URL, MODE } = import.meta.env;
|
||||
|
||||
// 上传远程升级文件
|
||||
const remoteUpgradeUrl =
|
||||
MODE === "development" ? "/api/operations/ebikeEcuInfo/upload" : VITE_APP_BASE_URL + "/operations/ebikeEcuInfo/upload";
|
||||
|
||||
const system = useSystemStore();
|
||||
const { token } = useUserInfoStore();
|
||||
const addFormRef = ref<any>(null);
|
||||
const fileList = ref<any[]>([]);
|
||||
const isLoading = ref<boolean>(false);
|
||||
const addForm = ref<any>({
|
||||
fullUpgrade: false,
|
||||
ecuSn: "",
|
||||
bikeCode: "",
|
||||
ecuBrand: "",
|
||||
type: "",
|
||||
url: ""
|
||||
});
|
||||
const options = [
|
||||
{ label: "是", value: true },
|
||||
{ label: "否", value: false }
|
||||
];
|
||||
const ecuBrandList = ref<any[]>([]);
|
||||
const typeList = ref<any[]>([]);
|
||||
|
||||
const rules = {
|
||||
fullUpgrade: [{ required: true, message: "请选择是否全部升级", trigger: "change", type: "boolean" }],
|
||||
ecuBrand: [{ required: true, message: "请选择中控品牌", trigger: "change" }],
|
||||
type: [{ required: true, message: "请选择升级类型", trigger: "change" }],
|
||||
url: [{ required: true, message: "请上传文件地址", trigger: "change" }]
|
||||
};
|
||||
|
||||
function fileSuccess(fileItem: any) {
|
||||
const { response } = fileItem;
|
||||
// addForm.value.url = response.data;
|
||||
console.log("response:", response.data);
|
||||
}
|
||||
function fileError(err: any) {
|
||||
console.error("err:", err);
|
||||
}
|
||||
|
||||
// 自定义上传
|
||||
async function customRequest(option: any) {
|
||||
const { onProgress, onError, onSuccess, fileItem, name } = option;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append(name || "file", fileItem.file);
|
||||
try {
|
||||
const response = await axios.post(remoteUpgradeUrl, formData, {
|
||||
headers: {
|
||||
Authorization: token,
|
||||
"Content-Type": "multipart/form-data"
|
||||
},
|
||||
onUploadProgress: (progressEvent: any) => {
|
||||
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
||||
onProgress(percentCompleted, progressEvent);
|
||||
},
|
||||
timeout: 60000 // 可选:设置超时
|
||||
});
|
||||
if (response.status === 200) {
|
||||
onSuccess(response.data, fileItem);
|
||||
addForm.value.url = response.data.data.fileUrl;
|
||||
} else {
|
||||
onError(new Error("上传失败"), fileItem);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("上传失败:", error);
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
addForm.value = {
|
||||
fullUpgrade: false,
|
||||
ecuSn: "",
|
||||
bikeCode: "",
|
||||
ecuBrand: "",
|
||||
type: "",
|
||||
url: ""
|
||||
};
|
||||
fileList.value = [];
|
||||
if (addFormRef.value) {
|
||||
addFormRef.value.resetFields();
|
||||
}
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
async function submit() {
|
||||
if (fileList.value.length > 0) {
|
||||
const file = fileList.value[0];
|
||||
addForm.value.url = file.response.data;
|
||||
}
|
||||
|
||||
let state = await addFormRef.value.validate();
|
||||
if (state) return false; // 校验不通过
|
||||
|
||||
isLoading.value = true;
|
||||
try {
|
||||
const res: any = await onlineUpgradeAPI(deepClone(addForm.value));
|
||||
if (res) {
|
||||
arcoMessage("success", "升级成功,请耐心等待设备升级完成");
|
||||
resetForm();
|
||||
} else {
|
||||
arcoMessage("error", "升级失败");
|
||||
}
|
||||
} catch (error: any) {
|
||||
arcoMessage("error", `${error.message} || '升级失败'`);
|
||||
console.error("升级失败:", error);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeMount(async () => {
|
||||
ecuBrandList.value = deepClone(system.getDictByCode("ecuBrandCode"));
|
||||
typeList.value = deepClone(system.getDictByCode("ECU_UPGRADE"));
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="snow-page">
|
||||
<div class="snow-inner">
|
||||
<div class="header">模块在线升级</div>
|
||||
<div class="form_bar">
|
||||
<a-form ref="addFormRef" :model="addForm" :rules="rules">
|
||||
<a-form-item field="fullUpgrade" label="是否全部升级:" validate-trigger="blur">
|
||||
<a-radio-group v-model="addForm.fullUpgrade" :options="options" />
|
||||
</a-form-item>
|
||||
<a-form-item v-if="!addForm.fullUpgrade" field="bikeCode" label="车辆编号:" validate-trigger="blur">
|
||||
<a-input :style="{ width: '320px' }" placeholder="请输入车辆编号" allow-clear v-model="addForm.bikeCode" />
|
||||
</a-form-item>
|
||||
<a-form-item v-if="!addForm.fullUpgrade" field="ecuSn" label="中控编号:" validate-trigger="blur">
|
||||
<a-input :style="{ width: '320px' }" placeholder="请输入中控编号" allow-clear v-model="addForm.ecuSn" />
|
||||
</a-form-item>
|
||||
<a-form-item field="ecuBrand" label="中控品牌:" validate-trigger="blur">
|
||||
<a-select v-model="addForm.ecuBrand" :style="{ width: '320px' }" placeholder="请选择">
|
||||
<a-option v-for="it in ecuBrandList" :key="it.dicId" :value="it.dicValue">{{ it.dicValueName }}</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item field="type" label="升级类型:" validate-trigger="blur">
|
||||
<a-select v-model="addForm.type" :style="{ width: '320px' }" placeholder="请选择" allow-search>
|
||||
<a-option v-for="it in typeList" :key="it.dicId" :value="it.dicValue">{{ it.dicValueName }}</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item field="url" label="上传升级文件:" validate-trigger="blur">
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
name="file"
|
||||
:custom-request="customRequest"
|
||||
:limit="1"
|
||||
@success="fileSuccess"
|
||||
@error="fileError"
|
||||
>
|
||||
<template #upload-button>
|
||||
<div
|
||||
style="
|
||||
background-color: var(--color-fill-2);
|
||||
color: var(--color-text-1);
|
||||
border: 1px dashed var(--color-fill-4);
|
||||
height: 158px;
|
||||
width: 380px;
|
||||
border-radius: 2;
|
||||
line-height: 158px;
|
||||
text-align: center;
|
||||
"
|
||||
>
|
||||
<div>
|
||||
拖动文件 或
|
||||
<span style="color: #3370ff"> 点击上传</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<a-button type="primary" :loading="isLoading" @click="submit">{{ isLoading ? "正在升级中" : "升级设备" }}</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.header {
|
||||
width: 100%;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 50px;
|
||||
}
|
||||
.form_bar {
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
@ -249,6 +249,7 @@ const onUpdate = async (record: any) => {
|
||||
try {
|
||||
let res: any = await getStaffByIdAPI(record.staffId);
|
||||
if (res.code === 200) {
|
||||
console.log(filterIds(res.data.roles, "roleId"));
|
||||
addForm.value = {
|
||||
staffId: res.data.staffId,
|
||||
username: res.data.username,
|
||||
|
||||
@ -235,9 +235,7 @@ const handleUpdate = (record: any) => {
|
||||
open.value = true;
|
||||
title.value = "修改运营区";
|
||||
const data = deepClone(record);
|
||||
if (data.regionPolygon) {
|
||||
data.coordinates = PointDataHandler.restoreForDisplay(data.regionPolygon.coordinates);
|
||||
}
|
||||
AddFormRef.value.updateForm(data);
|
||||
};
|
||||
|
||||
|
||||
@ -124,9 +124,9 @@ const handleUpdate = (record: any) => {
|
||||
};
|
||||
|
||||
const handleDelete = async (record: any) => {
|
||||
const { siteId } = record;
|
||||
const { regionId } = record;
|
||||
try {
|
||||
const res: any = await deleteSiteAPI(siteId);
|
||||
const res: any = await deleteSiteAPI(regionId);
|
||||
if (res.code === 200) {
|
||||
arcoMessage("success", "删除成功");
|
||||
getRegionPage();
|
||||
|
||||
@ -28,7 +28,6 @@ export default defineConfig(({ mode }) => {
|
||||
rewrite: path => path.replace(/^\/api/, ""),
|
||||
bypass(req, res, options) {
|
||||
// @ts-ignore
|
||||
// console.log(res, options);
|
||||
const proxyUrl = new URL(options.rewrite(req.url) || "", options.target)?.href || "";
|
||||
console.log(proxyUrl);
|
||||
req.headers["x-req-proxyUrl"] = proxyUrl;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user