Compare commits
15 Commits
7319fae447
...
ba27975609
Author | SHA1 | Date |
---|---|---|
|
ba27975609 | |
|
e9bde6e00c | |
|
3fa6aa7014 | |
|
63b17eede0 | |
|
7b274988dd | |
|
5dcdca0397 | |
|
1d2cd48a7f | |
|
15bb35c029 | |
|
128afe950e | |
|
c1a1861e09 | |
|
e5c6da07bd | |
|
9d5f885766 | |
|
8c8f65be7f | |
|
12cef7b84f | |
|
8f6ae14e47 |
|
@ -7,7 +7,7 @@
|
||||||
<meta name="renderer" content="webkit" />
|
<meta name="renderer" content="webkit" />
|
||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0" />
|
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0" />
|
||||||
<title>智借还</title>
|
<title>智柜通</title>
|
||||||
<link rel="icon" href="/favicon.ico" />
|
<link rel="icon" href="/favicon.ico" />
|
||||||
<script>
|
<script>
|
||||||
window.process = {};
|
window.process = {};
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<svg width="80" height="80" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="5" y="5" width="90" height="90" rx="10" fill="#E8F5E9" stroke="#81C784"
|
||||||
|
stroke-width="2" />
|
||||||
|
<text x="50" y="45" font-family="Arial, sans-serif" font-size="24" font-weight="bold"
|
||||||
|
fill="#2E7D32" text-anchor="middle">空闲</text>
|
||||||
|
<text x="50" y="75" font-family="Arial, sans-serif" font-size="12"
|
||||||
|
fill="#2E7D32" text-anchor="middle">小格</text>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 482 B |
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"Version": "4.4.0",
|
"Version": "4.4.0",
|
||||||
"Title": "智借还",
|
"Title": "智柜通",
|
||||||
"FixedHeader": true,
|
"FixedHeader": true,
|
||||||
"HiddenSideBar": false,
|
"HiddenSideBar": false,
|
||||||
"MultiTagsCache": false,
|
"MultiTagsCache": false,
|
||||||
|
|
|
@ -84,6 +84,12 @@ export interface UpdateAb98UserCommand extends AddAb98UserCommand {
|
||||||
ab98UserId: number;
|
ab98UserId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface BindQyUserCommand {
|
||||||
|
qyUserId: number;
|
||||||
|
name: string;
|
||||||
|
idNum: string;
|
||||||
|
}
|
||||||
|
|
||||||
export const getAb98UserListApi = (params: Ab98UserQuery) => {
|
export const getAb98UserListApi = (params: Ab98UserQuery) => {
|
||||||
return http.request<ResponseData<PageDTO<Ab98UserDTO>>>("get", "/ab98/users", { params });
|
return http.request<ResponseData<PageDTO<Ab98UserDTO>>>("get", "/ab98/users", { params });
|
||||||
};
|
};
|
||||||
|
@ -102,4 +108,8 @@ export const deleteAb98UserApi = (ids: number[]) => {
|
||||||
|
|
||||||
export const getAb98UserDetailApi = (id: number) => {
|
export const getAb98UserDetailApi = (id: number) => {
|
||||||
return http.request<ResponseData<Ab98UserDetailDTO>>("get", `/ab98/users/detail/${id}`);
|
return http.request<ResponseData<Ab98UserDetailDTO>>("get", `/ab98/users/detail/${id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const bindQyUserApi = (data: BindQyUserCommand) => {
|
||||||
|
return http.request<ResponseData<void>>("post", "/ab98/users/bindQyUser", { data });
|
||||||
};
|
};
|
|
@ -45,6 +45,10 @@ export interface SmartCabinetDTO {
|
||||||
belongType?: number;
|
belongType?: number;
|
||||||
usedCells?: number;
|
usedCells?: number;
|
||||||
availableCells?: number;
|
availableCells?: number;
|
||||||
|
/** 运行模式(0-支付模式 1-审批模式 2-借还模式 3-会员模式) */
|
||||||
|
mode?: number;
|
||||||
|
/** 借呗支付(1-正常使用 0-禁止使用) */
|
||||||
|
balanceEnable?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,6 +73,10 @@ export interface AddSmartCabinetCommand {
|
||||||
location: number;
|
location: number;
|
||||||
/** 归属类型(0-借还柜 1-固资通) */
|
/** 归属类型(0-借还柜 1-固资通) */
|
||||||
belongType: number;
|
belongType: number;
|
||||||
|
/** 运行模式(0-支付模式 1-审批模式 2-借还模式 3-会员模式) */
|
||||||
|
mode?: number;
|
||||||
|
/** 借呗支付(1-正常使用 0-禁止使用) */
|
||||||
|
balanceEnable?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -95,6 +103,10 @@ export interface UpdateSmartCabinetCommand {
|
||||||
location?: number;
|
location?: number;
|
||||||
/** 归属类型(0-借还柜 1-固资通) */
|
/** 归属类型(0-借还柜 1-固资通) */
|
||||||
belongType?: number;
|
belongType?: number;
|
||||||
|
/** 运行模式(0-支付模式 1-审批模式 2-借还模式 3-会员模式) */
|
||||||
|
mode?: number;
|
||||||
|
/** 借呗支付(1-正常使用 0-禁止使用) */
|
||||||
|
balanceEnable?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AllCabinetDataDTO {
|
export interface AllCabinetDataDTO {
|
||||||
|
@ -108,6 +120,13 @@ export const getSmartCabinetList = (params?: SmartCabinetQuery) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const getSmartCabinetListQuery = (params?: SmartCabinetQuery) => {
|
||||||
|
return http.request<ResponseData<SmartCabinetDTO[]>>('get', '/cabinet/smartCabinet/list', {
|
||||||
|
params
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const addSmartCabinet = (data: AddSmartCabinetCommand) => {
|
export const addSmartCabinet = (data: AddSmartCabinetCommand) => {
|
||||||
return http.request<ResponseData<void>>('post', '/cabinet/smartCabinet', {
|
return http.request<ResponseData<void>>('post', '/cabinet/smartCabinet', {
|
||||||
data
|
data
|
||||||
|
@ -134,4 +153,20 @@ export const allCabinets = () => {
|
||||||
|
|
||||||
export const getSmartCabinetDetailApi = (cabinetId: number) => {
|
export const getSmartCabinetDetailApi = (cabinetId: number) => {
|
||||||
return http.request<ResponseData<SmartCabinetDTO>>("get", `/cabinet/smartCabinet/detail/${cabinetId}`);
|
return http.request<ResponseData<SmartCabinetDTO>>("get", `/cabinet/smartCabinet/detail/${cabinetId}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取借呗支付状态文字描述
|
||||||
|
* @param balanceEnable 借呗支付状态数字
|
||||||
|
*/
|
||||||
|
export const getBalanceEnableText = (balanceEnable?: number) => {
|
||||||
|
switch (balanceEnable) {
|
||||||
|
case 0:
|
||||||
|
return '禁止使用';
|
||||||
|
case 1:
|
||||||
|
return '正常使用';
|
||||||
|
default:
|
||||||
|
return '未知状态';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -37,6 +37,8 @@ export type TokenDTO = {
|
||||||
token: string;
|
token: string;
|
||||||
/** 当前登录的用户 */
|
/** 当前登录的用户 */
|
||||||
currentUser: CurrentLoginUserDTO;
|
currentUser: CurrentLoginUserDTO;
|
||||||
|
/** 企业微信用户信息 */
|
||||||
|
qyUser: QyUserLoginDTO;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CurrentLoginUserDTO = {
|
export type CurrentLoginUserDTO = {
|
||||||
|
@ -121,4 +123,68 @@ type qyUserinfoQuery = {
|
||||||
/** 获取企业微信访问用户身份接口 */
|
/** 获取企业微信访问用户身份接口 */
|
||||||
export const getQyUserinfo = (params: qyUserinfoQuery) => {
|
export const getQyUserinfo = (params: qyUserinfoQuery) => {
|
||||||
return http.request<ResponseData<string>>("get", "/getQyUserinfo", { params });
|
return http.request<ResponseData<string>>("get", "/getQyUserinfo", { params });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export interface QyUserLoginDTO {
|
||||||
|
/** 用户ID */
|
||||||
|
id?: number;
|
||||||
|
/** 全局唯一ID */
|
||||||
|
openUserid?: string;
|
||||||
|
/** 企业用户ID */
|
||||||
|
userid?: string;
|
||||||
|
/** 汇邦云用户ID */
|
||||||
|
ab98UserId?: number;
|
||||||
|
/** 用户姓名 */
|
||||||
|
name?: string;
|
||||||
|
/** 手机号码 */
|
||||||
|
mobile?: string;
|
||||||
|
/** 所属部门 */
|
||||||
|
department?: string;
|
||||||
|
/** 部门排序 */
|
||||||
|
userOrder?: string;
|
||||||
|
/** 职务信息 */
|
||||||
|
position?: string;
|
||||||
|
/** 性别 */
|
||||||
|
gender?: string;
|
||||||
|
/** 邮箱 */
|
||||||
|
email?: string;
|
||||||
|
/** 企业邮箱 */
|
||||||
|
bizMail?: string;
|
||||||
|
/** 部门负责人 */
|
||||||
|
isLeaderInDept?: string;
|
||||||
|
/** 直属上级 */
|
||||||
|
directLeader?: string;
|
||||||
|
/** 头像地址 */
|
||||||
|
avatar?: string;
|
||||||
|
/** 座机号码 */
|
||||||
|
telephone?: string;
|
||||||
|
/** 别名 */
|
||||||
|
alias?: string;
|
||||||
|
/** 激活状态 */
|
||||||
|
status?: string;
|
||||||
|
/** 个人二维码 */
|
||||||
|
qrCode?: string;
|
||||||
|
/** 操作人 */
|
||||||
|
operator?: string;
|
||||||
|
/** 有效状态 */
|
||||||
|
enableStatus?: string;
|
||||||
|
/** 创建时间 */
|
||||||
|
createTimeStr?: string;
|
||||||
|
/** 企业ID */
|
||||||
|
corpid?: string;
|
||||||
|
/** 应用ID */
|
||||||
|
appid?: string;
|
||||||
|
/** 用户余额 */
|
||||||
|
balance?: number;
|
||||||
|
/** 已使用用户余额 */
|
||||||
|
useBalance?: number;
|
||||||
|
/** 用户余额额度 */
|
||||||
|
balanceLimit?: number;
|
||||||
|
/** 系统角色ID */
|
||||||
|
sysRoleId?: number;
|
||||||
|
/** 角色ID */
|
||||||
|
roleId?: number;
|
||||||
|
/** 角色名称 */
|
||||||
|
roleName?: string;
|
||||||
|
}
|
|
@ -1,11 +1,19 @@
|
||||||
import { http } from "@/utils/http";
|
import { http } from "@/utils/http";
|
||||||
|
|
||||||
export interface GoodsQuery extends BasePageQuery {
|
export interface GoodsQuery extends BasePageQuery {
|
||||||
|
/** 商品名称 */
|
||||||
goodsName?: string;
|
goodsName?: string;
|
||||||
categoryId?: number;
|
categoryId?: number;
|
||||||
|
/** 商品状态(0下架 1上架) */
|
||||||
status?: number;
|
status?: number;
|
||||||
|
/** 商品ID */
|
||||||
goodsId?: number;
|
goodsId?: number;
|
||||||
|
/** 自动审批开关(0关闭 1开启) */
|
||||||
autoApproval?: number;
|
autoApproval?: number;
|
||||||
|
/** 所属类型(0智借还 1固资通) */
|
||||||
|
belongType?: number;
|
||||||
|
/** 企业微信ID */
|
||||||
|
corpid: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 商品DTO */
|
/** 商品DTO */
|
||||||
|
@ -16,6 +24,8 @@ export interface GoodsDTO {
|
||||||
goodsName: string;
|
goodsName: string;
|
||||||
/** 商品分类ID */
|
/** 商品分类ID */
|
||||||
categoryId: number;
|
categoryId: number;
|
||||||
|
/** 企业微信ID */
|
||||||
|
corpid: string;
|
||||||
/** 商品价格 */
|
/** 商品价格 */
|
||||||
price: number;
|
price: number;
|
||||||
/** 库存数量 */
|
/** 库存数量 */
|
||||||
|
@ -46,10 +56,14 @@ export interface GoodsDTO {
|
||||||
cellNo?: number;
|
cellNo?: number;
|
||||||
/** 单元格编号(字符串形式) */
|
/** 单元格编号(字符串形式) */
|
||||||
cellNoStr?: string;
|
cellNoStr?: string;
|
||||||
|
/** 所属店铺名称 */
|
||||||
|
shopNameStr?: string;
|
||||||
/** 总库存量(含所有仓库) */
|
/** 总库存量(含所有仓库) */
|
||||||
totalStock?: number;
|
totalStock?: number;
|
||||||
/** 商品使用说明 */
|
/** 商品使用说明 */
|
||||||
usageInstruction?: string;
|
usageInstruction?: string;
|
||||||
|
/** 所属类型(0智借还 1固资通) */
|
||||||
|
belongType: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 商品请求参数 */
|
/** 商品请求参数 */
|
||||||
|
@ -65,6 +79,8 @@ export interface GoodsRequest {
|
||||||
remark?: string;
|
remark?: string;
|
||||||
/** 商品使用说明 */
|
/** 商品使用说明 */
|
||||||
usageInstruction?: string;
|
usageInstruction?: string;
|
||||||
|
/** 企业微信ID */
|
||||||
|
corpid: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取商品列表 */
|
/** 获取商品列表 */
|
||||||
|
|
|
@ -15,6 +15,7 @@ export interface OrderQuery extends BasePageQuery {
|
||||||
cabinetId?: number;
|
cabinetId?: number;
|
||||||
/** 格口id */
|
/** 格口id */
|
||||||
cellId?: number;
|
cellId?: number;
|
||||||
|
goodsId?: number;
|
||||||
/**
|
/**
|
||||||
* 订单状态
|
* 订单状态
|
||||||
* @remarks
|
* @remarks
|
||||||
|
|
|
@ -3,24 +3,91 @@ import { http } from '@/utils/http';
|
||||||
/** 商店分页查询参数 */
|
/** 商店分页查询参数 */
|
||||||
export interface ShopQuery extends BasePageQuery {
|
export interface ShopQuery extends BasePageQuery {
|
||||||
shopName?: string;
|
shopName?: string;
|
||||||
|
corpid?: string;
|
||||||
|
/** 归属类型(0-借还柜 1-固资通) */
|
||||||
|
belongType?: number;
|
||||||
|
/** 运行模式(0-支付模式 1-审批模式 2-借还模式 3-会员模式 4-耗材模式) */
|
||||||
|
mode?: number;
|
||||||
|
/** 借呗支付(1-正常使用 0-禁止使用) */
|
||||||
|
balanceEnable?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 商店DTO */
|
/** 商店DTO */
|
||||||
export interface ShopDTO {
|
export interface ShopDTO {
|
||||||
shopId: number;
|
shopId: number;
|
||||||
shopName: string;
|
shopName: string;
|
||||||
|
corpid?: string;
|
||||||
|
/** 封面图URL */
|
||||||
|
coverImg?: string;
|
||||||
|
/** 归属类型(0-借还柜 1-固资通) */
|
||||||
|
belongType?: number;
|
||||||
|
/** 运行模式(0-支付模式 1-审批模式 2-借还模式 3-会员模式 4-耗材模式) */
|
||||||
|
mode?: number;
|
||||||
|
/** 借呗支付(1-正常使用 0-禁止使用) */
|
||||||
|
balanceEnable?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 新增商店命令 */
|
/** 新增商店命令 */
|
||||||
export interface AddShopCommand {
|
export interface AddShopCommand {
|
||||||
shopName: string;
|
shopName: string;
|
||||||
|
corpid: string;
|
||||||
|
/** 封面图URL */
|
||||||
|
coverImg?: string;
|
||||||
|
/** 归属类型(0-借还柜 1-固资通) */
|
||||||
|
belongType?: number;
|
||||||
|
/** 运行模式(0-支付模式 1-审批模式 2-借还模式 3-会员模式 4-耗材模式) */
|
||||||
|
mode?: number;
|
||||||
|
/** 借呗支付(1-正常使用 0-禁止使用) */
|
||||||
|
balanceEnable?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 更新商店命令 */
|
/** 更新商店命令 */
|
||||||
export interface UpdateShopCommand {
|
export interface UpdateShopCommand {
|
||||||
|
corpid: string;
|
||||||
shopId: number;
|
shopId: number;
|
||||||
shopName: string;
|
shopName: string;
|
||||||
}
|
/** 封面图URL */
|
||||||
|
coverImg?: string;
|
||||||
|
/** 归属类型(0-借还柜 1-固资通) */
|
||||||
|
belongType?: number;
|
||||||
|
/** 运行模式(0-支付模式 1-审批模式 2-借还模式 3-会员模式 4-耗材模式) */
|
||||||
|
mode?: number;
|
||||||
|
/** 借呗支付(1-正常使用 0-禁止使用) */
|
||||||
|
balanceEnable?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 运行模式文字映射
|
||||||
|
const modeTextMap = {
|
||||||
|
0: '支付模式',
|
||||||
|
1: '审批模式',
|
||||||
|
2: '借还模式',
|
||||||
|
3: '会员模式',
|
||||||
|
4: '耗材模式'
|
||||||
|
};
|
||||||
|
|
||||||
|
// 借呗支付状态文字映射
|
||||||
|
const balanceEnableTextMap = {
|
||||||
|
0: '禁止使用',
|
||||||
|
1: '正常使用'
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将运行模式数值转换为文字描述
|
||||||
|
* @param mode 运行模式数值
|
||||||
|
* @returns 对应的文字描述,未知值返回空字符串
|
||||||
|
*/
|
||||||
|
export const getModeText = (mode?: number): string => {
|
||||||
|
return mode !== undefined ? modeTextMap[mode] || '' : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将借呗支付状态转换为文字描述
|
||||||
|
* @param balanceEnable 借呗支付状态数值
|
||||||
|
* @returns 对应的文字描述,未知值返回空字符串
|
||||||
|
*/
|
||||||
|
export const getBalanceEnableText = (balanceEnable?: number): string => {
|
||||||
|
return balanceEnable !== undefined ? balanceEnableTextMap[balanceEnable] || '' : '';
|
||||||
|
};
|
||||||
|
|
||||||
/** 获取商店列表 */
|
/** 获取商店列表 */
|
||||||
export const getShopList = (params?: ShopQuery) => {
|
export const getShopList = (params?: ShopQuery) => {
|
||||||
|
@ -29,6 +96,11 @@ export const getShopList = (params?: ShopQuery) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** 获取商店详情 */
|
||||||
|
export const getShopById = (id: number) => {
|
||||||
|
return http.request<ResponseData<ShopDTO>>('get', `/shop/shops/${id}`);
|
||||||
|
};
|
||||||
|
|
||||||
/** 新增商店 */
|
/** 新增商店 */
|
||||||
export const addShop = (data: AddShopCommand) => {
|
export const addShop = (data: AddShopCommand) => {
|
||||||
return http.request<ResponseData<void>>('post', '/shop/shops', {
|
return http.request<ResponseData<void>>('post', '/shop/shops', {
|
||||||
|
|
|
@ -130,6 +130,7 @@ router.beforeEach(async (to: ToRouteType, _from, next) => {
|
||||||
});
|
});
|
||||||
// 登录成功后 将token存储到sessionStorage中
|
// 登录成功后 将token存储到sessionStorage中
|
||||||
setTokenFromBackend(data);
|
setTokenFromBackend(data);
|
||||||
|
wxStore.setQyUser(data.qyUser);
|
||||||
// 获取后端路由
|
// 获取后端路由
|
||||||
await initRouter();
|
await initRouter();
|
||||||
next({ path: getTopMenu(true).path });
|
next({ path: getTopMenu(true).path });
|
||||||
|
|
|
@ -39,6 +39,14 @@ export default {
|
||||||
meta: {
|
meta: {
|
||||||
title: "用户详情"
|
title: "用户详情"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/shop/goods/detail",
|
||||||
|
name: "GoodsDetail",
|
||||||
|
component: () => import("@/views/shop/goods/detail.vue"),
|
||||||
|
meta: {
|
||||||
|
title: "商品详情"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
} as RouteConfigsTable;
|
} as RouteConfigsTable;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import { store } from "@/store";
|
import { store } from "@/store";
|
||||||
|
import { QyUserLoginDTO } from "@/api/common/login";
|
||||||
|
|
||||||
|
|
||||||
export const useWxStore = defineStore("wx", () => {
|
export const useWxStore = defineStore("wx", () => {
|
||||||
|
@ -15,12 +16,18 @@ export const useWxStore = defineStore("wx", () => {
|
||||||
const userid = ref<string>("")
|
const userid = ref<string>("")
|
||||||
// 初始化
|
// 初始化
|
||||||
const isInit = ref<boolean>(false);
|
const isInit = ref<boolean>(false);
|
||||||
|
const qyUser = ref<QyUserLoginDTO>(null);
|
||||||
|
|
||||||
// 设置 userid
|
// 设置 userid
|
||||||
const setUserid = (id: string) => {
|
const setUserid = (id: string) => {
|
||||||
userid.value = id
|
userid.value = id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const setQyUser = (user: QyUserLoginDTO) => {
|
||||||
|
if (!user) return;
|
||||||
|
qyUser.value = user;
|
||||||
|
}
|
||||||
|
|
||||||
const initWx = () => {
|
const initWx = () => {
|
||||||
if (isInit.value) return;
|
if (isInit.value) return;
|
||||||
isInit.value = true;
|
isInit.value = true;
|
||||||
|
@ -49,7 +56,10 @@ export const useWxStore = defineStore("wx", () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { corpid, code, state, userid, isInit, setUserid, handleWxCallback, initWx }
|
return {
|
||||||
|
corpid, code, state, userid, isInit, qyUser,
|
||||||
|
setUserid, handleWxCallback, initWx, setQyUser
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -35,4 +35,8 @@ export const CabinetImgMap = {
|
||||||
img: "cabinet_4.jpg",
|
img: "cabinet_4.jpg",
|
||||||
name: "4格柜",
|
name: "4格柜",
|
||||||
},
|
},
|
||||||
|
10: {
|
||||||
|
img: "cabinet_16.jpg",
|
||||||
|
name: "10格柜",
|
||||||
|
},
|
||||||
}
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, watch } from "vue";
|
import { ref, reactive, watch } from "vue";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||||
import { updateCabinetCell } from "@/api/cabinet/cabinet-cell";
|
import { updateCabinetCell, clearGoodsCells } from "@/api/cabinet/cabinet-cell";
|
||||||
import Confirm from "@iconify-icons/ep/check";
|
import Confirm from "@iconify-icons/ep/check";
|
||||||
import type { FormRules } from 'element-plus';
|
import type { FormRules } from 'element-plus';
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ export interface FormDTO {
|
||||||
cellType: number;
|
cellType: number;
|
||||||
availableStatus: number;
|
availableStatus: number;
|
||||||
usageStatus: number;
|
usageStatus: number;
|
||||||
|
stock: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -38,7 +39,8 @@ const formData = reactive<FormDTO>({
|
||||||
pinNo: null,
|
pinNo: null,
|
||||||
cellType: 1,
|
cellType: 1,
|
||||||
availableStatus: 1,
|
availableStatus: 1,
|
||||||
usageStatus: 1
|
usageStatus: 1,
|
||||||
|
stock: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
const rules = reactive<FormRules>({
|
const rules = reactive<FormRules>({
|
||||||
|
@ -86,6 +88,22 @@ const closeDialog = () => {
|
||||||
emit('update:modelValue', false);
|
emit('update:modelValue', false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
async function handleClearGoods() {
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm(
|
||||||
|
`确认要下架${props.row.goodsName}吗?`,
|
||||||
|
'警告',
|
||||||
|
{ confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }
|
||||||
|
);
|
||||||
|
await clearGoodsCells(props.row.cellId);
|
||||||
|
ElMessage.success('商品下架成功');
|
||||||
|
emit('refresh');
|
||||||
|
closeDialog();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('操作取消或失败', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
watch(() => props.row, (val) => {
|
watch(() => props.row, (val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
Object.assign(formData, val);
|
Object.assign(formData, val);
|
||||||
|
@ -95,18 +113,10 @@ watch(() => props.row, (val) => {
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
|
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
|
||||||
<el-form-item label="柜体ID" prop="cabinetId">
|
|
||||||
<el-input v-model.number="formData.cabinetId" placeholder="请输入柜体ID" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="主板ID" prop="mainboardId">
|
<el-form-item label="主板ID" prop="mainboardId">
|
||||||
<el-input v-model.number="formData.mainboardId" placeholder="请输入主板ID" />
|
<el-input v-model.number="formData.mainboardId" placeholder="请输入主板ID" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="单元格号" prop="cellNo">
|
|
||||||
<el-input v-model.number="formData.cellNo" placeholder="请输入单元格号" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item label="针脚号" prop="pinNo">
|
<el-form-item label="针脚号" prop="pinNo">
|
||||||
<el-input v-model.number="formData.pinNo" placeholder="请输入针脚号" />
|
<el-input v-model.number="formData.pinNo" placeholder="请输入针脚号" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -120,23 +130,35 @@ watch(() => props.row, (val) => {
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="使用状态" prop="usageStatus">
|
<el-form-item v-if="props.row.goodsId" label="商品ID">
|
||||||
<el-select v-model="formData.usageStatus" placeholder="请选择状态">
|
<el-input :model-value="props.row.goodsId" disabled />
|
||||||
<el-option label="空闲" :value="1" />
|
</el-form-item>
|
||||||
<el-option label="已占用" :value="2" />
|
<el-form-item v-if="props.row.goodsId" label="商品名称">
|
||||||
</el-select>
|
<el-input :model-value="props.row.goodsName" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="props.row.goodsId" label="商品图片">
|
||||||
|
<el-image :src="props.row.coverImg" style="width: 100px; height: 100px" fit="contain" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="props.row.goodsId" label="价格">
|
||||||
|
<el-input :model-value="props.row.price" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="props.row.goodsId" label="库存" prop="stock">
|
||||||
|
<el-input-number v-model="formData.stock" :min="0" :max="1000" class="stock-input" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="可用状态" prop="availableStatus">
|
|
||||||
<el-select v-model="formData.availableStatus" placeholder="请选择状态">
|
|
||||||
<el-option label="正常" :value="1" />
|
|
||||||
<el-option label="故障" :value="2" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" :icon="useRenderIcon(Confirm)" @click="handleConfirm">
|
<el-button type="primary" @click="handleConfirm" class="save-btn">
|
||||||
提交
|
保存修改
|
||||||
|
</el-button>
|
||||||
|
<el-button v-if="props.row.goodsId" type="danger" @click="handleClearGoods" class="clear-btn">
|
||||||
|
下架商品
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.save-btn, .clear-btn {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,263 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, ref } from "vue";
|
||||||
|
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||||
|
import { getShopList, type ShopDTO, ShopQuery, getModeText, getBalanceEnableText } from "@/api/shop/shop";
|
||||||
|
import { type PaginationProps } from "@pureadmin/table";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { useWxStore } from "@/store/modules/wx";
|
||||||
|
|
||||||
|
import Search from "@iconify-icons/ep/search";
|
||||||
|
import Refresh from "@iconify-icons/ep/refresh";
|
||||||
|
import View from "@iconify-icons/ep/view";
|
||||||
|
import AddFill from "@iconify-icons/ri/add-circle-line";
|
||||||
|
import ShopFormModal from "./shop-form-modal.vue";
|
||||||
|
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||||
|
const { VITE_PUBLIC_IMG_PATH: IMG_PATH } = import.meta.env;
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "ShopCard"
|
||||||
|
});
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const wxStore = useWxStore();
|
||||||
|
const formRef = ref();
|
||||||
|
const modalVisible = ref(false);
|
||||||
|
const currentRow = ref<ShopDTO | null>(null);
|
||||||
|
const searchFormParams = ref<ShopQuery>({
|
||||||
|
shopName: "",
|
||||||
|
corpid: wxStore.corpid
|
||||||
|
});
|
||||||
|
|
||||||
|
const pageLoading = ref(false);
|
||||||
|
const dataList = ref<ShopDTO[]>([]);
|
||||||
|
const pagination = ref<PaginationProps>({
|
||||||
|
total: 0,
|
||||||
|
pageSize: 12,
|
||||||
|
currentPage: 1,
|
||||||
|
background: true
|
||||||
|
});
|
||||||
|
|
||||||
|
async function onSearch() {
|
||||||
|
pagination.value.currentPage = 1;
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getList() {
|
||||||
|
try {
|
||||||
|
pageLoading.value = true;
|
||||||
|
const { data } = await getShopList({
|
||||||
|
...searchFormParams.value,
|
||||||
|
corpid: wxStore.corpid,
|
||||||
|
pageSize: pagination.value.pageSize,
|
||||||
|
pageNum: pagination.value.currentPage
|
||||||
|
});
|
||||||
|
dataList.value = data.rows;
|
||||||
|
pagination.value.total = data.total;
|
||||||
|
} finally {
|
||||||
|
pageLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetForm = formEl => {
|
||||||
|
if (!formEl) return;
|
||||||
|
formEl.resetFields();
|
||||||
|
onSearch();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleViewDetail = (row: ShopDTO) => {
|
||||||
|
currentRow.value = row;
|
||||||
|
modalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function getModeType(mode: number): "" | "success" | "warning" | "info" | "danger" {
|
||||||
|
switch (mode) {
|
||||||
|
case 0: return 'success';
|
||||||
|
case 1: return 'info';
|
||||||
|
case 2: return 'warning';
|
||||||
|
case 3: return 'danger';
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBalanceType(enable: number): "" | "success" | "warning" | "info" | "danger" {
|
||||||
|
return enable == 1 ? 'success' : 'danger';
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="main">
|
||||||
|
<div class="float-right w-full">
|
||||||
|
<el-form ref="formRef" :inline="true" :model="searchFormParams"
|
||||||
|
class="search-form bg-bg_color flex w-[99/100] pl-[22px] pt-[12px]">
|
||||||
|
<el-form-item label="" prop="shopName">
|
||||||
|
<el-input @keydown.enter.prevent="onSearch" v-model="searchFormParams.shopName" placeholder="请输入地址名称"
|
||||||
|
clearable class="!w-[200px]" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" :icon="useRenderIcon(Search)" :loading="pageLoading" @click="onSearch">
|
||||||
|
搜索
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item class="space-item">
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" :icon="useRenderIcon(AddFill)" @click="modalVisible = true; currentRow = null"
|
||||||
|
style="margin-right: 10px;">
|
||||||
|
新增地址
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<div class="grid-container">
|
||||||
|
<el-row :gutter="12">
|
||||||
|
<el-col v-for="(item, index) in dataList" :key="item.shopId" :xs="24" :sm="12" :md="8" :lg="4" :xl="4">
|
||||||
|
<el-card class="cabinet-card" :body-style="{ padding: '8px 10px' }">
|
||||||
|
<div class="card-content">
|
||||||
|
<img v-if="item.coverImg" :src="item.coverImg" alt="" class="cabinet-image">
|
||||||
|
<svg v-if="!item.coverImg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 100" width="160" height="100"
|
||||||
|
class="cabinet-image">
|
||||||
|
<!-- 背景:浅灰色填充,模拟图片容器 -->
|
||||||
|
<rect width="100%" height="100%" fill="#f8f8f8" rx="4" ry="4" /> <!-- 可选圆角,适配卡片风格 -->
|
||||||
|
<!-- 图片图标:简化的“图片”符号(矩形+交叉线),直观关联“图片” -->
|
||||||
|
<g stroke="#ccc" stroke-width="2" fill="none">
|
||||||
|
<rect x="20" y="10" width="120" height="65" /> <!-- 图片框 -->
|
||||||
|
<line x1="20" y1="10" x2="140" y2="75" /> <!-- 对角线1 -->
|
||||||
|
<line x1="140" y1="10" x2="20" y2="75" /> <!-- 对角线2 -->
|
||||||
|
</g>
|
||||||
|
<!-- 说明文字:明确提示“未设置图片”,居中对齐 -->
|
||||||
|
<text x="50%" y="92" font-size="12" fill="#888" text-anchor="middle" font-family="Arial, sans-serif">
|
||||||
|
未设置图片
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<el-descriptions class="cabinet-info" :column="1">
|
||||||
|
<!-- <el-descriptions-item class="type">模式:{{ item.belongType === 0 ? '借还模式' : '固资模式' }}</el-descriptions-item> -->
|
||||||
|
<el-descriptions-item class="mode">运行模式:<el-tag :type="getModeType(item.mode)">{{ getModeText(item.mode) }}</el-tag></el-descriptions-item>
|
||||||
|
<el-descriptions-item class="balance">借呗支付:<el-tag :type="getBalanceType(item.balanceEnable)">{{ getBalanceEnableText(item.balanceEnable) }}</el-tag></el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
<el-divider class="divider" />
|
||||||
|
<el-button class="detail-btn" link @click="handleViewDetail(item)">
|
||||||
|
{{ item.shopName }}
|
||||||
|
</el-button>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<div class="pagination-wrapper">
|
||||||
|
<el-pagination background layout="prev, pager, next" :page-size="pagination.pageSize"
|
||||||
|
:total="pagination.total" v-model:current-page="pagination.currentPage" @current-change="getList"
|
||||||
|
@size-change="getList" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<shop-form-modal v-model:visible="modalVisible" :row="currentRow" @refresh="getList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.search-form {
|
||||||
|
:deep(.el-form-item) {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-descriptions__cell) {
|
||||||
|
padding-bottom: 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cabinet-card {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
min-height: 190px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.cabinet-image {
|
||||||
|
width: 50%;
|
||||||
|
height: 130px;
|
||||||
|
padding: 0 3px;
|
||||||
|
object-fit: contain;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-content {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.cabinet-info {
|
||||||
|
text-align: left;
|
||||||
|
padding: 16px 0px;
|
||||||
|
|
||||||
|
.name,
|
||||||
|
.type,
|
||||||
|
.shop,
|
||||||
|
.location,
|
||||||
|
.template {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
line-height: 1;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
width: 100%;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
margin: 5px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-btn {
|
||||||
|
width: 100%;
|
||||||
|
border: 0;
|
||||||
|
margin-top: auto;
|
||||||
|
padding: 8px 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-container {
|
||||||
|
margin: 12px 0;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.el-row {
|
||||||
|
margin-bottom: -20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-wrapper {
|
||||||
|
position: relative;
|
||||||
|
background: var(--el-bg-color);
|
||||||
|
padding: 8px 12px;
|
||||||
|
margin-top: 20px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
:deep(.el-pagination) {
|
||||||
|
margin: 0;
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.space-item {
|
||||||
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -13,11 +13,13 @@ import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
import ShopFormModal from "./shop-form-modal.vue";
|
import ShopFormModal from "./shop-form-modal.vue";
|
||||||
import ReQrcode from "@/components/ReQrcode";
|
import ReQrcode from "@/components/ReQrcode";
|
||||||
import { copyTextToClipboard } from "@pureadmin/utils";
|
import { copyTextToClipboard } from "@pureadmin/utils";
|
||||||
|
import { useWxStore } from "@/store/modules/wx";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "Shop"
|
name: "Shop"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const wxStore = useWxStore();
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
|
@ -28,6 +30,7 @@ const handleRefresh = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const searchFormParams = ref<ShopQuery>({
|
const searchFormParams = ref<ShopQuery>({
|
||||||
|
corpid: wxStore.corpid,
|
||||||
shopName: ""
|
shopName: ""
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -48,6 +51,7 @@ const getList = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const { data } = await getShopList({
|
const { data } = await getShopList({
|
||||||
...searchFormParams.value,
|
...searchFormParams.value,
|
||||||
|
corpid: wxStore.corpid,
|
||||||
pageSize: pagination.value.pageSize,
|
pageSize: pagination.value.pageSize,
|
||||||
pageNum: pagination.value.currentPage
|
pageNum: pagination.value.currentPage
|
||||||
});
|
});
|
||||||
|
@ -162,6 +166,11 @@ getList();
|
||||||
<el-table-column type="selection" width="55" />
|
<el-table-column type="selection" width="55" />
|
||||||
<el-table-column label="地址ID" prop="shopId" width="100" />
|
<el-table-column label="地址ID" prop="shopId" width="100" />
|
||||||
<el-table-column label="地址名称" prop="shopName" />
|
<el-table-column label="地址名称" prop="shopName" />
|
||||||
|
<el-table-column label="商品模式" prop="belongType" width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.belongType === 0 ? '借还模式' : '固资模式' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="150" fixed="right">
|
<el-table-column label="操作" width="150" fixed="right">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button type="primary" link :icon="useRenderIcon(EditPen)" @click="handleEdit(row)">
|
<el-button type="primary" link :icon="useRenderIcon(EditPen)" @click="handleEdit(row)">
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from "vue";
|
import { ref, watch, onMounted } from "vue";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { addShop, updateShop, ShopDTO, UpdateShopCommand } from "@/api/shop/shop";
|
import { addShop, updateShop, ShopDTO, UpdateShopCommand, AddShopCommand } from "@/api/shop/shop";
|
||||||
|
import { useWxStore } from "@/store/modules/wx";
|
||||||
|
import Upload from "@iconify-icons/ep/upload";
|
||||||
|
const { VITE_APP_BASE_API } = import.meta.env;
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
visible: {
|
visible: {
|
||||||
|
@ -16,14 +19,25 @@ const props = defineProps({
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "refresh"]);
|
const emit = defineEmits(["update:visible", "refresh"]);
|
||||||
|
|
||||||
|
const wxStore = useWxStore();
|
||||||
|
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const formData = ref<UpdateShopCommand>({
|
const formData = ref<UpdateShopCommand>({
|
||||||
|
corpid: wxStore.corpid,
|
||||||
shopId: 0,
|
shopId: 0,
|
||||||
shopName: ""
|
shopName: "",
|
||||||
|
belongType: undefined,
|
||||||
|
mode: undefined,
|
||||||
|
balanceEnable: undefined,
|
||||||
|
coverImg: ""
|
||||||
});
|
});
|
||||||
|
|
||||||
const rules = {
|
const rules = {
|
||||||
shopName: [{ required: true, message: "请输入地址名称", trigger: "blur" }]
|
shopName: [{ required: true, message: "请输入地址名称", trigger: "blur" }],
|
||||||
|
belongType: [{ required: true, message: "请选择商品模式", trigger: "change" }],
|
||||||
|
mode: [{ required: true, message: "请选择运行模式", trigger: "change" }],
|
||||||
|
balanceEnable: [{ required: true, message: "请选择借呗支付状态", trigger: "change" }],
|
||||||
|
coverImg: [{ required: true, message: "请上传封面图", trigger: "change" }]
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
@ -33,16 +47,27 @@ watch(
|
||||||
if (props.row?.shopId) {
|
if (props.row?.shopId) {
|
||||||
formData.value = {
|
formData.value = {
|
||||||
...props.row,
|
...props.row,
|
||||||
shopId: props.row.shopId
|
shopId: props.row.shopId,
|
||||||
|
corpid: props.row.corpid,
|
||||||
|
belongType: props.row.belongType,
|
||||||
|
mode: props.row.mode,
|
||||||
|
balanceEnable: props.row.balanceEnable,
|
||||||
|
coverImg: props.row.coverImg || ""
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
formData.value = {
|
formData.value = {
|
||||||
shopId: 0,
|
shopId: 0,
|
||||||
shopName: ""
|
shopName: "",
|
||||||
|
corpid: wxStore.corpid,
|
||||||
|
belongType: undefined,
|
||||||
|
mode: undefined,
|
||||||
|
balanceEnable: undefined,
|
||||||
|
coverImg: ""
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
|
@ -67,11 +92,27 @@ const handleSubmit = async () => {
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
emit("update:visible", false);
|
emit("update:visible", false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleAvatarSuccess = (response) => {
|
||||||
|
formData.value.coverImg = response.data.url;
|
||||||
|
};
|
||||||
|
|
||||||
|
const beforeAvatarUpload = (rawFile) => {
|
||||||
|
if (!['image/jpeg', 'image/png'].includes(rawFile.type)) {
|
||||||
|
ElMessage.error('封面图必须是 JPG/PNG 格式!');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (rawFile.size > 50 * 1024 * 1024) {
|
||||||
|
ElMessage.error('封面图大小不能超过 50MB!');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-dialog :title="formData.shopId ? '编辑地址' : '新增地址'" :model-value="visible" @update:model-value="handleClose"
|
<el-drawer :title="formData.shopId ? '编辑地址' : '新增地址'" :model-value="visible" @update:model-value="handleClose"
|
||||||
width="600px">
|
size="600px" direction="rtl">
|
||||||
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
|
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
|
||||||
<el-form-item label="地址ID" prop="shopId" v-if="formData.shopId">
|
<el-form-item label="地址ID" prop="shopId" v-if="formData.shopId">
|
||||||
<el-input v-model="formData.shopId" :disabled="true" />
|
<el-input v-model="formData.shopId" :disabled="true" />
|
||||||
|
@ -79,10 +120,83 @@ const handleClose = () => {
|
||||||
<el-form-item label="地址名称" prop="shopName">
|
<el-form-item label="地址名称" prop="shopName">
|
||||||
<el-input v-model="formData.shopName" placeholder="请输入地址名称" />
|
<el-input v-model="formData.shopName" placeholder="请输入地址名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="封面图" prop="coverImg">
|
||||||
|
<el-upload class="avatar-uploader" :action="VITE_APP_BASE_API + '/file/upload'" :show-file-list="false"
|
||||||
|
:on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
|
||||||
|
<img v-if="formData.coverImg" :src="formData.coverImg" class="avatar" />
|
||||||
|
<svg v-if="!formData.coverImg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 100" width="160" height="100"
|
||||||
|
class="cabinet-image">
|
||||||
|
<!-- 背景:浅灰色填充,模拟图片容器 -->
|
||||||
|
<rect width="100%" height="100%" fill="#f8f8f8" rx="4" ry="4" /> <!-- 可选圆角,适配卡片风格 -->
|
||||||
|
<!-- 图片图标:简化的“图片”符号(矩形+交叉线),直观关联“图片” -->
|
||||||
|
<g stroke="#ccc" stroke-width="2" fill="none">
|
||||||
|
<rect x="20" y="10" width="120" height="65" /> <!-- 图片框 -->
|
||||||
|
<line x1="20" y1="10" x2="140" y2="75" /> <!-- 对角线1 -->
|
||||||
|
<line x1="140" y1="10" x2="20" y2="75" /> <!-- 对角线2 -->
|
||||||
|
</g>
|
||||||
|
<!-- 说明文字:明确提示“未设置图片”,居中对齐 -->
|
||||||
|
<text x="50%" y="92" font-size="12" fill="#888" text-anchor="middle" font-family="Arial, sans-serif">
|
||||||
|
未设置图片
|
||||||
|
</text>
|
||||||
|
</svg>
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- <el-form-item label="商品模式" prop="belongType">
|
||||||
|
<el-select v-model="formData.belongType" placeholder="请选择归属类型">
|
||||||
|
<el-option label="借还模式" :value="0" />
|
||||||
|
<el-option label="固资模式" :value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item> -->
|
||||||
|
<el-form-item label="运行模式" prop="mode">
|
||||||
|
<el-select v-model="formData.mode" placeholder="请选择运行模式">
|
||||||
|
<el-option label="支付模式" :value="0" />
|
||||||
|
<el-option label="审批模式" :value="1" />
|
||||||
|
<el-option label="借还模式" :value="2" />
|
||||||
|
<el-option label="会员模式" :value="3" />
|
||||||
|
<el-option label="耗材模式" :value="4" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="借呗支付" prop="balanceEnable">
|
||||||
|
<el-select v-model="formData.balanceEnable" placeholder="请选择借呗支付状态">
|
||||||
|
<el-option label="正常使用" :value="1" />
|
||||||
|
<el-option label="禁止使用" :value="0" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="handleClose">取消</el-button>
|
<el-button @click="handleClose" style="margin-right: 5px;">取消</el-button>
|
||||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.avatar-uploader {
|
||||||
|
:deep(.el-upload) {
|
||||||
|
border: 1px dashed var(--el-border-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: var(--el-transition-duration-fast);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 178px;
|
||||||
|
height: 178px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cabinet-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0;
|
||||||
|
object-fit: contain;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,117 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
|
import { changeGoodsCellsStock, clearGoodsCells } from "@/api/cabinet/cabinet-cell";
|
||||||
|
import { getGoodsInfo } from "@/api/shop/goods";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
cellId: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
goodsId: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
goodsName: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
currentStock: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
coverImg: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['refresh', 'update:modelValue']);
|
||||||
|
const closeModal = () => {
|
||||||
|
emit('update:modelValue', false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const stockInput = ref(props.currentStock);
|
||||||
|
const isEditing = ref(false);
|
||||||
|
|
||||||
|
async function handleStockChange() {
|
||||||
|
try {
|
||||||
|
const { data } = await getGoodsInfo(props.goodsId);
|
||||||
|
const remainingStock = data.stock - data.totalStock + props.currentStock;
|
||||||
|
|
||||||
|
if (stockInput.value > remainingStock) {
|
||||||
|
ElMessage.warning('分配数量不能超过剩余库存');
|
||||||
|
stockInput.value = remainingStock;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await changeGoodsCellsStock(props.cellId, stockInput.value);
|
||||||
|
ElMessage.success('库存更新成功');
|
||||||
|
emit('refresh');
|
||||||
|
isEditing.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('库存调整失败', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleClearGoods() {
|
||||||
|
try {
|
||||||
|
await ElMessageBox.confirm(
|
||||||
|
`确认要下架${props.goodsName}吗?`,
|
||||||
|
'警告',
|
||||||
|
{ confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }
|
||||||
|
);
|
||||||
|
await clearGoodsCells(props.cellId);
|
||||||
|
ElMessage.success('商品下架成功');
|
||||||
|
emit('refresh');
|
||||||
|
closeModal();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('操作取消或失败', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="config-modal">
|
||||||
|
<el-descriptions :column="1" border>
|
||||||
|
<el-descriptions-item label="商品ID" >{{ props.goodsId }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="商品名称">{{ props.goodsName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="商品图片">
|
||||||
|
<el-image :src="coverImg" style="width: 100px; height: 100px" fit="contain" />
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="价格">{{ price }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="当前库存">
|
||||||
|
<el-input-number v-model="stockInput" :min="0" :max="1000" :disabled="!isEditing" class="stock-input" />
|
||||||
|
<el-button v-if="!isEditing" type="primary" size="small" @click="isEditing = true">修改</el-button>
|
||||||
|
<el-button v-if="isEditing" type="success" size="small" @click="handleStockChange">保存</el-button>
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
|
||||||
|
<div class="action-buttons">
|
||||||
|
<el-button type="danger" @click="handleClearGoods">
|
||||||
|
下架商品
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.config-modal {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stock-input {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,7 +1,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted } from "vue";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import { getSmartCabinetDetailApi, type SmartCabinetDTO } from "@/api/cabinet/smart-cabinet";
|
import { getSmartCabinetDetailApi, type SmartCabinetDTO, getBalanceEnableText } from "@/api/cabinet/smart-cabinet";
|
||||||
import { CabinetCellQuery, changeGoodsCellsStock, clearGoodsCells, getCabinetCellList, type CabinetCellDTO } from "@/api/cabinet/cabinet-cell";
|
import { CabinetCellQuery, changeGoodsCellsStock, clearGoodsCells, getCabinetCellList, type CabinetCellDTO } from "@/api/cabinet/cabinet-cell";
|
||||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||||
import { CabinetImgMap } from "@/utils/cabinetImgMap";
|
import { CabinetImgMap } from "@/utils/cabinetImgMap";
|
||||||
|
@ -9,6 +9,7 @@ import GatewayConfigModal from "@/views/cabinet/smart-cabinet/GatewayConfigModal
|
||||||
import ShopConfigModal from "@/views/cabinet/smart-cabinet/ShopConfigModal.vue";
|
import ShopConfigModal from "@/views/cabinet/smart-cabinet/ShopConfigModal.vue";
|
||||||
import MainCabinetConfigModal from "@/views/cabinet/smart-cabinet/MainCabinetConfigModal.vue";
|
import MainCabinetConfigModal from "@/views/cabinet/smart-cabinet/MainCabinetConfigModal.vue";
|
||||||
import CabinetGoodsConfigModal from "@/views/shop/cabinet-goods/cabinet-goods-config-modal.vue";
|
import CabinetGoodsConfigModal from "@/views/shop/cabinet-goods/cabinet-goods-config-modal.vue";
|
||||||
|
import ConfiguredGoodsModal from "./configured-goods-modal.vue";
|
||||||
import { ElMessage, ElMessageBox } from "element-plus";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
const { VITE_PUBLIC_IMG_PATH: IMG_PATH } = import.meta.env;
|
const { VITE_PUBLIC_IMG_PATH: IMG_PATH } = import.meta.env;
|
||||||
import EditPen from "@iconify-icons/ep/edit-pen";
|
import EditPen from "@iconify-icons/ep/edit-pen";
|
||||||
|
@ -21,6 +22,7 @@ import CellEditModal from "@/views/cabinet/cabinet-cell/cell-edit-modal.vue";
|
||||||
import { getGoodsInfo } from "@/api/shop/goods";
|
import { getGoodsInfo } from "@/api/shop/goods";
|
||||||
import EditCabinetDrawer from "./edit-cabinet-drawer.vue";
|
import EditCabinetDrawer from "./edit-cabinet-drawer.vue";
|
||||||
import { CabinetMainboardDTO, deleteMainboard, getMainboardList, updateMainboard } from "@/api/cabinet/mainboards";
|
import { CabinetMainboardDTO, deleteMainboard, getMainboardList, updateMainboard } from "@/api/cabinet/mainboards";
|
||||||
|
import { getShopById, ShopDTO, getModeText } from "@/api/shop/shop";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "SmartCabinetDetail"
|
name: "SmartCabinetDetail"
|
||||||
|
@ -36,6 +38,19 @@ const cabinetInfo = ref<SmartCabinetDTO>({
|
||||||
lockControlNo: 0,
|
lockControlNo: 0,
|
||||||
location: 0
|
location: 0
|
||||||
});
|
});
|
||||||
|
const shopInfo = ref<ShopDTO>({
|
||||||
|
shopId: 0,
|
||||||
|
shopName: "",
|
||||||
|
corpid: '',
|
||||||
|
/** 封面图URL */
|
||||||
|
coverImg: '',
|
||||||
|
/** 归属类型(0-借还柜 1-固资通) */
|
||||||
|
belongType:0,
|
||||||
|
/** 运行模式(0-支付模式 1-审批模式 2-借还模式 3-会员模式 4-耗材模式) */
|
||||||
|
mode: -1,
|
||||||
|
/** 借呗支付(1-正常使用 0-禁止使用) */
|
||||||
|
balanceEnable: 1,
|
||||||
|
});
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const activeTab = ref('cells');
|
const activeTab = ref('cells');
|
||||||
const mainboardList = ref<CabinetMainboardDTO[]>([]);
|
const mainboardList = ref<CabinetMainboardDTO[]>([]);
|
||||||
|
@ -54,18 +69,28 @@ const searchCellParams = ref<CabinetCellQuery>({
|
||||||
goodsName: null
|
goodsName: null
|
||||||
});
|
});
|
||||||
const cellPagination = ref({
|
const cellPagination = ref({
|
||||||
pageSize: 5,
|
pageSize: 18,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
total: 0
|
total: 0
|
||||||
});
|
});
|
||||||
const goodsConfigVisible = ref(false);
|
const goodsConfigVisible = ref(false);
|
||||||
|
const configuredGoodsVisible = ref(false);
|
||||||
const currentCellId = ref<number>();
|
const currentCellId = ref<number>();
|
||||||
const cellFormVisible = ref(false);
|
const cellFormVisible = ref(false);
|
||||||
const cellEditVisible = ref(false);
|
const cellEditVisible = ref(false);
|
||||||
|
|
||||||
function handleConfigure(row: CabinetCellDTO) {
|
function handleConfigure(row: CabinetCellDTO) {
|
||||||
currentCellId.value = row.cellId;
|
if (row.goodsId) {
|
||||||
goodsConfigVisible.value = true;
|
currentCell.value = row;
|
||||||
|
configuredGoodsVisible.value = true;
|
||||||
|
} else {
|
||||||
|
if (shopInfo.value && shopInfo.value.shopId) {
|
||||||
|
currentCellId.value = row.cellId;
|
||||||
|
goodsConfigVisible.value = true;
|
||||||
|
} else {
|
||||||
|
ElMessage.error('请先配置机柜所属地址!');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleStockConfig(row: CabinetCellDTO) {
|
async function handleStockConfig(row: CabinetCellDTO) {
|
||||||
|
@ -128,6 +153,11 @@ async function fetchCabinetDetail() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const { data } = await getSmartCabinetDetailApi(cabinetId.value);
|
const { data } = await getSmartCabinetDetailApi(cabinetId.value);
|
||||||
cabinetInfo.value = data;
|
cabinetInfo.value = data;
|
||||||
|
// 获取关联商店信息
|
||||||
|
if (cabinetInfo.value.shopId) {
|
||||||
|
const { data: shopData } = await getShopById(cabinetInfo.value.shopId);
|
||||||
|
shopInfo.value = shopData;
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
@ -257,32 +287,13 @@ onMounted(() => {
|
||||||
<el-divider />
|
<el-divider />
|
||||||
|
|
||||||
<el-descriptions class="cabinet-details" :column="1" border>
|
<el-descriptions class="cabinet-details" :column="1" border>
|
||||||
<el-descriptions-item label="柜体ID">{{ cabinetInfo.cabinetId }}</el-descriptions-item>
|
<el-descriptions-item label="名称">{{ cabinetInfo.cabinetName }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="柜体类型">
|
<el-descriptions-item label="模式">{{ getModeText(shopInfo.mode) }}</el-descriptions-item>
|
||||||
{{ cabinetInfo.cabinetType === 0 ? '主柜' : '副柜' }}
|
<el-descriptions-item label="格式">{{ CabinetImgMap[cabinetInfo.templateNo]?.name || '-'
|
||||||
</el-descriptions-item>
|
}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="模板">
|
<el-descriptions-item label="已用">{{ cabinetInfo.usedCells || '0' }}</el-descriptions-item>
|
||||||
{{ CabinetImgMap[cabinetInfo.templateNo]?.name || '-' }}
|
<el-descriptions-item label="未用">{{ cabinetInfo.availableCells || '0' }}</el-descriptions-item>
|
||||||
</el-descriptions-item>
|
<el-descriptions-item label="柜址">{{ cabinetInfo.shopName || '-' }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="归属商店">
|
|
||||||
{{ cabinetInfo.shopName || '-' }}
|
|
||||||
<el-button type="success" link :icon="useRenderIcon('ep:shop')" @click="shopConfigVisible = true">
|
|
||||||
配置
|
|
||||||
</el-button>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="MQTT网关">
|
|
||||||
{{ cabinetInfo.mqttServerId || '-' }}
|
|
||||||
<el-button type="warning" link :icon="useRenderIcon('ant-design:gateway-outlined')"
|
|
||||||
@click="gatewayConfigVisible = true">
|
|
||||||
配置
|
|
||||||
</el-button>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="归属主柜" v-if="cabinetInfo.cabinetType === 1">
|
|
||||||
{{ cabinetInfo.mainCabinetName || '-' }}
|
|
||||||
<el-button type="primary" link :icon="useRenderIcon('ep:setting')" @click="mainCabinetConfigVisible = true">
|
|
||||||
配置
|
|
||||||
</el-button>
|
|
||||||
</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
|
@ -302,13 +313,23 @@ onMounted(() => {
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-descriptions :column="2" border>
|
<el-descriptions :column="2" border>
|
||||||
<el-descriptions-item label="主柜ID">{{ cabinetInfo.mainCabinet || '-' }}</el-descriptions-item>
|
<el-descriptions-item label="柜体名称">{{ cabinetInfo.cabinetName || '-' }}</el-descriptions-item>
|
||||||
<el-descriptions-item label="主柜名称">{{ cabinetInfo.mainCabinetName || '-' }}</el-descriptions-item>
|
<el-descriptions-item label="运行模式">{{ getModeText(shopInfo.mode) }}</el-descriptions-item>
|
||||||
<!-- <el-descriptions-item label="归属类型">
|
<el-descriptions-item label="柜体格式">{{ CabinetImgMap[cabinetInfo.templateNo]?.name || '-'
|
||||||
{{ cabinetInfo.belongType === 0 ? '借还柜' : '固资通' }}
|
}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="柜体地址">{{ cabinetInfo.shopName || '-' }}
|
||||||
|
<el-button type="success" link @click="shopConfigVisible = true">
|
||||||
|
配置
|
||||||
|
</el-button></el-descriptions-item>
|
||||||
|
<el-descriptions-item label="柜体网关">{{ cabinetInfo.mqttServerId || '-' }}
|
||||||
|
<el-button type="warning" link @click="gatewayConfigVisible = true">
|
||||||
|
配置
|
||||||
|
</el-button></el-descriptions-item>
|
||||||
|
<el-descriptions-item label="借呗支付">{{ getBalanceEnableText(shopInfo.balanceEnable)
|
||||||
|
}}</el-descriptions-item>
|
||||||
|
<!-- <el-descriptions-item label="商品模式">
|
||||||
|
{{ cabinetInfo.belongType === 0 ? '借还模式' : '固资模式' }}
|
||||||
</el-descriptions-item> -->
|
</el-descriptions-item> -->
|
||||||
<el-descriptions-item label="MQTT服务器ID">{{ cabinetInfo.mqttServerId || '-' }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="操作员">{{ cabinetInfo.operator || '-' }}</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -324,74 +345,61 @@ onMounted(() => {
|
||||||
搜索
|
搜索
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
|
||||||
<el-button :icon="useRenderIcon(Refresh)" @click="resetCellSearch">
|
|
||||||
重置
|
|
||||||
</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
<!-- <el-button type="primary" :size="'small'" :icon="useRenderIcon(AddFill)" @click="cellFormVisible = true">
|
<!-- <el-button type="primary" :size="'small'" :icon="useRenderIcon(AddFill)" @click="cellFormVisible = true">
|
||||||
新增格口
|
新增格口
|
||||||
</el-button> -->
|
</el-button> -->
|
||||||
</div>
|
</div>
|
||||||
<el-table v-loading="loading" :data="cellList" border>
|
<el-row :gutter="12">
|
||||||
<el-table-column label="格口ID" prop="cellId" width="80" />
|
<el-col v-for="(item, index) in cellList" :key="item.cellId" :xs="24" :sm="12" :md="8" :lg="4" :xl="4">
|
||||||
<el-table-column label="格口号" prop="cellNo" width="80" />
|
<el-card class="cell-card" :body-style="{ padding: '8px 10px' }">
|
||||||
<el-table-column label="针脚号" prop="pinNo" width="80" />
|
<div class="card-content">
|
||||||
<el-table-column label="商品图片" width="120">
|
<el-image v-if="item.coverImg" :src="item.coverImg" class="cell-image" fit="contain" />
|
||||||
<template #default="{ row }">
|
<svg v-if="!item.coverImg" width="80" height="80" viewBox="0 0 100 100"
|
||||||
<el-image :src="row.coverImg" :preview-src-list="[row.coverImg]" :preview-teleported="true"
|
xmlns="http://www.w3.org/2000/svg" class="cell-image">
|
||||||
:hide-on-click-modal="true" fit="cover" class="rounded" width="60" height="60" />
|
<rect x="5" y="5" width="90" height="90" rx="10" fill="#E8F5E9" stroke="#81C784" stroke-width="2" />
|
||||||
</template>
|
<!-- 添加在矩形和文本之间的虚线 -->
|
||||||
</el-table-column>
|
<line x1="20" y1="70" x2="80" y2="70" stroke="#2E7D32" stroke-width="1" stroke-dasharray="4,2" />
|
||||||
<el-table-column label="商品名称">
|
<text x="50" y="45" font-family="Arial, sans-serif" font-size="24" font-weight="bold" fill="#2E7D32"
|
||||||
<template #default="{ row }">
|
text-anchor="middle">空闲</text>
|
||||||
{{ row.goodsId ? row.goodsName : '未配置商品' }}
|
<text x="50" y="85" font-family="Arial, sans-serif" font-size="12" fill="#2E7D32"
|
||||||
</template>
|
text-anchor="middle">{{ switchCellType(item.cellType) }}</text>
|
||||||
</el-table-column>
|
</svg>
|
||||||
<el-table-column label="价格" prop="price" width="80" />
|
<div class="cell-info">
|
||||||
<el-table-column label="库存" prop="stock" width="80" />
|
<!-- <div class="cell-no">格口号: {{ item.cellNo }}</div> -->
|
||||||
<el-table-column label="单元格类型" prop="cellType" width="120">
|
<div class="price">价格: {{ item.price }}</div>
|
||||||
<template #default="{ row }">
|
<div class="stock">库存: {{ item.stock }}</div>
|
||||||
{{ switchCellType(row.cellType) }}
|
<!-- <div class="cell-type">类型: {{ switchCellType(item.cellType) }}</div> -->
|
||||||
</template>
|
</div>
|
||||||
</el-table-column>
|
<!-- <div class="goods-name">{{ item.goodsId ? item.goodsName : '未配置商品' }}</div> -->
|
||||||
<el-table-column label="购买次数" prop="orderCount" width="100" />
|
</div>
|
||||||
<el-table-column label="相关信息" width="150" fixed="right">
|
<div class="line-num">
|
||||||
<template #default="{ row }">
|
<el-divider direction="horizontal" class="vertical-divider" />
|
||||||
<el-button type="success" link :icon="useRenderIcon('document')"
|
<span class="line-number">{{ item.cellNo }}</span>
|
||||||
@click="router.push({ path: '/shop/order/index', query: { cellId: row.cellId } })">
|
</div>
|
||||||
购买记录
|
<div class="action-buttons">
|
||||||
</el-button>
|
<el-button v-if="!item.goodsId" link type="success"
|
||||||
<el-button type="warning" link :icon="useRenderIcon('document')"
|
@click="handleConfigure(item)" class="cell-btn">
|
||||||
@click="router.push({ path: '/cabinet/operation/index', query: { cellId: row.cellId } })">
|
商品配置
|
||||||
开启记录
|
</el-button>
|
||||||
</el-button>
|
<el-button v-if="item.goodsId" link type="primary"
|
||||||
</template>
|
@click="handleEditCell(item)" class="cell-btn">
|
||||||
</el-table-column>
|
{{ item.goodsName }}
|
||||||
<el-table-column label="操作" width="150" fixed="right">
|
</el-button>
|
||||||
<template #default="{ row }">
|
<!-- <el-button v-if="item.goodsId" type="warning" link :icon="useRenderIcon(EditPen)"
|
||||||
<el-button v-if="cabinetInfo.belongType === 0" type="success" link :icon="useRenderIcon(AddFill)"
|
@click="handleStockConfig(item)">
|
||||||
@click="handleConfigure(row)">
|
库存
|
||||||
配置商品
|
</el-button>
|
||||||
</el-button>
|
<el-button v-if="item.goodsId" type="danger" link :icon="useRenderIcon(Delete)"
|
||||||
|
@click="handleClearGoods(item)">
|
||||||
<el-button type="primary" link :icon="useRenderIcon(EditPen)" @click="handleEditCell(row)">
|
下架
|
||||||
编辑格口
|
</el-button> -->
|
||||||
</el-button>
|
</div>
|
||||||
<el-button v-if="row.goodsId" type="warning" link :icon="useRenderIcon(EditPen)"
|
</el-card>
|
||||||
@click="handleStockConfig(row)">
|
</el-col>
|
||||||
配置库存
|
</el-row>
|
||||||
</el-button>
|
|
||||||
<el-button v-if="row.goodsId" type="danger" link :icon="useRenderIcon(Delete)"
|
|
||||||
@click="handleClearGoods(row)">
|
|
||||||
下架商品
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<el-pagination v-model:current-page="cellPagination.currentPage" v-model:page-size="cellPagination.pageSize"
|
<el-pagination v-model:current-page="cellPagination.currentPage" v-model:page-size="cellPagination.pageSize"
|
||||||
:page-sizes="[5, 8, 16, 24, 32]" layout="total, sizes, prev, pager, next, jumper"
|
:page-sizes="[12, 18, 24, 30, 36, 42]" layout="total, sizes, prev, pager, next, jumper"
|
||||||
:total="cellPagination.total" @size-change="handleCellSizeChange" @current-change="handleCellPageChange"
|
:total="cellPagination.total" @size-change="handleCellSizeChange" @current-change="handleCellPageChange"
|
||||||
class="pagination" />
|
class="pagination" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -421,21 +429,22 @@ onMounted(() => {
|
||||||
<ShopConfigModal v-model="shopConfigVisible" :cabinet-id="cabinetId" @refresh="fetchCabinetDetail" />
|
<ShopConfigModal v-model="shopConfigVisible" :cabinet-id="cabinetId" @refresh="fetchCabinetDetail" />
|
||||||
<MainCabinetConfigModal v-model="mainCabinetConfigVisible" :cabinet-id="cabinetId"
|
<MainCabinetConfigModal v-model="mainCabinetConfigVisible" :cabinet-id="cabinetId"
|
||||||
@refresh="fetchCabinetDetail" />
|
@refresh="fetchCabinetDetail" />
|
||||||
<el-drawer v-model="editCabinetDrawerVisible"
|
<el-drawer v-model="editCabinetDrawerVisible" title="编辑柜体" size="30%" direction="rtl">
|
||||||
title="编辑柜体" size="30%" direction="rtl">
|
|
||||||
<EditCabinetDrawer v-model="editCabinetDrawerVisible" :cabinet-info="cabinetInfo"
|
<EditCabinetDrawer v-model="editCabinetDrawerVisible" :cabinet-info="cabinetInfo"
|
||||||
@refresh="fetchCabinetDetail" />
|
@refresh="fetchCabinetDetail" />
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
<el-drawer v-model="goodsConfigVisible" title="配置商品"
|
<el-drawer v-model="goodsConfigVisible" title="配置商品" size="50%" direction="rtl">
|
||||||
size="50%" direction="rtl">
|
<CabinetGoodsConfigModal v-model="goodsConfigVisible" :cell-id="currentCellId" :belong-type="shopInfo.mode == 4 ? 1 : 0" @refresh="fetchCellList" />
|
||||||
<CabinetGoodsConfigModal v-model="goodsConfigVisible" :cell-id="currentCellId" @refresh="fetchCellList" />
|
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
<el-drawer v-model="cellFormVisible" title="新增格口"
|
<el-drawer v-model="configuredGoodsVisible" title="管理商品" size="30%" direction="rtl">
|
||||||
size="30%" direction="rtl">
|
<ConfiguredGoodsModal v-model="configuredGoodsVisible" :cell-id="currentCell?.cellId"
|
||||||
|
:goods-id="currentCell?.goodsId" :goods-name="currentCell?.goodsName" :current-stock="currentCell?.stock"
|
||||||
|
:cover-img="currentCell?.coverImg" :price="currentCell?.price" @refresh="fetchCellList" />
|
||||||
|
</el-drawer>
|
||||||
|
<el-drawer v-model="cellFormVisible" title="新增格口" size="30%" direction="rtl">
|
||||||
<CellFormModal v-model="cellFormVisible" :initial-cabinet-id="cabinetId" @refresh="fetchCellList" />
|
<CellFormModal v-model="cellFormVisible" :initial-cabinet-id="cabinetId" @refresh="fetchCellList" />
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
<el-drawer v-model="cellEditVisible" title="编辑格口"
|
<el-drawer v-model="cellEditVisible" title="编辑格口" size="30%" direction="rtl">
|
||||||
size="30%" direction="rtl">
|
|
||||||
<CellEditModal v-model="cellEditVisible" :row="currentCell" @refresh="fetchCellList" />
|
<CellEditModal v-model="cellEditVisible" :row="currentCell" @refresh="fetchCellList" />
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
</div>
|
</div>
|
||||||
|
@ -443,6 +452,82 @@ onMounted(() => {
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
.cell-card {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
/* &:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
} */
|
||||||
|
|
||||||
|
.card-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin: 0px;
|
||||||
|
|
||||||
|
.cell-image {
|
||||||
|
width: 50%;
|
||||||
|
height: 130px;
|
||||||
|
object-fit: contain;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell-info {
|
||||||
|
padding: 18px 8px 0 8px;
|
||||||
|
|
||||||
|
div {
|
||||||
|
font-size: 13px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
color: #606266;
|
||||||
|
|
||||||
|
&.goods-name {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--el-text-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.price {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-num {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.vertical-divider {
|
||||||
|
margin: 0 0 0 0;
|
||||||
|
width: 85%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-number {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: auto;
|
||||||
|
padding: 8px 0 0 0;
|
||||||
|
/* border-top: 1px solid var(--el-border-color-light); */
|
||||||
|
|
||||||
|
.cell-btn {
|
||||||
|
margin-right: 8px;
|
||||||
|
width: 80px;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
:deep(.el-tabs__header) {
|
:deep(.el-tabs__header) {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
@ -458,6 +543,7 @@ onMounted(() => {
|
||||||
.el-form-item {
|
.el-form-item {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail-container {
|
.detail-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -489,7 +575,7 @@ onMounted(() => {
|
||||||
|
|
||||||
.cabinet-image {
|
.cabinet-image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 420px;
|
height: 320px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
@ -504,6 +590,7 @@ onMounted(() => {
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination {
|
.pagination {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,9 @@ const formData = reactive({
|
||||||
templateNo: "",
|
templateNo: "",
|
||||||
lockControlNo: 0,
|
lockControlNo: 0,
|
||||||
location: 0,
|
location: 0,
|
||||||
belongType: 0
|
belongType: 0,
|
||||||
|
mode: 0,
|
||||||
|
balanceEnable: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
const rules = reactive<FormRules>({
|
const rules = reactive<FormRules>({
|
||||||
|
@ -43,6 +45,12 @@ const rules = reactive<FormRules>({
|
||||||
],
|
],
|
||||||
belongType: [
|
belongType: [
|
||||||
{ required: true, message: "请选择归属类型", trigger: "change" }
|
{ required: true, message: "请选择归属类型", trigger: "change" }
|
||||||
|
],
|
||||||
|
mode: [
|
||||||
|
{ required: true, message: "请选择运行模式", trigger: "change" }
|
||||||
|
],
|
||||||
|
balanceEnable: [
|
||||||
|
{ required: true, message: "请选择借呗支付状态", trigger: "change" }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -96,10 +104,26 @@ watch(() => props.cabinetInfo, (newVal) => {
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- <el-form-item label="归属类型" prop="belongType">
|
<!-- <el-form-item label="商品模式" prop="belongType">
|
||||||
<el-select v-model="formData.belongType" placeholder="请选择归属类型">
|
<el-select v-model="formData.belongType" placeholder="请选择商品模式">
|
||||||
<el-option label="借还柜" :value="0" />
|
<el-option label="借还模式" :value="0" />
|
||||||
<el-option label="固资通" :value="1" />
|
<el-option label="固资模式" :value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item> -->
|
||||||
|
|
||||||
|
<!-- <el-form-item label="运行模式" prop="mode">
|
||||||
|
<el-select v-model="formData.mode" placeholder="请选择运行模式">
|
||||||
|
<el-option label="支付模式" :value="0" />
|
||||||
|
<el-option label="审批模式" :value="1" />
|
||||||
|
<el-option label="借还模式" :value="2" />
|
||||||
|
<el-option label="会员模式" :value="3" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item> -->
|
||||||
|
|
||||||
|
<!-- <el-form-item label="借呗支付" prop="balanceEnable">
|
||||||
|
<el-select v-model="formData.balanceEnable" placeholder="请选择借呗支付状态">
|
||||||
|
<el-option label="正常使用" :value="1" />
|
||||||
|
<el-option label="禁止使用" :value="0" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item> -->
|
</el-form-item> -->
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ import View from "@iconify-icons/ep/view";
|
||||||
import AddFill from "@iconify-icons/ri/add-circle-line";
|
import AddFill from "@iconify-icons/ri/add-circle-line";
|
||||||
import SmartCabinetCardFormModal from "./smart-cabinet-card-form-modal.vue";
|
import SmartCabinetCardFormModal from "./smart-cabinet-card-form-modal.vue";
|
||||||
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||||
|
import { getModeText } from "@/api/shop/shop";
|
||||||
const { VITE_PUBLIC_IMG_PATH: IMG_PATH } = import.meta.env;
|
const { VITE_PUBLIC_IMG_PATH: IMG_PATH } = import.meta.env;
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
|
@ -129,9 +130,7 @@ onMounted(() => {
|
||||||
<img :src="`${IMG_PATH}img/cabinet/${CabinetImgMap[item.templateNo]?.img || 'default.jpg'}`"
|
<img :src="`${IMG_PATH}img/cabinet/${CabinetImgMap[item.templateNo]?.img || 'default.jpg'}`"
|
||||||
class="cabinet-image" />
|
class="cabinet-image" />
|
||||||
<el-descriptions class="cabinet-info" :column="1">
|
<el-descriptions class="cabinet-info" :column="1">
|
||||||
<el-descriptions-item class="name">名称:{{ item.cabinetName }}
|
<el-descriptions-item class="name">模式:{{ getModeText(item.mode) }}
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item class="name">模式:{{ '支付模式' }}
|
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<!-- <div class="type">柜体类型:{{ item.cabinetType === 0 ? '主柜' : '副柜' }}</div> -->
|
<!-- <div class="type">柜体类型:{{ item.cabinetType === 0 ? '主柜' : '副柜' }}</div> -->
|
||||||
<el-descriptions-item class="template">格式:{{ CabinetImgMap[item.templateNo]?.name || '-' }}
|
<el-descriptions-item class="template">格式:{{ CabinetImgMap[item.templateNo]?.name || '-' }}
|
||||||
|
@ -145,7 +144,9 @@ onMounted(() => {
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</div>
|
</div>
|
||||||
<el-divider class="divider" />
|
<el-divider class="divider" />
|
||||||
<el-button class="detail-btn" :icon="useRenderIcon(View)" @click="handleViewDetail(item)" />
|
<el-button class="detail-btn" link @click="handleViewDetail(item)">
|
||||||
|
{{ item.cabinetName }}
|
||||||
|
</el-button>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
@ -229,6 +230,10 @@ onMounted(() => {
|
||||||
border: 0;
|
border: 0;
|
||||||
margin-top: auto;
|
margin-top: auto;
|
||||||
padding: 8px 0;
|
padding: 8px 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ export interface FormDTO {
|
||||||
lockControlNo: number;
|
lockControlNo: number;
|
||||||
location: number;
|
location: number;
|
||||||
belongType: number;
|
belongType: number;
|
||||||
|
mode: number;
|
||||||
|
balanceEnable: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -28,15 +30,17 @@ const emit = defineEmits(["update:modelValue", "refresh"]);
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const formData = reactive<FormDTO>({
|
const formData = reactive<FormDTO>({
|
||||||
cabinetName: "",
|
cabinetName: "",
|
||||||
cabinetType: 1,
|
cabinetType: 0,
|
||||||
templateNo: "",
|
templateNo: "",
|
||||||
lockControlNo: 0,
|
lockControlNo: 0,
|
||||||
location: 0,
|
location: 0,
|
||||||
belongType: 0
|
belongType: 0,
|
||||||
|
mode: 0,
|
||||||
|
balanceEnable: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
const rules = reactive<FormRules>({
|
const rules = reactive<FormRules>({
|
||||||
cabinetName: [{ required: true, message: "柜体名称必填", trigger: "blur" }],
|
cabinetName: [{ required: true, max:4, message: "柜体名称必填", trigger: "blur" }],
|
||||||
cabinetType: [{ required: true, message: "请选择柜体类型", trigger: "change" }],
|
cabinetType: [{ required: true, message: "请选择柜体类型", trigger: "change" }],
|
||||||
templateNo: [{ required: true, message: "请选择模板编号", trigger: "change" }],
|
templateNo: [{ required: true, message: "请选择模板编号", trigger: "change" }],
|
||||||
lockControlNo: [
|
lockControlNo: [
|
||||||
|
@ -48,6 +52,12 @@ const rules = reactive<FormRules>({
|
||||||
],
|
],
|
||||||
belongType: [
|
belongType: [
|
||||||
{ required: true, message: "请选择归属类型", trigger: "change" }
|
{ required: true, message: "请选择归属类型", trigger: "change" }
|
||||||
|
],
|
||||||
|
mode: [
|
||||||
|
{ required: true, message: "请选择运行模式", trigger: "change" }
|
||||||
|
],
|
||||||
|
balanceEnable: [
|
||||||
|
{ required: true, message: "请选择借呗支付状态", trigger: "change" }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -80,12 +90,12 @@ const templateOptions = Object.entries(CabinetImgMap).map(([value, item]) => ({
|
||||||
<el-input v-model="formData.cabinetName" placeholder="请输入柜体名称" />
|
<el-input v-model="formData.cabinetName" placeholder="请输入柜体名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="柜体类型" prop="cabinetType">
|
<!-- <el-form-item label="柜体类型" prop="cabinetType">
|
||||||
<el-select v-model="formData.cabinetType" placeholder="请选择类型">
|
<el-select v-model="formData.cabinetType" placeholder="请选择类型">
|
||||||
<el-option label="主柜" :value="0" />
|
<el-option label="主柜" :value="0" />
|
||||||
<el-option label="副柜" :value="1" />
|
<el-option label="副柜" :value="1" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item> -->
|
||||||
|
|
||||||
<el-form-item label="模板编号" prop="templateNo">
|
<el-form-item label="模板编号" prop="templateNo">
|
||||||
<el-select v-model="formData.templateNo" placeholder="请选择模板编号">
|
<el-select v-model="formData.templateNo" placeholder="请选择模板编号">
|
||||||
|
@ -93,10 +103,26 @@ const templateOptions = Object.entries(CabinetImgMap).map(([value, item]) => ({
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- <el-form-item label="归属类型" prop="belongType">
|
<!-- <el-form-item label="商品模式" prop="belongType">
|
||||||
<el-select v-model="formData.belongType" placeholder="请选择归属类型">
|
<el-select v-model="formData.belongType" placeholder="请选择商品模式">
|
||||||
<el-option label="借还柜" :value="0" />
|
<el-option label="借还模式" :value="0" />
|
||||||
<el-option label="固资通" :value="1" />
|
<el-option label="固资模式" :value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item> -->
|
||||||
|
|
||||||
|
<!-- <el-form-item label="运行模式" prop="mode">
|
||||||
|
<el-select v-model="formData.mode" placeholder="请选择运行模式">
|
||||||
|
<el-option label="支付模式" :value="0" />
|
||||||
|
<el-option label="审批模式" :value="1" />
|
||||||
|
<el-option label="借还模式" :value="2" />
|
||||||
|
<el-option label="会员模式" :value="3" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item> -->
|
||||||
|
|
||||||
|
<!-- <el-form-item label="借呗支付" prop="balanceEnable">
|
||||||
|
<el-select v-model="formData.balanceEnable" placeholder="请选择借呗支付状态">
|
||||||
|
<el-option label="正常使用" :value="1" />
|
||||||
|
<el-option label="禁止使用" :value="0" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item> -->
|
</el-form-item> -->
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="visible" title="商店配置" width="800px">
|
<el-dialog v-model="visible" title="地址配置" width="800px">
|
||||||
<el-table :data="shopList" v-loading="loading" border>
|
<el-table :data="shopList" v-loading="loading" border>
|
||||||
<el-table-column prop="shopId" label="商店ID" width="100" />
|
<el-table-column prop="shopId" label="地址ID" width="100" />
|
||||||
<el-table-column prop="shopName" label="商店名称" />
|
<el-table-column prop="shopName" label="地址名称" />
|
||||||
<el-table-column label="操作" width="80" fixed="right">
|
<el-table-column label="操作" width="80" fixed="right">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button link type="primary" @click="handleConfig(row)">配置</el-button>
|
<el-button link type="primary" @click="handleConfig(row)">配置</el-button>
|
||||||
|
@ -25,6 +25,7 @@ import { updateSmartCabinet } from '@/api/cabinet/smart-cabinet';
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: boolean;
|
modelValue: boolean;
|
||||||
cabinetId: number;
|
cabinetId: number;
|
||||||
|
// belongType?: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'refresh']);
|
const emit = defineEmits(['update:modelValue', 'refresh']);
|
||||||
|
@ -47,7 +48,8 @@ const loadShops = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const { data } = await getShopList({
|
const { data } = await getShopList({
|
||||||
pageSize: pagination.value.pageSize,
|
pageSize: pagination.value.pageSize,
|
||||||
pageNum: pagination.value.currentPage
|
pageNum: pagination.value.currentPage,
|
||||||
|
// belongType: props.belongType
|
||||||
});
|
});
|
||||||
shopList.value = data.rows;
|
shopList.value = data.rows;
|
||||||
pagination.value.total = data.total;
|
pagination.value.total = data.total;
|
||||||
|
|
|
@ -103,6 +103,7 @@ const onLogin = async (formEl: FormInstance | undefined) => {
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
// 登录成功后 将token存储到sessionStorage中
|
// 登录成功后 将token存储到sessionStorage中
|
||||||
setTokenFromBackend(data);
|
setTokenFromBackend(data);
|
||||||
|
wxStore.setQyUser(data.qyUser);
|
||||||
// 获取后端路由
|
// 获取后端路由
|
||||||
initRouter().then(() => {
|
initRouter().then(() => {
|
||||||
router.push(getTopMenu(true).path);
|
router.push(getTopMenu(true).path);
|
||||||
|
@ -132,6 +133,7 @@ const onLogin = async (formEl: FormInstance | undefined) => {
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
// 登录成功后 将token存储到sessionStorage中
|
// 登录成功后 将token存储到sessionStorage中
|
||||||
setTokenFromBackend(data);
|
setTokenFromBackend(data);
|
||||||
|
wxStore.setQyUser(data.qyUser);
|
||||||
// 获取后端路由
|
// 获取后端路由
|
||||||
initRouter().then(() => {
|
initRouter().then(() => {
|
||||||
router.push(getTopMenu(true).path);
|
router.push(getTopMenu(true).path);
|
||||||
|
|
|
@ -6,11 +6,16 @@ import { configureGoodsCellsStock } from "@/api/cabinet/cabinet-cell";
|
||||||
import Search from "@iconify-icons/ep/search";
|
import Search from "@iconify-icons/ep/search";
|
||||||
import Refresh from "@iconify-icons/ep/refresh";
|
import Refresh from "@iconify-icons/ep/refresh";
|
||||||
import { ElMessage, ElMessageBox } from "element-plus";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
|
import { useWxStore } from "@/store/modules/wx";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
cellId: {
|
cellId: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
belongType: {
|
||||||
|
type: Number,
|
||||||
|
required: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -19,9 +24,13 @@ const closeModal = () => {
|
||||||
emit('update:modelValue', false);
|
emit('update:modelValue', false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const wxStore = useWxStore();
|
||||||
|
|
||||||
const searchFormParams = ref({
|
const searchFormParams = ref({
|
||||||
|
corpid: wxStore.corpid,
|
||||||
goodsName: "",
|
goodsName: "",
|
||||||
status: null
|
status: null,
|
||||||
|
belongType: props.belongType
|
||||||
});
|
});
|
||||||
|
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
|
@ -36,6 +45,8 @@ const dataList = ref<GoodsDTO[]>([]);
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
try {
|
try {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
searchFormParams.value.corpid = wxStore.corpid;
|
||||||
|
searchFormParams.value.belongType = props.belongType;
|
||||||
const { data } = await getGoodsListApi({
|
const { data } = await getGoodsListApi({
|
||||||
...searchFormParams.value,
|
...searchFormParams.value,
|
||||||
pageSize: pagination.value.pageSize,
|
pageSize: pagination.value.pageSize,
|
||||||
|
@ -93,15 +104,23 @@ defineExpose({ getList });
|
||||||
<template>
|
<template>
|
||||||
<div class="config-modal">
|
<div class="config-modal">
|
||||||
<el-form :inline="true" :model="searchFormParams" class="search-form">
|
<el-form :inline="true" :model="searchFormParams" class="search-form">
|
||||||
<el-form-item label="商品名称:">
|
<el-form-item>
|
||||||
<el-input v-model="searchFormParams.goodsName" placeholder="请输入商品名称" clearable />
|
<el-input @keydown.enter.prevent="getList" v-model="searchFormParams.goodsName" placeholder="请输入商品名称"
|
||||||
|
clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="状态:">
|
<!-- <el-form-item label="状态:">
|
||||||
<el-select v-model="searchFormParams.status" placeholder="请选择状态" clearable>
|
<el-select v-model="searchFormParams.status" placeholder="请选择状态" clearable>
|
||||||
<el-option label="已上架" :value="1" />
|
<el-option label="已上架" :value="1" />
|
||||||
<el-option label="已下架" :value="2" />
|
<el-option label="已下架" :value="2" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item> -->
|
||||||
|
<!-- <el-form-item prop="belongType">
|
||||||
|
<el-select v-model="searchFormParams.belongType" placeholder="请选择商品所属" clearable @change="getList"
|
||||||
|
class="!w-[180px]">
|
||||||
|
<el-option label="智柜通" :value="0" />
|
||||||
|
<el-option label="固资通" :value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item> -->
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" :icon="useRenderIcon(Search)" @click="getList">
|
<el-button type="primary" :icon="useRenderIcon(Search)" @click="getList">
|
||||||
搜索
|
搜索
|
||||||
|
|
|
@ -0,0 +1,269 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, watch } from "vue";
|
||||||
|
import { useRoute, useRouter } from "vue-router";
|
||||||
|
import { getGoodsInfo, GoodsDTO } from "@/api/shop/goods";
|
||||||
|
import { getOrderListApi, type OrderDTO, OrderQuery } from "@/api/shop/order";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
|
import { useRenderIcon } from '@/components/ReIcon/src/hooks';
|
||||||
|
import EditPen from '@iconify-icons/ep/edit-pen';
|
||||||
|
import GoodsEditModal from "./goods-edit-modal.vue";
|
||||||
|
|
||||||
|
const handleEdit = (row: GoodsDTO) => {
|
||||||
|
goodsInfo.value = row;
|
||||||
|
editModalVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { VITE_PUBLIC_IMG_PATH: IMG_PATH } = import.meta.env;
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: "GoodsDetail"
|
||||||
|
});
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
const route = useRoute();
|
||||||
|
const goodsInfo = ref<GoodsDTO>({
|
||||||
|
goodsId: 0,
|
||||||
|
goodsName: "",
|
||||||
|
categoryId: 0,
|
||||||
|
price: 0,
|
||||||
|
stock: 0,
|
||||||
|
status: 0,
|
||||||
|
autoApproval: 0,
|
||||||
|
coverImg: "",
|
||||||
|
goodsDetail: "",
|
||||||
|
belongType: 0,
|
||||||
|
corpid: ""
|
||||||
|
});
|
||||||
|
const loading = ref(false);
|
||||||
|
const activeTab = ref('basic');
|
||||||
|
const goodsId = ref<number>(0);
|
||||||
|
const editModalVisible = ref(false);
|
||||||
|
|
||||||
|
async function fetchGoodsDetail() {
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
const { data } = await getGoodsInfo(goodsId.value);
|
||||||
|
goodsInfo.value = data;
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
goodsId.value = Number(route.query.id);
|
||||||
|
fetchGoodsDetail();
|
||||||
|
});
|
||||||
|
|
||||||
|
const orderList = ref<OrderDTO[]>([]);
|
||||||
|
const orderLoading = ref(false);
|
||||||
|
const orderPagination = ref({
|
||||||
|
pageSize: 8,
|
||||||
|
currentPage: 1,
|
||||||
|
total: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
const fetchOrderList = async () => {
|
||||||
|
try {
|
||||||
|
orderLoading.value = true;
|
||||||
|
const { data } = await getOrderListApi({
|
||||||
|
goodsId: goodsId.value,
|
||||||
|
pageSize: orderPagination.value.pageSize,
|
||||||
|
pageNum: orderPagination.value.currentPage
|
||||||
|
});
|
||||||
|
orderList.value = data.rows;
|
||||||
|
orderPagination.value.total = data.total;
|
||||||
|
} finally {
|
||||||
|
orderLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOrderSizeChange = (val: number) => {
|
||||||
|
orderPagination.value.pageSize = val;
|
||||||
|
fetchOrderList();
|
||||||
|
};
|
||||||
|
|
||||||
|
const onOrderCurrentChange = (val: number) => {
|
||||||
|
orderPagination.value.currentPage = val;
|
||||||
|
fetchOrderList();
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(goodsId, () => {
|
||||||
|
fetchOrderList();
|
||||||
|
}, { immediate: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="detail-container">
|
||||||
|
<goods-edit-modal v-model:visible="editModalVisible" :row="goodsInfo" @refresh="fetchGoodsDetail" />
|
||||||
|
<div class="flex-container">
|
||||||
|
<el-card class="goods-info-card">
|
||||||
|
<div class="goods-header">
|
||||||
|
<img :src="goodsInfo.coverImg" class="goods-image" />
|
||||||
|
<div class="goods-name">{{ goodsInfo.goodsName }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-divider />
|
||||||
|
|
||||||
|
<el-descriptions class="goods-details" :column="1" border>
|
||||||
|
<el-descriptions-item label="名称">{{ goodsInfo.goodsName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="价格">{{ goodsInfo.price }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="库存">{{ goodsInfo.stock }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="状态">{{ goodsInfo.status === 1 ? '已上架' : '已下架' }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card class="info-card">
|
||||||
|
<div class="tab-header">
|
||||||
|
<el-tabs type="card" v-model="activeTab" class="tab-header-card">
|
||||||
|
<el-tab-pane label="基本信息" name="basic"></el-tab-pane>
|
||||||
|
<el-tab-pane label="购买记录" name="order"></el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
<el-button v-if="goodsInfo.belongType == 0" type="primary" @click="handleEdit(goodsInfo)"
|
||||||
|
style="margin-bottom: 12px" :size="'default'">
|
||||||
|
编辑商品
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-details" v-if="activeTab === 'basic'">
|
||||||
|
<el-descriptions :column="2" border>
|
||||||
|
<el-descriptions-item label="名称">{{ goodsInfo.goodsName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="价格">{{ goodsInfo.price }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="库存">{{ goodsInfo.stock }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="已分配库存">{{ goodsInfo.totalStock }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="状态">{{ goodsInfo.status === 1 ? '已上架' : '已下架' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="自动审批">{{ goodsInfo.autoApproval === 1 ? '开启' : '关闭' }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="商品描述" :span="2">
|
||||||
|
<div v-html="goodsInfo.goodsDetail"></div>
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="关联状态" :span="2">
|
||||||
|
{{ goodsInfo.cellNoStr ? '已上柜' : '未上柜' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="关联柜址">{{ goodsInfo.shopNameStr }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="柜体名称">{{ goodsInfo.cabinetName }}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="柜体格号">{{ goodsInfo.cellNoStr }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="order-details" v-if="activeTab === 'order'">
|
||||||
|
<el-table v-loading="orderLoading" :data="orderList" row-key="orderId" border>
|
||||||
|
<el-table-column label="订单ID" prop="orderId" width="120" />
|
||||||
|
<el-table-column label="商品名称" prop="goodsNames">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span v-if="row.goodsNames">
|
||||||
|
{{ row.goodsNames.split(',').join(', ') }}
|
||||||
|
</span>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="姓名" prop="name" width="120" />
|
||||||
|
<el-table-column label="手机号" prop="mobile" width="120" />
|
||||||
|
<el-table-column label="订单金额" prop="totalAmount" width="120">
|
||||||
|
<template #default="{ row }">{{ row.totalAmount }}元</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="订单状态" prop="status" width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="row.status === 2 ? 'success' : row.status === 5 ? 'danger' : 'info'">
|
||||||
|
{{ { 1: '待付款', 2: '已付款', 3: '已发货', 4: '已完成', 5: '已取消' }[row.status] }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="支付状态" prop="payStatus" width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="row.payStatus === 2 ? 'success' : 'info'">
|
||||||
|
{{ { 1: '未支付', 2: '已支付', 3: '退款中', 4: '已退款' }[row.payStatus] }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="支付方式" prop="paymentMethod" width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ { wechat: '微信支付', balance: '余额支付' }[row.paymentMethod] || row.paymentMethod }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="支付时间" prop="payTime" width="180">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ row.payTime ? new Date(row.payTime).toLocaleString() : '-' }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-pagination v-model:current-page="orderPagination.currentPage" v-model:page-size="orderPagination.pageSize"
|
||||||
|
:page-sizes="[8, 10, 20, 50]" layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="orderPagination.total" @size-change="onOrderSizeChange" @current-change="onOrderCurrentChange"
|
||||||
|
class="pagination" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sales-details" v-if="activeTab === 'sales'">
|
||||||
|
<!-- 销售记录表格 -->
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.detail-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.flex-container {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
gap: 12px;
|
||||||
|
min-height: 0;
|
||||||
|
|
||||||
|
.goods-info-card {
|
||||||
|
width: 20%;
|
||||||
|
height: 88vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-card {
|
||||||
|
width: 80%;
|
||||||
|
height: 88vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.goods-image {
|
||||||
|
width: 100%;
|
||||||
|
height: 320px;
|
||||||
|
object-fit: contain;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-name {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
|
||||||
|
.tab-header-card {
|
||||||
|
flex: 1;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-details {
|
||||||
|
margin-top: 8px;
|
||||||
|
background-color: var(--el-bg-color);
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 16px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -84,6 +84,7 @@ const initForm = async () => {
|
||||||
categoryOptions.value = data;
|
categoryOptions.value = data;
|
||||||
|
|
||||||
// 初始化表单数据
|
// 初始化表单数据
|
||||||
|
console.log("初始化表单数据", props.row);
|
||||||
if (props.row?.goodsId) {
|
if (props.row?.goodsId) {
|
||||||
isEdit.value = true;
|
isEdit.value = true;
|
||||||
Object.assign(formData, props.row);
|
Object.assign(formData, props.row);
|
||||||
|
@ -160,12 +161,12 @@ const handleDelete = async () => {
|
||||||
<el-input-number v-model="formData.stock" :min="0" controls-position="right" />
|
<el-input-number v-model="formData.stock" :min="0" controls-position="right" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="商品分类" prop="categoryId">
|
<!-- <el-form-item label="商品分类" prop="categoryId">
|
||||||
<el-select v-model="formData.categoryId" placeholder="请选择商品分类" clearable class="w-full">
|
<el-select v-model="formData.categoryId" placeholder="请选择商品分类" clearable class="w-full">
|
||||||
<el-option v-for="category in categoryOptions" :key="category.categoryId" :label="category.categoryName"
|
<el-option v-for="category in categoryOptions" :key="category.categoryId" :label="category.categoryName"
|
||||||
:value="category.categoryId" />
|
:value="category.categoryId" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item> -->
|
||||||
|
|
||||||
<el-form-item label="自动审批" prop="autoApproval">
|
<el-form-item label="自动审批" prop="autoApproval">
|
||||||
<el-switch v-model="formData.autoApproval" :active-value="1" :inactive-value="0" active-text="启用"
|
<el-switch v-model="formData.autoApproval" :active-value="1" :inactive-value="0" active-text="启用"
|
||||||
|
@ -192,7 +193,6 @@ const handleDelete = async () => {
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="closeDialog">取消</el-button>
|
|
||||||
<el-button type="primary" :icon="useRenderIcon(Confirm)" @click="handleConfirm">
|
<el-button type="primary" :icon="useRenderIcon(Confirm)" @click="handleConfirm">
|
||||||
确认
|
确认
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { addGoodsApi, GoodsDTO } from "@/api/shop/goods";
|
||||||
import { CategoryDTO, getCategoryAllApi } from "@/api/shop/category";
|
import { CategoryDTO, getCategoryAllApi } from "@/api/shop/category";
|
||||||
import Confirm from "@iconify-icons/ep/check";
|
import Confirm from "@iconify-icons/ep/check";
|
||||||
import Upload from "@iconify-icons/ep/upload";
|
import Upload from "@iconify-icons/ep/upload";
|
||||||
|
import { useWxStore } from "@/store/modules/wx";
|
||||||
const { VITE_APP_BASE_API } = import.meta.env;
|
const { VITE_APP_BASE_API } = import.meta.env;
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -17,6 +18,7 @@ const props = defineProps({
|
||||||
|
|
||||||
const emit = defineEmits(["update:visible", "refresh"]);
|
const emit = defineEmits(["update:visible", "refresh"]);
|
||||||
|
|
||||||
|
const wxStore = useWxStore();
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const formData = reactive<GoodsDTO>({
|
const formData = reactive<GoodsDTO>({
|
||||||
goodsName: "",
|
goodsName: "",
|
||||||
|
@ -27,7 +29,9 @@ const formData = reactive<GoodsDTO>({
|
||||||
categoryId: 0,
|
categoryId: 0,
|
||||||
goodsDetail: "",
|
goodsDetail: "",
|
||||||
coverImg: "",
|
coverImg: "",
|
||||||
usageInstruction: ""
|
usageInstruction: "",
|
||||||
|
belongType: 0,
|
||||||
|
corpid: wxStore.corpid
|
||||||
});
|
});
|
||||||
|
|
||||||
const rules = reactive<FormRules>({
|
const rules = reactive<FormRules>({
|
||||||
|
@ -48,6 +52,7 @@ const rules = reactive<FormRules>({
|
||||||
const handleConfirm = async () => {
|
const handleConfirm = async () => {
|
||||||
try {
|
try {
|
||||||
await formRef.value.validate();
|
await formRef.value.validate();
|
||||||
|
formData.corpid = wxStore.corpid;
|
||||||
await addGoodsApi(formData);
|
await addGoodsApi(formData);
|
||||||
ElMessage.success("商品添加成功");
|
ElMessage.success("商品添加成功");
|
||||||
emit("refresh");
|
emit("refresh");
|
||||||
|
@ -96,7 +101,7 @@ const beforeAvatarUpload = (rawFile) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-dialog title="新增商品" :model-value="visible" width="600px" @close="closeDialog" @open="loadCategories">
|
<el-drawer :title="'新增商品'" :model-value="visible" size="50%" direction="rtl" @close="closeDialog">
|
||||||
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80px" label-position="right">
|
<el-form ref="formRef" :model="formData" :rules="rules" label-width="80px" label-position="right">
|
||||||
<el-form-item label="商品名称" prop="goodsName">
|
<el-form-item label="商品名称" prop="goodsName">
|
||||||
<el-input v-model="formData.goodsName" placeholder="请输入商品名称" clearable />
|
<el-input v-model="formData.goodsName" placeholder="请输入商品名称" clearable />
|
||||||
|
@ -118,12 +123,12 @@ const beforeAvatarUpload = (rawFile) => {
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- 在状态表单项前添加分类选择 -->
|
<!-- 在状态表单项前添加分类选择 -->
|
||||||
<el-form-item label="商品分类" prop="categoryId">
|
<!-- <el-form-item label="商品分类" prop="categoryId">
|
||||||
<el-select v-model="formData.categoryId" placeholder="请选择商品分类" clearable class="w-full">
|
<el-select v-model="formData.categoryId" placeholder="请选择商品分类" clearable class="w-full">
|
||||||
<el-option v-for="category in categoryOptions" :key="category.categoryId" :label="category.categoryName"
|
<el-option v-for="category in categoryOptions" :key="category.categoryId" :label="category.categoryName"
|
||||||
:value="category.categoryId" />
|
:value="category.categoryId" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item> -->
|
||||||
|
|
||||||
<el-form-item label="自动审批" prop="autoApproval">
|
<el-form-item label="自动审批" prop="autoApproval">
|
||||||
<el-switch v-model="formData.autoApproval" :active-value="1" :inactive-value="0" active-text="启用"
|
<el-switch v-model="formData.autoApproval" :active-value="1" :inactive-value="0" active-text="启用"
|
||||||
|
@ -142,15 +147,23 @@ const beforeAvatarUpload = (rawFile) => {
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="closeDialog">取消</el-button>
|
<div class="drawer-footer">
|
||||||
<el-button type="primary" :icon="useRenderIcon(Confirm)" @click="handleConfirm">
|
<el-button type="primary" :icon="useRenderIcon(Confirm)" @click="handleConfirm">
|
||||||
确认
|
确认
|
||||||
</el-button>
|
</el-button>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-drawer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.drawer-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.avatar-uploader {
|
.avatar-uploader {
|
||||||
:deep(.el-upload) {
|
:deep(.el-upload) {
|
||||||
border: 1px dashed var(--el-border-color);
|
border: 1px dashed var(--el-border-color);
|
||||||
|
|
|
@ -9,28 +9,36 @@ import AddFill from "@iconify-icons/ri/add-circle-line";
|
||||||
import Search from "@iconify-icons/ep/search";
|
import Search from "@iconify-icons/ep/search";
|
||||||
import Refresh from "@iconify-icons/ep/refresh";
|
import Refresh from "@iconify-icons/ep/refresh";
|
||||||
import Setting from "@iconify-icons/ep/setting";
|
import Setting from "@iconify-icons/ep/setting";
|
||||||
|
import View from "@iconify-icons/ep/view";
|
||||||
import GoodsFormModal from "./goods-form-modal.vue";
|
import GoodsFormModal from "./goods-form-modal.vue";
|
||||||
import GoodsEditModal from "./goods-edit-modal.vue";
|
import GoodsEditModal from "./goods-edit-modal.vue";
|
||||||
import { ElMessage, ElMessageBox } from "element-plus";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
import { deleteGoodsApi } from "@/api/shop/goods";
|
import { deleteGoodsApi } from "@/api/shop/goods";
|
||||||
|
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import { useWxStore } from "@/store/modules/wx";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "ShopGoods"
|
name: "ShopGoods"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const wxStore = useWxStore();
|
||||||
|
const router = useRouter();
|
||||||
const formRef = ref();
|
const formRef = ref();
|
||||||
const tableRef = ref();
|
const tableRef = ref();
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false);
|
||||||
|
|
||||||
// 搜索表单
|
// 搜索表单
|
||||||
const searchFormParams = ref({
|
const searchFormParams = ref({
|
||||||
|
corpid: wxStore.corpid,
|
||||||
|
belongType: null,
|
||||||
goodsName: "",
|
goodsName: "",
|
||||||
status: null
|
status: null
|
||||||
});
|
});
|
||||||
|
|
||||||
// 分页参数
|
// 分页参数
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
pageSize: 6,
|
pageSize: 12,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
total: 0
|
total: 0
|
||||||
});
|
});
|
||||||
|
@ -47,6 +55,7 @@ const getList = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const { data } = await getGoodsListApi({
|
const { data } = await getGoodsListApi({
|
||||||
...searchFormParams.value,
|
...searchFormParams.value,
|
||||||
|
corpid: wxStore.corpid,
|
||||||
pageSize: pagination.value.pageSize,
|
pageSize: pagination.value.pageSize,
|
||||||
pageNum: pagination.value.currentPage
|
pageNum: pagination.value.currentPage
|
||||||
});
|
});
|
||||||
|
@ -125,6 +134,25 @@ const handleEdit = (row: GoodsDTO) => {
|
||||||
editVisible.value = true;
|
editVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleViewDetail = (row: GoodsDTO) => {
|
||||||
|
// 保存信息到标签页
|
||||||
|
useMultiTagsStoreHook().handleTags("push", {
|
||||||
|
path: `/shop/goods/detail`,
|
||||||
|
name: "GoodsDetail",
|
||||||
|
query: { id: row.goodsId },
|
||||||
|
meta: {
|
||||||
|
title: `${row.goodsName}`,
|
||||||
|
dynamicLevel: 3
|
||||||
|
}
|
||||||
|
});
|
||||||
|
router.push({
|
||||||
|
path: '/shop/goods/detail',
|
||||||
|
query: {
|
||||||
|
id: row.goodsId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -135,6 +163,13 @@ const handleEdit = (row: GoodsDTO) => {
|
||||||
<el-input @keydown.enter.prevent="onSearch" v-model="searchFormParams.goodsName" placeholder="请输入商品名称" clearable
|
<el-input @keydown.enter.prevent="onSearch" v-model="searchFormParams.goodsName" placeholder="请输入商品名称" clearable
|
||||||
class="!w-[200px]" />
|
class="!w-[200px]" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item prop="belongType">
|
||||||
|
<el-select v-model="searchFormParams.belongType" placeholder="请选择商品所属" clearable @change="onSearch"
|
||||||
|
class="!w-[180px]">
|
||||||
|
<el-option label="智柜通" :value="0" />
|
||||||
|
<el-option label="固资通" :value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<!-- <el-form-item label="状态:" prop="status">
|
<!-- <el-form-item label="状态:" prop="status">
|
||||||
<el-select v-model="searchFormParams.status" placeholder="请选择状态" clearable class="!w-[180px]">
|
<el-select v-model="searchFormParams.status" placeholder="请选择状态" clearable class="!w-[180px]">
|
||||||
<el-option label="已上架" :value="1" />
|
<el-option label="已上架" :value="1" />
|
||||||
|
@ -156,60 +191,27 @@ const handleEdit = (row: GoodsDTO) => {
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<div class="table-container">
|
<div class="grid-container">
|
||||||
<el-table ref="tableRef" v-loading="loading" :data="dataList" row-key="id"
|
<el-row :gutter="12">
|
||||||
@selection-change="handleSelectionChange" border>
|
<el-col v-for="(item, index) in dataList" :key="item.goodsId" :xs="24" :sm="12" :md="8" :lg="4" :xl="4">
|
||||||
<el-table-column type="selection" width="55" />
|
<el-card class="goods-card" :body-style="{ padding: '8px 10px' }">
|
||||||
<el-table-column label="商品图片" width="120">
|
<div class="card-content">
|
||||||
<template #default="{ row }">
|
<el-image :src="item.coverImg" :preview-src-list="[item.coverImg]" class="goods-image" fit="contain" />
|
||||||
<el-image :src="row.coverImg" :preview-src-list="[row.coverImg]" :z-index="9999" :preview-teleported="true"
|
<div class="goods-info">
|
||||||
:hide-on-click-modal="true" fit="cover" class="rounded" width="60" height="60" />
|
<div class="price">价格:{{ item.price }}</div>
|
||||||
</template>
|
<div class="stock">库存:{{ item.stock }}</div>
|
||||||
</el-table-column>
|
<div class="info-item">状态:{{ item.status === 1 ? '已上架' : '已下架' }}</div>
|
||||||
<el-table-column label="商品名称" prop="goodsName" />
|
</div>
|
||||||
<el-table-column label="价格" prop="price" width="120" />
|
</div>
|
||||||
<el-table-column label="库存" prop="stock" width="120" />
|
<div class="detail-btn" @click="handleViewDetail(item)">
|
||||||
<el-table-column label="状态" prop="status" width="120">
|
{{ item.goodsName }}
|
||||||
<template #default="{ row }">
|
</div>
|
||||||
<el-tag :type="row.status === 1 ? 'success' : 'danger'">
|
</el-card>
|
||||||
{{ row.status === 1 ? '已上架' : '已下架' }}
|
</el-col>
|
||||||
</el-tag>
|
</el-row>
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="自动审批" prop="autoApproval" width="120">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-tag :type="row.autoApproval === 1 ? 'success' : 'info'">
|
|
||||||
{{ row.autoApproval === 1 ? '启用' : '关闭' }}
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="柜口" prop="cellNo" width="120">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{ !row.cellNoStr ? '未配置' : row.cabinetName + ' 格口' + row.cellNoStr }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="操作" width="150" fixed="right">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-button type="primary" link :icon="useRenderIcon(EditPen)" @click="handleEdit(row)" class="right-btn">
|
|
||||||
编辑
|
|
||||||
</el-button>
|
|
||||||
<!-- <el-button type="warning" link :icon="useRenderIcon(Setting)" class="right-btn"
|
|
||||||
@click="currentRow = row; configVisible = true">
|
|
||||||
配置格口
|
|
||||||
</el-button> -->
|
|
||||||
<!-- <el-popconfirm :title="`确认删除【${row.goodsName}】?`" @confirm="handleDelete(row)">
|
|
||||||
<template #reference>
|
|
||||||
<el-button type="danger" link :icon="useRenderIcon(Delete)" class="right-btn">
|
|
||||||
删除
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-popconfirm> -->
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<el-pagination v-model:current-page="pagination.currentPage" v-model:page-size="pagination.pageSize"
|
<el-pagination v-model:current-page="pagination.currentPage" v-model:page-size="pagination.pageSize"
|
||||||
:page-sizes="[6, 10, 20, 50]" layout="total, sizes, prev, pager, next, jumper" :total="pagination.total"
|
:page-sizes="[12, 18, 24, 30, 36, 42]" layout="total, sizes, prev, pager, next, jumper"
|
||||||
@size-change="onSizeChange" @current-change="onCurrentChange" class="pagination" />
|
:total="pagination.total" @size-change="onSizeChange" @current-change="onCurrentChange" class="pagination" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 新增商品弹窗 -->
|
<!-- 新增商品弹窗 -->
|
||||||
<goods-form-modal v-model:visible="modalVisible" @refresh="getList" />
|
<goods-form-modal v-model:visible="modalVisible" @refresh="getList" />
|
||||||
|
@ -226,6 +228,7 @@ const handleEdit = (row: GoodsDTO) => {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
background-color: rgba(0, 0, 0, 0.8);
|
background-color: rgba(0, 0, 0, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-form {
|
.search-form {
|
||||||
:deep(.el-form-item) {
|
:deep(.el-form-item) {
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
|
@ -237,26 +240,97 @@ const handleEdit = (row: GoodsDTO) => {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.right-btn {
|
|
||||||
margin: 0;
|
.pagination {
|
||||||
|
margin-top: 10px;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
:deep(.el-pagination) {
|
||||||
|
margin: 0;
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-container {
|
.goods-card {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
min-height: 210px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
/* &:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin: 0px;
|
||||||
|
|
||||||
|
.goods-image {
|
||||||
|
width: 55%;
|
||||||
|
height: 180px;
|
||||||
|
object-fit: contain;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.goods-info {
|
||||||
|
flex: 1;
|
||||||
|
padding: 16px 0 0 0;
|
||||||
|
|
||||||
|
.name,
|
||||||
|
.info-item,
|
||||||
|
.price,
|
||||||
|
.stock {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .price,
|
||||||
|
.info-item,
|
||||||
|
.stock {
|
||||||
|
color: #909399;
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
margin: 5px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-btn {
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--el-color-primary-light-9);
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
margin-top: auto;
|
||||||
|
padding: 4px 0;
|
||||||
|
text-align: center;
|
||||||
|
color: #409eff;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-container {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
background-color: var(--el-bg-color);
|
background-color: var(--el-bg-color);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||||
display: flex;
|
margin-bottom: 12px;
|
||||||
flex-direction: column;
|
min-height: 300px;
|
||||||
|
|
||||||
.el-table {
|
.el-row {
|
||||||
flex: 1;
|
margin-bottom: -12px;
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pagination {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -216,7 +216,17 @@ onSearch().then(() => {
|
||||||
statusList[item].label }}</el-radio>
|
statusList[item].label }}</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item> -->
|
</el-form-item> -->
|
||||||
<el-form-item label="菜单权限" prop="menuIds" class="form-input">
|
<el-form-item prop="menuIds" class="form-input">
|
||||||
|
<template #label>
|
||||||
|
<div class="menu-label">
|
||||||
|
<span>菜单权限</span>
|
||||||
|
<!-- <el-checkbox-group v-model="formData.menuIds" class="checkbox-group">
|
||||||
|
<el-checkbox v-model="formData.menuIds" label="all" class="menu-checkbox">
|
||||||
|
全部
|
||||||
|
</el-checkbox>
|
||||||
|
</el-checkbox-group> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<el-checkbox-group v-model="formData.menuIds" class="checkbox-group">
|
<el-checkbox-group v-model="formData.menuIds" class="checkbox-group">
|
||||||
<template v-for="menu in processedMenuOptions" :key="menu.categoryName">
|
<template v-for="menu in processedMenuOptions" :key="menu.categoryName">
|
||||||
<span class="menu-category">{{ menu.categoryName }}:</span>
|
<span class="menu-category">{{ menu.categoryName }}:</span>
|
||||||
|
|
|
@ -257,7 +257,7 @@ watch(
|
||||||
.pagination-wrapper {
|
.pagination-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: var(--el-bg-color);
|
background: var(--el-bg-color);
|
||||||
padding: 8px 12px;
|
padding: 12px 12px 13px 12px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,16 @@
|
||||||
import { Goods, Shop, Document, Money } from '@element-plus/icons-vue';
|
import { Goods, Shop, Document, Money } from '@element-plus/icons-vue';
|
||||||
import { getStats, TodayLatestOrderGoodsDTO, TopGoodsDTO } from '@/api/shop/stats';
|
import { getStats, TodayLatestOrderGoodsDTO, TopGoodsDTO } from '@/api/shop/stats';
|
||||||
import { markRaw, onMounted, ref } from 'vue';
|
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';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "Welcome"
|
name: "Welcome"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const wxStore = useWxStore();
|
||||||
|
|
||||||
const shopData = ref<{
|
const shopData = ref<{
|
||||||
name: string;
|
name: string;
|
||||||
icon: any; // 假设这里是 Element Plus 的图标组件
|
icon: any; // 假设这里是 Element Plus 的图标组件
|
||||||
|
@ -32,6 +37,31 @@ const topGoods = ref<TopGoodsDTO[]>([]);
|
||||||
const todayLatestOrderGoods = ref<TodayLatestOrderGoodsDTO[]>([]);
|
const todayLatestOrderGoods = ref<TodayLatestOrderGoodsDTO[]>([]);
|
||||||
const maxOccurrenceCount = ref(0);
|
const maxOccurrenceCount = ref(0);
|
||||||
|
|
||||||
|
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 || '绑定失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
const { data } = await getStats();
|
const { data } = await getStats();
|
||||||
|
@ -59,6 +89,11 @@ onMounted(async () => {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取统计数据失败:', error);
|
console.error('获取统计数据失败:', error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (wxStore.qyUser && !wxStore.qyUser.ab98UserId) {
|
||||||
|
showDialog.value = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -187,6 +222,20 @@ onMounted(async () => {
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue