bookingUser改为shopUser
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
VITE_APP_NAME=后台管理系统
|
VITE_APP_NAME=后台管理系统
|
||||||
VITE_SOCKET_URL=wss://server.gxwebsoft.com
|
VITE_SOCKET_URL=wss://server.gxwebsoft.com
|
||||||
VITE_SERVER_URL=https://server.gxwebsoft.com/api
|
VITE_SERVER_URL=https://server.gxwebsoft.com/api
|
||||||
VITE_API_URL=https://modules.gxwebsoft.com/api
|
#VITE_API_URL=https://modules.gxwebsoft.com/api
|
||||||
|
|
||||||
#VITE_API_URL=http://127.0.0.1:9099/api
|
VITE_API_URL=http://127.0.0.1:9099/api
|
||||||
#VITE_SERVER_URL=http://127.0.0.1:9091/api
|
#VITE_SERVER_URL=http://127.0.0.1:9091/api
|
||||||
#VITE_SOCKET_URL=ws://localhost:9191
|
#VITE_SOCKET_URL=ws://localhost:9191
|
||||||
#VITE_API_URL=https://server.gxwebsoft.com/api
|
#VITE_API_URL=https://server.gxwebsoft.com/api
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ export interface LoginParam {
|
|||||||
tenantId?: number;
|
tenantId?: number;
|
||||||
// 是否记住密码
|
// 是否记住密码
|
||||||
remember?: boolean;
|
remember?: boolean;
|
||||||
|
// 手机号码
|
||||||
|
phone?: string;
|
||||||
|
// 短信验证码
|
||||||
|
code?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { PageParam } from '@/api';
|
import type { PageParam } from '@/api';
|
||||||
|
import { OrderInfo } from "@/api/shop/orderInfo/model";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 预约订单
|
* 预约订单
|
||||||
@@ -84,6 +85,12 @@ export interface Order {
|
|||||||
deleted?: number;
|
deleted?: number;
|
||||||
// 租户id
|
// 租户id
|
||||||
tenantId?: number;
|
tenantId?: number;
|
||||||
|
// 商户名称
|
||||||
|
merchantName?: string;
|
||||||
|
// 商户图标
|
||||||
|
merchantAvatar?: string;
|
||||||
|
//
|
||||||
|
orderInfoList?: OrderInfo[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,4 +99,5 @@ export interface Order {
|
|||||||
export interface OrderParam extends PageParam {
|
export interface OrderParam extends PageParam {
|
||||||
orderId?: number;
|
orderId?: number;
|
||||||
keywords?: string;
|
keywords?: string;
|
||||||
|
userId?: number;
|
||||||
}
|
}
|
||||||
|
|||||||
106
src/api/shop/orderInfo/index.ts
Normal file
106
src/api/shop/orderInfo/index.ts
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import type { ApiResult, PageResult } from '@/api';
|
||||||
|
import type { OrderInfo, OrderInfoParam } from './model';
|
||||||
|
import { MODULES_API_URL } from '@/config/setting';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询
|
||||||
|
*/
|
||||||
|
export async function pageOrderInfo(params: OrderInfoParam) {
|
||||||
|
const res = await request.get<ApiResult<PageResult<OrderInfo>>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info/page',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*/
|
||||||
|
export async function listOrderInfo(params?: OrderInfoParam) {
|
||||||
|
const res = await request.get<ApiResult<OrderInfo[]>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加
|
||||||
|
*/
|
||||||
|
export async function addOrderInfo(data: OrderInfo) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改
|
||||||
|
*/
|
||||||
|
export async function updateOrderInfo(data: OrderInfo) {
|
||||||
|
const res = await request.put<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
export async function removeOrderInfo(id?: number) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除
|
||||||
|
*/
|
||||||
|
export async function removeBatchOrderInfo(data: (number | undefined)[]) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info/batch',
|
||||||
|
{
|
||||||
|
data
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id查询
|
||||||
|
*/
|
||||||
|
export async function getOrderInfo(id: number) {
|
||||||
|
const res = await request.get<ApiResult<OrderInfo>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
55
src/api/shop/orderInfo/model/index.ts
Normal file
55
src/api/shop/orderInfo/model/index.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import type { PageParam } from '@/api';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export interface OrderInfo {
|
||||||
|
//
|
||||||
|
id?: number;
|
||||||
|
// 关联订单表id
|
||||||
|
oid?: number;
|
||||||
|
// 关联场馆id
|
||||||
|
sid?: number;
|
||||||
|
// 关联场地id
|
||||||
|
fid?: number;
|
||||||
|
// 场馆
|
||||||
|
siteName?: string;
|
||||||
|
// 场地
|
||||||
|
fieldName?: string;
|
||||||
|
// 预约时间段
|
||||||
|
dateTime?: string;
|
||||||
|
// 单价
|
||||||
|
price?: string;
|
||||||
|
// 儿童价
|
||||||
|
childrenPrice?: string;
|
||||||
|
// 成人人数
|
||||||
|
adultNum?: string;
|
||||||
|
// 儿童人数
|
||||||
|
childrenNum?: string;
|
||||||
|
// 1已付款,2未付款,3无需付款或占用状态
|
||||||
|
payStatus?: string;
|
||||||
|
// 是否免费:1免费、2收费
|
||||||
|
isFree?: string;
|
||||||
|
// 是否支持儿童票:1支持,2不支持
|
||||||
|
isChildren?: string;
|
||||||
|
// 预订类型:1全场,2半场
|
||||||
|
type?: string;
|
||||||
|
// 组合数据:日期+时间段+场馆id+场地id
|
||||||
|
mergeData?: string;
|
||||||
|
// 开场时间
|
||||||
|
startTime?: number;
|
||||||
|
// 下单时间
|
||||||
|
orderTime?: number;
|
||||||
|
// 毫秒时间戳
|
||||||
|
timeFlag?: string;
|
||||||
|
// 租户id
|
||||||
|
tenantId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索条件
|
||||||
|
*/
|
||||||
|
export interface OrderInfoParam extends PageParam {
|
||||||
|
id?: number;
|
||||||
|
keywords?: string;
|
||||||
|
}
|
||||||
106
src/api/shop/users/index.ts
Normal file
106
src/api/shop/users/index.ts
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import type { ApiResult, PageResult } from '@/api';
|
||||||
|
import type { Users, UsersParam } from './model';
|
||||||
|
import { MODULES_API_URL } from '@/config/setting';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询用户
|
||||||
|
*/
|
||||||
|
export async function pageUsers(params: UsersParam) {
|
||||||
|
const res = await request.get<ApiResult<PageResult<Users>>>(
|
||||||
|
MODULES_API_URL + '/shop/users/page',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询用户列表
|
||||||
|
*/
|
||||||
|
export async function listUsers(params?: UsersParam) {
|
||||||
|
const res = await request.get<ApiResult<Users[]>>(
|
||||||
|
MODULES_API_URL + '/shop/users',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加用户
|
||||||
|
*/
|
||||||
|
export async function addUsers(data: Users) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/users',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改用户
|
||||||
|
*/
|
||||||
|
export async function updateUsers(data: Users) {
|
||||||
|
const res = await request.put<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/users',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除用户
|
||||||
|
*/
|
||||||
|
export async function removeUsers(id?: number) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/users/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除用户
|
||||||
|
*/
|
||||||
|
export async function removeBatchUsers(data: (number | undefined)[]) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/users/batch',
|
||||||
|
{
|
||||||
|
data
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id查询用户
|
||||||
|
*/
|
||||||
|
export async function getUsers(id: number) {
|
||||||
|
const res = await request.get<ApiResult<Users>>(
|
||||||
|
MODULES_API_URL + '/shop/users/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
73
src/api/shop/users/model/index.ts
Normal file
73
src/api/shop/users/model/index.ts
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import type { PageParam } from '@/api';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户
|
||||||
|
*/
|
||||||
|
export interface Users {
|
||||||
|
//
|
||||||
|
userId?: number;
|
||||||
|
// 用户唯一小程序id
|
||||||
|
openid?: string;
|
||||||
|
// 小程序用户秘钥
|
||||||
|
sessionKey?: string;
|
||||||
|
// 用户名
|
||||||
|
username?: string;
|
||||||
|
// 头像地址
|
||||||
|
avatarUrl?: string;
|
||||||
|
// 1男,2女
|
||||||
|
sex?: string;
|
||||||
|
// 国家
|
||||||
|
country?: string;
|
||||||
|
// 省份
|
||||||
|
province?: string;
|
||||||
|
// 城市
|
||||||
|
city?: string;
|
||||||
|
// 所在辖区
|
||||||
|
region?: string;
|
||||||
|
// 经度
|
||||||
|
longitude?: string;
|
||||||
|
// 纬度
|
||||||
|
latitude?: string;
|
||||||
|
// 手机号码
|
||||||
|
phone?: string;
|
||||||
|
// 邮箱
|
||||||
|
email?: string;
|
||||||
|
// 邮箱是否验证, 0否, 1是
|
||||||
|
emailVerified?: number;
|
||||||
|
// 积分
|
||||||
|
points?: string;
|
||||||
|
// 余额
|
||||||
|
balance?: string;
|
||||||
|
// 注册时间
|
||||||
|
addTime?: number;
|
||||||
|
// 身份证号码
|
||||||
|
idCard?: string;
|
||||||
|
// 真实姓名
|
||||||
|
realName?: string;
|
||||||
|
// 是否管理员:1是;2否
|
||||||
|
isAdmin?: number;
|
||||||
|
// 客户端ID
|
||||||
|
clientId?: string;
|
||||||
|
// 注册来源客户端 (APP、H5、小程序等)
|
||||||
|
platform?: string;
|
||||||
|
// 排序
|
||||||
|
sortNumber?: number;
|
||||||
|
// 备注
|
||||||
|
comments?: string;
|
||||||
|
// 状态
|
||||||
|
status?: number;
|
||||||
|
// 是否删除, 0否, 1是
|
||||||
|
deleted?: number;
|
||||||
|
// 租户id
|
||||||
|
tenantId?: number;
|
||||||
|
// 注册时间
|
||||||
|
createTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户搜索条件
|
||||||
|
*/
|
||||||
|
export interface UsersParam extends PageParam {
|
||||||
|
userId?: number;
|
||||||
|
keywords?: string;
|
||||||
|
}
|
||||||
@@ -103,7 +103,7 @@ export interface User {
|
|||||||
//
|
//
|
||||||
truename?: string;
|
truename?: string;
|
||||||
// 是否管理员:1是;2否
|
// 是否管理员:1是;2否
|
||||||
isAdmin?: number;
|
isAdmin?: boolean;
|
||||||
// 客户端ID
|
// 客户端ID
|
||||||
clientId?: string;
|
clientId?: string;
|
||||||
// 注册来源客户端 (APP、H5、小程序等)
|
// 注册来源客户端 (APP、H5、小程序等)
|
||||||
|
|||||||
@@ -30,30 +30,39 @@
|
|||||||
</template>
|
</template>
|
||||||
<!-- 导航菜单 -->
|
<!-- 导航菜单 -->
|
||||||
<template v-if="form.showMenuCard">
|
<template v-if="form.showMenuCard">
|
||||||
<div class="menu-card ele-cell">
|
<!-- 单排 -->
|
||||||
<template
|
<div class="order-card ele-cell">
|
||||||
v-for="(item, index) in navigation1"
|
<div
|
||||||
|
v-for="(item, index) in navigation"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
class="ele-cell-content ele-text-center btn-center"
|
||||||
|
@click="openMpMenuEdit(item)"
|
||||||
>
|
>
|
||||||
|
<a-image :src="item.icon" :width="30" :preview="false" />
|
||||||
|
<span>{{ item.title }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 双排 -->
|
||||||
|
<div class="menu-card ele-cell">
|
||||||
|
<template v-for="(item, index) in navigation1" :key="index">
|
||||||
<div
|
<div
|
||||||
v-if="index < 4"
|
v-if="index < 4"
|
||||||
class="ele-cell-content ele-text-center btn-center"
|
class="ele-cell-content ele-text-center btn-center"
|
||||||
@click="openMpMenuEdit(item)"
|
@click="openMpMenuEdit(item)"
|
||||||
>
|
>
|
||||||
<a-image :src="item.icon" :width="30" :preview="false" />
|
<a-avatar :src="item.icon" :width="30" :preview="false" />
|
||||||
<span>{{ item.title }}</span>
|
<span>{{ item.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template
|
</div>
|
||||||
v-for="(item, index) in navigation2"
|
<div class="menu-card ele-cell">
|
||||||
:key="index"
|
<template v-for="(item, index) in navigation2" :key="index">
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
v-if="index < 4"
|
v-if="index < 4"
|
||||||
class="ele-cell-content ele-text-center btn-center"
|
class="ele-cell-content ele-text-center btn-center"
|
||||||
@click="openMpMenuEdit(item)"
|
@click="openMpMenuEdit(item)"
|
||||||
>
|
>
|
||||||
<a-image :src="item.icon" :width="30" :preview="false" />
|
<a-avatar :src="item.icon" :width="30" :preview="false" />
|
||||||
<span>{{ item.title }}</span>
|
<span>{{ item.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -194,6 +203,8 @@
|
|||||||
const adImageList = ref<any[]>();
|
const adImageList = ref<any[]>();
|
||||||
// 首页导航图标
|
// 首页导航图标
|
||||||
const scrollList = ref<any>();
|
const scrollList = ref<any>();
|
||||||
|
// 单排
|
||||||
|
const navigation = ref<MpMenu[]>();
|
||||||
// 第一排
|
// 第一排
|
||||||
const navigation1 = ref<any[]>();
|
const navigation1 = ref<any[]>();
|
||||||
// 第二排
|
// 第二排
|
||||||
@@ -245,8 +256,9 @@
|
|||||||
listMpMenu({}).then((list) => {
|
listMpMenu({}).then((list) => {
|
||||||
server.value = list.filter((d) => d.type == 0);
|
server.value = list.filter((d) => d.type == 0);
|
||||||
order.value = list.filter((d) => d.type == 1);
|
order.value = list.filter((d) => d.type == 1);
|
||||||
navigation1.value = list.filter((d) => d.type == 2 && d.rows == 0);
|
navigation.value = list.filter((d) => d.type == 2 && d.rows == 0);
|
||||||
navigation2.value = list.filter((d) => d.type == 2 && d.rows == 1);
|
navigation1.value = list.filter((d) => d.type == 2 && d.rows == 1);
|
||||||
|
navigation2.value = list.filter((d) => d.type == 2 && d.rows == 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
listAd({ adType: '幻灯片' }).then((res) => {
|
listAd({ adType: '幻灯片' }).then((res) => {
|
||||||
@@ -458,9 +470,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.menu-card {
|
.menu-card {
|
||||||
width: 340px;
|
width: 330px;
|
||||||
margin: 6px auto;
|
margin: 6px auto;
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border-color: slategrey;
|
border-color: slategrey;
|
||||||
.btn-center {
|
.btn-center {
|
||||||
@@ -518,4 +529,22 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.order-card {
|
||||||
|
width: 330px;
|
||||||
|
height: 80px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 5px;
|
||||||
|
border-color: slategrey;
|
||||||
|
//position: absolute;
|
||||||
|
//top: 230px;
|
||||||
|
//left: 24px;
|
||||||
|
.btn-center {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -9,104 +9,73 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tabs-card">
|
<template v-if="form.showOrderCard">
|
||||||
<a-tabs v-model:activeKey="activeKey">
|
|
||||||
<a-tab-pane key="1" tab="全部订单">
|
|
||||||
|
|
||||||
</a-tab-pane>
|
|
||||||
<a-tab-pane key="2" tab="未支付" force-render>
|
|
||||||
|
|
||||||
</a-tab-pane>
|
|
||||||
<a-tab-pane key="3" tab="已支付">
|
|
||||||
|
|
||||||
</a-tab-pane>
|
|
||||||
<a-tab-pane key="4" tab="已完成">
|
|
||||||
|
|
||||||
</a-tab-pane>
|
|
||||||
<a-tab-pane key="5" tab="押金">
|
|
||||||
|
|
||||||
</a-tab-pane>
|
|
||||||
</a-tabs>
|
|
||||||
<div class="order-list">
|
|
||||||
<span class="ele-text-placeholder">订单列表</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<template v-if="form.showMenuCard">
|
|
||||||
<div class="phone-body" style="overflow-y: auto; overflow-x: hidden">
|
<div class="phone-body" style="overflow-y: auto; overflow-x: hidden">
|
||||||
<!-- 幻灯片轮播 -->
|
<div class="tabs-card">
|
||||||
<template v-if="form.showCarousel">
|
<a-tabs v-model:activeKey="activeKey">
|
||||||
<a-carousel arrows autoplay :dots="true">
|
<a-tab-pane key="1" tab="全部订单" />
|
||||||
<template v-if="adImageList">
|
<a-tab-pane key="2" tab="未支付" force-render />
|
||||||
<template v-for="(img, index) in adImageList" :key="index">
|
<a-tab-pane key="3" tab="已支付" />
|
||||||
<div class="ad-item">
|
<a-tab-pane key="4" tab="已完成" />
|
||||||
<a-image
|
<a-tab-pane key="5" tab="押金" />
|
||||||
:preview="false"
|
</a-tabs>
|
||||||
:src="img.url"
|
</div>
|
||||||
width="100%"
|
<!-- 订单列表 -->
|
||||||
height="200px"
|
<template v-for="(item, index) in orderList" :key="index">
|
||||||
/>
|
<a-card
|
||||||
</div>
|
size="small"
|
||||||
</template>
|
class="order-item"
|
||||||
|
:title="item.merchantName"
|
||||||
|
:body-style="{ padding: '8px' }"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
{{ item.name }}
|
||||||
</template>
|
</template>
|
||||||
</a-carousel>
|
<template #extra
|
||||||
</template>
|
><span class="ele-text-success">已支付</span></template
|
||||||
<!-- 导航菜单 -->
|
|
||||||
<template v-if="form.showMenuCard">
|
|
||||||
<div class="menu-card ele-cell">
|
|
||||||
<div
|
|
||||||
v-for="(item, index) in scrollList"
|
|
||||||
:key="index"
|
|
||||||
class="ele-cell-content ele-text-center btn-center"
|
|
||||||
@click="openMpMenuEdit(item)"
|
|
||||||
>
|
>
|
||||||
<a-image :src="item.icon" :width="30" :preview="false" />
|
<template #actions>
|
||||||
<span>{{ item.title }}</span>
|
<div class="ele-cell card-actions">
|
||||||
</div>
|
<div class="card-actions-item" @click="actionsClick">
|
||||||
</div>
|
<a-button class="mini-btn" size="mini">申请开票</a-button>
|
||||||
<MpMenuEdit
|
</div>
|
||||||
v-model:visible="showMpMenuEdit"
|
</div>
|
||||||
:data="current"
|
</template>
|
||||||
@done="reload"
|
<div class="order-body ele-cell ele-cell-align-top">
|
||||||
/>
|
<!-- <uv-avatar :src="item.merchantAvatar" shape="square" size="90"></uv-avatar> -->
|
||||||
</template>
|
<div class="ele-cell-content">
|
||||||
<!-- 商户列表 -->
|
<block
|
||||||
<template v-if="form.showShopCard">
|
v-for="(sub, subIndex) in item.orderInfoList"
|
||||||
<div class="merchant-card-title">场地预定</div>
|
:key="subIndex"
|
||||||
<div
|
>
|
||||||
class="merchant-card ele-cell"
|
<div class="ele-cell">
|
||||||
v-for="(item, index) in shopList"
|
<div class="ele-text-secondary">时间:</div>
|
||||||
:key="index"
|
<div class="ele-text-heading">{{ sub.dateTime }}</div>
|
||||||
>
|
</div>
|
||||||
<a-image :src="item.image" :width="96" :preview="false" />
|
<div class="ele-cell">
|
||||||
<div class="merchant-info ele-cell-content">
|
<div class="ele-text-secondary">场地:</div>
|
||||||
<div class="merchant-name">{{ item.merchantName }}</div>
|
<div class="ele-text-heading">{{ sub.fieldName }}</div>
|
||||||
<div class="merchant-desc ele-cell-desc">
|
</div>
|
||||||
{{ item.comments }}
|
<div class="ele-cell">
|
||||||
|
<div class="ele-text-secondary">金额:</div>
|
||||||
|
<div class="ele-text-heading">¥{{ sub.price }}</div>
|
||||||
|
</div>
|
||||||
|
<div style="padding-bottom: 8px"></div>
|
||||||
|
</block>
|
||||||
|
<div class="ele-cell">
|
||||||
|
<div class="ele-text-placeholder" style="flex: 1;"
|
||||||
|
>共2件</div
|
||||||
|
>
|
||||||
|
<div class="ele-cell" style="font-weight: bold">
|
||||||
|
<div class="ele-text-heading"
|
||||||
|
>实付:</div
|
||||||
|
>
|
||||||
|
<div class="ele-text-heading">¥{{ item.payPrice }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="">-->
|
</a-card>
|
||||||
<!-- <a-button>我要去</a-button>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<!-- 培训课程 -->
|
|
||||||
<template v-if="form.showTtrainCard">
|
|
||||||
<div class="merchant-card-title">培训课程</div>
|
|
||||||
<div
|
|
||||||
class="merchant-card ele-cell"
|
|
||||||
v-for="(item, index) in shopList"
|
|
||||||
:key="index"
|
|
||||||
@click="openMpMenuEdit(item)"
|
|
||||||
>
|
|
||||||
<a-image :src="item.image" :width="96" :preview="false" />
|
|
||||||
<div class="merchant-info ele-cell-content">
|
|
||||||
<div class="merchant-name">{{ item.merchantName }}</div>
|
|
||||||
<div class="merchant-desc ele-cell-desc">
|
|
||||||
{{ item.comments }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -170,6 +139,8 @@
|
|||||||
const { query } = unref(currentRoute);
|
const { query } = unref(currentRoute);
|
||||||
|
|
||||||
import MpMenuEdit from '@/views/cms/mp-weixin/menu/components/mpMenuEdit.vue';
|
import MpMenuEdit from '@/views/cms/mp-weixin/menu/components/mpMenuEdit.vue';
|
||||||
|
import { listOrder, pageOrder } from '@/api/shop/order';
|
||||||
|
import { Order } from '@/api/shop/order/model';
|
||||||
|
|
||||||
const prpos = withDefaults(
|
const prpos = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@@ -206,6 +177,8 @@
|
|||||||
const server = ref<any[]>();
|
const server = ref<any[]>();
|
||||||
// 商户列表
|
// 商户列表
|
||||||
const shopList = ref<Merchant[]>();
|
const shopList = ref<Merchant[]>();
|
||||||
|
// 订单列表
|
||||||
|
const orderList = ref<Order[]>();
|
||||||
|
|
||||||
const config = ref({
|
const config = ref({
|
||||||
selector: '#content', //容器,可使用css选择器
|
selector: '#content', //容器,可使用css选择器
|
||||||
@@ -239,32 +212,38 @@
|
|||||||
const activeKey = ref('1');
|
const activeKey = ref('1');
|
||||||
|
|
||||||
const reload = () => {
|
const reload = () => {
|
||||||
listWebsiteField({}).then((list) => {
|
// listWebsiteField({}).then((list) => {
|
||||||
list.map((d) => {
|
// list.map((d) => {
|
||||||
const key = String(d.name);
|
// const key = String(d.name);
|
||||||
param.value[key] = d.value;
|
// param.value[key] = d.value;
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
|
|
||||||
listMpMenu({}).then((list) => {
|
// listMpMenu({}).then((list) => {
|
||||||
server.value = list.filter((d) => d.type == 0);
|
// server.value = list.filter((d) => d.type == 0);
|
||||||
order.value = list.filter((d) => d.type == 1);
|
// order.value = list.filter((d) => d.type == 1);
|
||||||
scrollList.value = list.filter((d) => d.type == 2);
|
// scrollList.value = list.filter((d) => d.type == 2);
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
|
// listAd({ adType: '幻灯片' }).then((res) => {
|
||||||
|
// const carouselImages = res[0].images;
|
||||||
|
// if (carouselImages) {
|
||||||
|
// adImageList.value = JSON.parse(carouselImages);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
listAd({ adType: '幻灯片' }).then((res) => {
|
// listMerchant({}).then((list) => {
|
||||||
const carouselImages = res[0].images;
|
// shopList.value = list;
|
||||||
if (carouselImages) {
|
// });
|
||||||
adImageList.value = JSON.parse(carouselImages);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
listMerchant({}).then((list) => {
|
pageOrder({ userId: 13448 }).then((res) => {
|
||||||
shopList.value = list;
|
orderList.value = res?.list;
|
||||||
});
|
});
|
||||||
emit('done');
|
emit('done');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const actionsClick = () => {};
|
||||||
|
|
||||||
reload();
|
reload();
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
@@ -523,12 +502,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs-card{
|
.tabs-card {
|
||||||
padding: 0 10px;
|
padding: 0 8px;
|
||||||
.order-list{
|
//.order-item {
|
||||||
background-color: #ffffff;
|
// background-color: #ffffff;
|
||||||
padding: 10px;
|
// padding: 10px;
|
||||||
min-height: 200px;
|
// min-height: 200px;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-item {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
.order-title {
|
||||||
|
padding: 20rpx 0;
|
||||||
|
border-bottom: 1px #eee solid;
|
||||||
|
|
||||||
|
.merchant-name {
|
||||||
|
padding-left: 12rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-body {
|
||||||
|
}
|
||||||
|
.card-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding-right: 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -117,11 +117,7 @@
|
|||||||
// 模拟器的字段
|
// 模拟器的字段
|
||||||
const form = ref<any>({
|
const form = ref<any>({
|
||||||
pageName: '场馆预定订单',
|
pageName: '场馆预定订单',
|
||||||
showOrderCard: false,
|
showOrderCard: true
|
||||||
showCarousel: false,
|
|
||||||
showMenuCard: false,
|
|
||||||
showShopCard: false,
|
|
||||||
showTtrainCard: false
|
|
||||||
});
|
});
|
||||||
// 菜单列表
|
// 菜单列表
|
||||||
const list = ref<any[]>();
|
const list = ref<any[]>();
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
<div
|
<div
|
||||||
class="title ele-cell-content"
|
class="title ele-cell-content"
|
||||||
:style="{ color: item.color || '#333333' }"
|
:style="{ color: item.color || '#333333' }"
|
||||||
>{{ item.title }}</div
|
>{{ item.title }}</div
|
||||||
>
|
>
|
||||||
<RightOutlined class="ele-text-secondary" />
|
<RightOutlined class="ele-text-secondary" />
|
||||||
</div>
|
</div>
|
||||||
@@ -80,8 +80,6 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<template v-if="form.showMenuCard">
|
<template v-if="form.showMenuCard">
|
||||||
<div class="phone-body" style="overflow-y: auto; overflow-x: hidden">
|
<div class="phone-body" style="overflow-y: auto; overflow-x: hidden">
|
||||||
<!-- 幻灯片轮播 -->
|
<!-- 幻灯片轮播 -->
|
||||||
@@ -200,12 +198,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {
|
import {
|
||||||
ProfileOutlined,
|
ProfileOutlined,
|
||||||
ShopOutlined,
|
ShopOutlined,
|
||||||
HomeOutlined,
|
HomeOutlined,
|
||||||
UserOutlined, RightOutlined
|
UserOutlined,
|
||||||
} from "@ant-design/icons-vue";
|
RightOutlined
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
import { ref, unref, watch } from 'vue';
|
import { ref, unref, watch } from 'vue';
|
||||||
import { MpWeixinParam, WebsiteField } from '@/api/cms/website/field/model';
|
import { MpWeixinParam, WebsiteField } from '@/api/cms/website/field/model';
|
||||||
import { listWebsiteField } from '@/api/system/website/field';
|
import { listWebsiteField } from '@/api/system/website/field';
|
||||||
@@ -220,7 +219,7 @@ import {
|
|||||||
const { query } = unref(currentRoute);
|
const { query } = unref(currentRoute);
|
||||||
|
|
||||||
import MpMenuEdit from '@/views/cms/mp-weixin/menu/components/mpMenuEdit.vue';
|
import MpMenuEdit from '@/views/cms/mp-weixin/menu/components/mpMenuEdit.vue';
|
||||||
import UserCardEdit from "@/views/cms/field/components/website-field-edit.vue";
|
import UserCardEdit from '@/views/cms/field/components/website-field-edit.vue';
|
||||||
|
|
||||||
const prpos = withDefaults(
|
const prpos = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
@@ -328,222 +327,222 @@ import {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.phone-layout {
|
.phone-layout {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 16px;
|
right: 16px;
|
||||||
width: 390px;
|
width: 390px;
|
||||||
height: 844px;
|
height: 844px;
|
||||||
background: url('@/assets/img/app-ui.png');
|
background: url('@/assets/img/app-ui.png');
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: top;
|
background-position: top;
|
||||||
background-size: 100%;
|
|
||||||
//position: relative;
|
|
||||||
padding: 0 16px;
|
|
||||||
.phone-header-black {
|
|
||||||
height: 99px;
|
|
||||||
border-radius: 20px 20px 0 0;
|
|
||||||
background-size: 100%;
|
background-size: 100%;
|
||||||
.title {
|
//position: relative;
|
||||||
|
padding: 0 16px;
|
||||||
|
.phone-header-black {
|
||||||
height: 99px;
|
height: 99px;
|
||||||
font-size: 16px;
|
border-radius: 20px 20px 0 0;
|
||||||
display: flex;
|
background-size: 100%;
|
||||||
justify-content: center;
|
.title {
|
||||||
align-items: end;
|
height: 99px;
|
||||||
padding-bottom: 13px;
|
font-size: 16px;
|
||||||
.title-bar {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: center;
|
||||||
.back {
|
align-items: end;
|
||||||
display: block;
|
padding-bottom: 13px;
|
||||||
width: 50px;
|
.title-bar {
|
||||||
margin-left: 3px;
|
width: 100%;
|
||||||
background-color: #ffffff;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
.back {
|
||||||
|
display: block;
|
||||||
|
width: 50px;
|
||||||
|
margin-left: 3px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
.share {
|
||||||
|
display: block;
|
||||||
|
width: 50px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.share {
|
}
|
||||||
display: block;
|
}
|
||||||
width: 50px;
|
.phone-body-bg {
|
||||||
cursor: pointer;
|
padding: 0 16px;
|
||||||
|
height: 680px;
|
||||||
|
border-radius: 0 0 44px 44px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.phone-body {
|
||||||
|
width: 356px;
|
||||||
|
margin-left: 17px;
|
||||||
|
height: 630px;
|
||||||
|
padding: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 98px;
|
||||||
|
left: 0;
|
||||||
|
z-index: 999;
|
||||||
|
.comments {
|
||||||
|
padding: 20px;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
.form-data {
|
||||||
|
padding: 10px 20px;
|
||||||
|
.submit-btn {
|
||||||
|
padding: 30px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.goods {
|
||||||
|
.price {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
.ele-cell-title {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.goods-attr {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.goods-divider {
|
||||||
|
height: 6px;
|
||||||
|
}
|
||||||
|
.buy-bar {
|
||||||
|
position: fixed;
|
||||||
|
width: 356px;
|
||||||
|
bottom: 70px;
|
||||||
|
//top: 881px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 0 0 44px 44px;
|
||||||
|
border-top: 1px solid var(--grey-8);
|
||||||
|
.ele-cell-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.shop-btn,
|
||||||
|
.kefu-btn,
|
||||||
|
.star-btn {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 0 9px;
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
|
font-size: 19px;
|
||||||
|
}
|
||||||
|
.buy-btn {
|
||||||
|
display: flex;
|
||||||
|
.add-cart {
|
||||||
|
border-radius: 100px 0 0 100px;
|
||||||
|
border: none;
|
||||||
|
background-color: var(--orange-5);
|
||||||
|
color: #ffffff;
|
||||||
|
height: 40px;
|
||||||
|
width: 95px;
|
||||||
|
}
|
||||||
|
.buy-now {
|
||||||
|
border-radius: 0 100px 100px 0;
|
||||||
|
border: none;
|
||||||
|
background-color: var(--red-6);
|
||||||
|
color: #ffffff;
|
||||||
|
height: 40px;
|
||||||
|
width: 95px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.phone-body-bg {
|
:deep(.slick-slide) {
|
||||||
padding: 0 16px;
|
|
||||||
height: 680px;
|
|
||||||
border-radius: 0 0 44px 44px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.phone-body {
|
:deep(.slick-arrow.custom-slick-arrow) {
|
||||||
width: 356px;
|
font-size: 38px;
|
||||||
margin-left: 17px;
|
|
||||||
height: 630px;
|
|
||||||
padding: 0;
|
|
||||||
position: absolute;
|
|
||||||
top: 98px;
|
|
||||||
left: 0;
|
|
||||||
z-index: 999;
|
|
||||||
.comments {
|
|
||||||
padding: 20px;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
.form-data {
|
|
||||||
padding: 10px 20px;
|
|
||||||
.submit-btn {
|
|
||||||
padding: 30px 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.goods {
|
:deep(.slick-arrow.custom-slick-arrow) {
|
||||||
.price {
|
color: #fff;
|
||||||
font-size: 18px;
|
background-color: rgba(31, 45, 61, 0.11);
|
||||||
}
|
transition: ease all 0.3s;
|
||||||
.ele-cell-title {
|
opacity: 0.3;
|
||||||
font-weight: 600;
|
z-index: 1;
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
.goods-attr {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.goods-divider {
|
:deep(.slick-arrow.custom-slick-arrow:before) {
|
||||||
height: 6px;
|
display: none;
|
||||||
}
|
}
|
||||||
.buy-bar {
|
:deep(.slick-arrow.custom-slick-arrow:hover) {
|
||||||
position: fixed;
|
color: #fff;
|
||||||
width: 356px;
|
opacity: 0.5;
|
||||||
bottom: 70px;
|
}
|
||||||
//top: 881px;
|
:deep(.slick-slide h3) {
|
||||||
background-color: #ffffff;
|
color: #fff;
|
||||||
border-radius: 0 0 44px 44px;
|
}
|
||||||
border-top: 1px solid var(--grey-8);
|
|
||||||
.ele-cell-content {
|
.user-card {
|
||||||
|
height: 170px;
|
||||||
|
margin: 0 1px;
|
||||||
|
background-color: var(--grey-10);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
display: flex;
|
||||||
|
.user-avatar {
|
||||||
|
margin-left: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
.user-info {
|
||||||
|
margin-left: 10px;
|
||||||
|
.nickname {
|
||||||
|
color: var(--grey-3);
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.phone {
|
||||||
|
color: var(--grey-5);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.shop-btn,
|
}
|
||||||
.kefu-btn,
|
|
||||||
.star-btn {
|
.order-card {
|
||||||
|
width: 340px;
|
||||||
|
height: 80px;
|
||||||
|
margin: 0 1px;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 5px;
|
||||||
|
border-color: slategrey;
|
||||||
|
position: absolute;
|
||||||
|
top: 230px;
|
||||||
|
left: 24px;
|
||||||
|
.btn-center {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
align-items: center;
|
||||||
font-size: 13px;
|
justify-content: center;
|
||||||
padding: 0 9px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
white-space: nowrap;
|
|
||||||
}
|
}
|
||||||
.icon {
|
}
|
||||||
font-size: 19px;
|
|
||||||
|
.tools-card {
|
||||||
|
width: 340px;
|
||||||
|
margin: 0 1px;
|
||||||
|
padding: 6px 16px;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 5px;
|
||||||
|
border-color: slategrey;
|
||||||
|
position: absolute;
|
||||||
|
top: 324px;
|
||||||
|
left: 24px;
|
||||||
|
.ele-cell {
|
||||||
|
padding: 4px 0;
|
||||||
|
border-bottom: 1px solid var(--grey-9);
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.buy-btn {
|
.btn-center {
|
||||||
display: flex;
|
display: flex;
|
||||||
.add-cart {
|
align-items: center;
|
||||||
border-radius: 100px 0 0 100px;
|
justify-content: center;
|
||||||
border: none;
|
|
||||||
background-color: var(--orange-5);
|
|
||||||
color: #ffffff;
|
|
||||||
height: 40px;
|
|
||||||
width: 95px;
|
|
||||||
}
|
|
||||||
.buy-now {
|
|
||||||
border-radius: 0 100px 100px 0;
|
|
||||||
border: none;
|
|
||||||
background-color: var(--red-6);
|
|
||||||
color: #ffffff;
|
|
||||||
height: 40px;
|
|
||||||
width: 95px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
:deep(.slick-slide) {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
:deep(.slick-arrow.custom-slick-arrow) {
|
|
||||||
font-size: 38px;
|
|
||||||
}
|
|
||||||
:deep(.slick-arrow.custom-slick-arrow) {
|
|
||||||
color: #fff;
|
|
||||||
background-color: rgba(31, 45, 61, 0.11);
|
|
||||||
transition: ease all 0.3s;
|
|
||||||
opacity: 0.3;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
:deep(.slick-arrow.custom-slick-arrow:before) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
:deep(.slick-arrow.custom-slick-arrow:hover) {
|
|
||||||
color: #fff;
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
:deep(.slick-slide h3) {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-card {
|
|
||||||
height: 170px;
|
|
||||||
margin: 0 1px;
|
|
||||||
background-color: var(--grey-10);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: cover;
|
|
||||||
display: flex;
|
|
||||||
.user-avatar {
|
|
||||||
margin-left: 16px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
.user-info {
|
|
||||||
margin-left: 10px;
|
|
||||||
.nickname {
|
|
||||||
color: var(--grey-3);
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
.phone {
|
|
||||||
color: var(--grey-5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.order-card {
|
|
||||||
width: 340px;
|
|
||||||
height: 80px;
|
|
||||||
margin: 0 1px;
|
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 5px;
|
|
||||||
border-color: slategrey;
|
|
||||||
position: absolute;
|
|
||||||
top: 230px;
|
|
||||||
left: 24px;
|
|
||||||
.btn-center {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tools-card {
|
|
||||||
width: 340px;
|
|
||||||
margin: 0 1px;
|
|
||||||
padding: 6px 16px;
|
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 5px;
|
|
||||||
border-color: slategrey;
|
|
||||||
position: absolute;
|
|
||||||
top: 324px;
|
|
||||||
left: 24px;
|
|
||||||
.ele-cell {
|
|
||||||
padding: 4px 0;
|
|
||||||
border-bottom: 1px solid var(--grey-9);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.btn-center {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
106
src/views/shop/orderInfo/index.ts
Normal file
106
src/views/shop/orderInfo/index.ts
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import request from '@/utils/request';
|
||||||
|
import type { ApiResult, PageResult } from '@/api';
|
||||||
|
import type { OrderInfo, OrderInfoParam } from './model';
|
||||||
|
import { MODULES_API_URL } from '@/config/setting';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询
|
||||||
|
*/
|
||||||
|
export async function pageOrderInfo(params: OrderInfoParam) {
|
||||||
|
const res = await request.get<ApiResult<PageResult<OrderInfo>>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info/page',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*/
|
||||||
|
export async function listOrderInfo(params?: OrderInfoParam) {
|
||||||
|
const res = await request.get<ApiResult<OrderInfo[]>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info',
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加
|
||||||
|
*/
|
||||||
|
export async function addOrderInfo(data: OrderInfo) {
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改
|
||||||
|
*/
|
||||||
|
export async function updateOrderInfo(data: OrderInfo) {
|
||||||
|
const res = await request.put<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info',
|
||||||
|
data
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
*/
|
||||||
|
export async function removeOrderInfo(id?: number) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除
|
||||||
|
*/
|
||||||
|
export async function removeBatchOrderInfo(data: (number | undefined)[]) {
|
||||||
|
const res = await request.delete<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info/batch',
|
||||||
|
{
|
||||||
|
data
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id查询
|
||||||
|
*/
|
||||||
|
export async function getOrderInfo(id: number) {
|
||||||
|
const res = await request.get<ApiResult<OrderInfo>>(
|
||||||
|
MODULES_API_URL + '/shop/order-info/' + id
|
||||||
|
);
|
||||||
|
if (res.data.code === 0 && res.data.data) {
|
||||||
|
return res.data.data;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
55
src/views/shop/orderInfo/model/index.ts
Normal file
55
src/views/shop/orderInfo/model/index.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import type { PageParam } from '@/api';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
export interface OrderInfo {
|
||||||
|
//
|
||||||
|
id?: number;
|
||||||
|
// 关联订单表id
|
||||||
|
oid?: number;
|
||||||
|
// 关联场馆id
|
||||||
|
sid?: number;
|
||||||
|
// 关联场地id
|
||||||
|
fid?: number;
|
||||||
|
// 场馆
|
||||||
|
siteName?: string;
|
||||||
|
// 场地
|
||||||
|
fieldName?: string;
|
||||||
|
// 预约时间段
|
||||||
|
dateTime?: string;
|
||||||
|
// 单价
|
||||||
|
price?: string;
|
||||||
|
// 儿童价
|
||||||
|
childrenPrice?: string;
|
||||||
|
// 成人人数
|
||||||
|
adultNum?: string;
|
||||||
|
// 儿童人数
|
||||||
|
childrenNum?: string;
|
||||||
|
// 1已付款,2未付款,3无需付款或占用状态
|
||||||
|
payStatus?: string;
|
||||||
|
// 是否免费:1免费、2收费
|
||||||
|
isFree?: string;
|
||||||
|
// 是否支持儿童票:1支持,2不支持
|
||||||
|
isChildren?: string;
|
||||||
|
// 预订类型:1全场,2半场
|
||||||
|
type?: string;
|
||||||
|
// 组合数据:日期+时间段+场馆id+场地id
|
||||||
|
mergeData?: string;
|
||||||
|
// 开场时间
|
||||||
|
startTime?: number;
|
||||||
|
// 下单时间
|
||||||
|
orderTime?: number;
|
||||||
|
// 毫秒时间戳
|
||||||
|
timeFlag?: string;
|
||||||
|
// 租户id
|
||||||
|
tenantId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索条件
|
||||||
|
*/
|
||||||
|
export interface OrderInfoParam extends PageParam {
|
||||||
|
id?: number;
|
||||||
|
keywords?: string;
|
||||||
|
}
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
<!-- 机构选择下拉框 -->
|
|
||||||
<template>
|
|
||||||
<a-tree-select
|
|
||||||
allow-clear
|
|
||||||
tree-default-expand-all
|
|
||||||
:placeholder="placeholder"
|
|
||||||
:value="value || undefined"
|
|
||||||
:tree-data="data"
|
|
||||||
:dropdown-style="{ maxHeight: '360px', overflow: 'auto' }"
|
|
||||||
@update:value="updateValue"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import type { Organization } from '@/api/system/organization/model';
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'update:value', value?: number): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
// 选中的数据(v-modal)
|
|
||||||
value?: number;
|
|
||||||
// 提示信息
|
|
||||||
placeholder?: string;
|
|
||||||
// 机构数据
|
|
||||||
data: Organization[];
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
placeholder: '请选择角色'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
/* 更新选中数据 */
|
|
||||||
const updateValue = (value?: number) => {
|
|
||||||
emit('update:value', value);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
<!-- 角色选择下拉框 -->
|
|
||||||
<template>
|
|
||||||
<a-select
|
|
||||||
allow-clear
|
|
||||||
mode="multiple"
|
|
||||||
:value="roleIds"
|
|
||||||
:placeholder="placeholder"
|
|
||||||
@update:value="updateValue"
|
|
||||||
@blur="onBlur"
|
|
||||||
>
|
|
||||||
<a-select-option
|
|
||||||
v-for="item in data"
|
|
||||||
:key="item.roleId"
|
|
||||||
:value="item.roleId"
|
|
||||||
>
|
|
||||||
{{ item.roleName }}
|
|
||||||
</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, computed } from 'vue';
|
|
||||||
import { message } from 'ant-design-vue/es';
|
|
||||||
import { listRoles } from '@/api/system/role';
|
|
||||||
import type { Role } from '@/api/system/role/model';
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'update:value', value: Role[]): void;
|
|
||||||
(e: 'blur'): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const props = withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
// 选中的角色
|
|
||||||
value?: Role[];
|
|
||||||
//
|
|
||||||
placeholder?: string;
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
placeholder: '请选择角色'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 选中的角色id
|
|
||||||
const roleIds = computed(() => props.value?.map((d) => d.roleId as number));
|
|
||||||
|
|
||||||
// 角色数据
|
|
||||||
const data = ref<Role[]>([]);
|
|
||||||
|
|
||||||
/* 更新选中数据 */
|
|
||||||
const updateValue = (value: number[]) => {
|
|
||||||
emit(
|
|
||||||
'update:value',
|
|
||||||
value.map((v) => ({ roleId: v }))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 获取角色数据 */
|
|
||||||
listRoles()
|
|
||||||
.then((list) => {
|
|
||||||
data.value = list;
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
message.error(e.message);
|
|
||||||
});
|
|
||||||
|
|
||||||
/* 失去焦点 */
|
|
||||||
const onBlur = () => {
|
|
||||||
emit('blur');
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<!-- 角色选择下拉框 -->
|
|
||||||
<template>
|
|
||||||
<a-select
|
|
||||||
show-search
|
|
||||||
optionFilterProp="label"
|
|
||||||
:options="data"
|
|
||||||
allow-clear
|
|
||||||
:value="value"
|
|
||||||
:placeholder="placeholder"
|
|
||||||
@update:value="updateValue"
|
|
||||||
@blur="onBlur"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { getDictionaryOptions } from '@/utils/common';
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'update:value', value: string): void;
|
|
||||||
(e: 'blur'): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
value?: string;
|
|
||||||
placeholder?: string;
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
placeholder: '请选择性别'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 字典数据
|
|
||||||
const data = getDictionaryOptions('sex');
|
|
||||||
|
|
||||||
/* 更新选中数据 */
|
|
||||||
const updateValue = (value: string) => {
|
|
||||||
emit('update:value', value);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 失去焦点 */
|
|
||||||
const onBlur = () => {
|
|
||||||
emit('blur');
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@@ -1,313 +0,0 @@
|
|||||||
<!-- 用户编辑弹窗 -->
|
|
||||||
<template>
|
|
||||||
<ele-modal
|
|
||||||
:width="800"
|
|
||||||
:visible="visible"
|
|
||||||
:confirm-loading="loading"
|
|
||||||
:title="isUpdate ? '用户详情' : '新建用户'"
|
|
||||||
:body-style="{ paddingBottom: '8px' }"
|
|
||||||
@update:visible="updateVisible"
|
|
||||||
@ok="save"
|
|
||||||
>
|
|
||||||
<a-form
|
|
||||||
ref="formRef"
|
|
||||||
:model="form"
|
|
||||||
:rules="rules"
|
|
||||||
:label-col="styleResponsive ? { md: 5, sm: 4, xs: 24 } : { flex: '90px' }"
|
|
||||||
:wrapper-col="
|
|
||||||
styleResponsive ? { md: 17, sm: 20, xs: 24 } : { flex: '1' }
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<a-row :gutter="16">
|
|
||||||
<a-col
|
|
||||||
v-bind="styleResponsive ? { md: 12, sm: 24, xs: 24 } : { span: 12 }"
|
|
||||||
>
|
|
||||||
<a-form-item label="手机号" v-if="isUpdate" name="mobile">
|
|
||||||
<a-input
|
|
||||||
allow-clear
|
|
||||||
:maxlength="11"
|
|
||||||
placeholder="请输入手机号"
|
|
||||||
v-model:value="form.mobile"
|
|
||||||
:disabled="isUpdate"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="昵称" name="nickname">
|
|
||||||
<a-input
|
|
||||||
allow-clear
|
|
||||||
:maxlength="20"
|
|
||||||
placeholder="请输入昵称"
|
|
||||||
v-model:value="form.nickname"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="真实姓名" name="realName">
|
|
||||||
<a-input
|
|
||||||
allow-clear
|
|
||||||
:maxlength="20"
|
|
||||||
placeholder="请输入真实姓名"
|
|
||||||
v-model:value="form.realName"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="性别" name="sex">
|
|
||||||
<span v-if="form.sex == 1">男</span>
|
|
||||||
<span v-else-if="form.sex == 2">女</span>
|
|
||||||
<span v-else>未知</span>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col
|
|
||||||
v-bind="styleResponsive ? { md: 12, sm: 24, xs: 24 } : { span: 12 }"
|
|
||||||
>
|
|
||||||
<a-form-item label="会员等级">
|
|
||||||
<SelectGrade
|
|
||||||
:placeholder="`请选择会员等级`"
|
|
||||||
v-model:value="form.gradeName"
|
|
||||||
:disabled="isUpdate"
|
|
||||||
@done="chooseGradeId"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="邮箱" name="email">
|
|
||||||
<a-input
|
|
||||||
allow-clear
|
|
||||||
:maxlength="100"
|
|
||||||
placeholder="请输入邮箱"
|
|
||||||
v-model:value="form.email"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="出生日期">
|
|
||||||
<a-date-picker
|
|
||||||
class="ele-fluid"
|
|
||||||
value-format="YYYY-MM-DD"
|
|
||||||
placeholder="请选择出生日期"
|
|
||||||
v-model:value="form.birthday"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item v-if="!isUpdate" label="登录密码" name="password">
|
|
||||||
<a-input-password
|
|
||||||
:maxlength="20"
|
|
||||||
v-model:value="form.password"
|
|
||||||
placeholder="请输入登录密码"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="个人简介">
|
|
||||||
<a-textarea
|
|
||||||
:rows="4"
|
|
||||||
:maxlength="200"
|
|
||||||
placeholder="请输入个人简介"
|
|
||||||
v-model:value="form.introduction"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-form>
|
|
||||||
</ele-modal>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, reactive, watch } from 'vue';
|
|
||||||
import { message } from 'ant-design-vue/es';
|
|
||||||
import type { FormInstance, Rule } from 'ant-design-vue/es/form';
|
|
||||||
import { emailReg, phoneReg } from 'ele-admin-pro/es';
|
|
||||||
import { storeToRefs } from 'pinia';
|
|
||||||
import { useThemeStore } from '@/store/modules/theme';
|
|
||||||
import useFormData from '@/utils/use-form-data';
|
|
||||||
import RoleSelect from './role-select.vue';
|
|
||||||
import SexSelect from './sex-select.vue';
|
|
||||||
import { addUser, updateUser, checkExistence } from '@/api/system/user';
|
|
||||||
import type { User } from '@/api/system/user/model';
|
|
||||||
import OrgSelect from './org-select.vue';
|
|
||||||
// import { getDictionaryOptions } from '@/utils/common';
|
|
||||||
import { Organization } from '@/api/system/organization/model';
|
|
||||||
import { Grade } from '@/api/user/grade/model';
|
|
||||||
|
|
||||||
// 是否开启响应式布局
|
|
||||||
const themeStore = useThemeStore();
|
|
||||||
const { styleResponsive } = storeToRefs(themeStore);
|
|
||||||
// 获取字典数据
|
|
||||||
// const userTypeData = getDictionaryOptions('userType');
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'done'): void;
|
|
||||||
(e: 'update:visible', visible: boolean): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
// 弹窗是否打开
|
|
||||||
visible: boolean;
|
|
||||||
// 修改回显的数据
|
|
||||||
data?: User | null;
|
|
||||||
// 全部机构
|
|
||||||
organizationList: Organization[];
|
|
||||||
}>();
|
|
||||||
|
|
||||||
//
|
|
||||||
const formRef = ref<FormInstance | null>(null);
|
|
||||||
|
|
||||||
// 是否是修改
|
|
||||||
const isUpdate = ref(false);
|
|
||||||
|
|
||||||
// 提交状态
|
|
||||||
const loading = ref(false);
|
|
||||||
|
|
||||||
// 表单数据
|
|
||||||
const { form, resetFields, assignFields } = useFormData<User>({
|
|
||||||
type: undefined,
|
|
||||||
userId: undefined,
|
|
||||||
username: '',
|
|
||||||
nickname: '',
|
|
||||||
realName: '',
|
|
||||||
companyName: '',
|
|
||||||
sex: undefined,
|
|
||||||
roles: [],
|
|
||||||
email: '',
|
|
||||||
phone: '',
|
|
||||||
mobile: '',
|
|
||||||
password: '',
|
|
||||||
introduction: '',
|
|
||||||
organizationId: undefined,
|
|
||||||
birthday: '',
|
|
||||||
idCard: '',
|
|
||||||
comments: '',
|
|
||||||
gradeName: '',
|
|
||||||
gradeId: undefined
|
|
||||||
});
|
|
||||||
|
|
||||||
// 表单验证规则
|
|
||||||
const rules = reactive<Record<string, Rule[]>>({
|
|
||||||
username: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
type: 'string',
|
|
||||||
validator: (_rule: Rule, value: string) => {
|
|
||||||
return new Promise<void>((resolve, reject) => {
|
|
||||||
if (!value) {
|
|
||||||
return reject('请输入用户账号');
|
|
||||||
}
|
|
||||||
checkExistence('username', value, props.data?.userId)
|
|
||||||
.then(() => {
|
|
||||||
reject('账号已经存在');
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
nickname: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: '请输入昵称',
|
|
||||||
type: 'string',
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
// realName: [
|
|
||||||
// {
|
|
||||||
// required: true,
|
|
||||||
// message: '请输入真实姓名',
|
|
||||||
// type: 'string',
|
|
||||||
// trigger: 'blur'
|
|
||||||
// }
|
|
||||||
// ],
|
|
||||||
// sex: [
|
|
||||||
// {
|
|
||||||
// required: true,
|
|
||||||
// message: '请选择性别',
|
|
||||||
// type: 'string',
|
|
||||||
// trigger: 'blur'
|
|
||||||
// }
|
|
||||||
// ],
|
|
||||||
roles: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: '请选择角色',
|
|
||||||
type: 'array',
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
email: [
|
|
||||||
{
|
|
||||||
pattern: emailReg,
|
|
||||||
message: '邮箱格式不正确',
|
|
||||||
type: 'string',
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
password: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
type: 'string',
|
|
||||||
validator: async (_rule: Rule, value: string) => {
|
|
||||||
if (isUpdate.value || /^[\S]{5,18}$/.test(value)) {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
return Promise.reject('密码必须为5-18位非空白字符');
|
|
||||||
},
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
phone: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
pattern: phoneReg,
|
|
||||||
message: '手机号格式不正确',
|
|
||||||
type: 'string',
|
|
||||||
trigger: 'blur'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
const chooseGradeId = (data: Grade) => {
|
|
||||||
form.gradeName = data.name;
|
|
||||||
form.gradeId = data.gradeId;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 保存编辑 */
|
|
||||||
const save = () => {
|
|
||||||
if (!formRef.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
formRef.value
|
|
||||||
.validate()
|
|
||||||
.then(() => {
|
|
||||||
loading.value = true;
|
|
||||||
const saveOrUpdate = isUpdate.value ? updateUser : addUser;
|
|
||||||
saveOrUpdate(form)
|
|
||||||
.then((msg) => {
|
|
||||||
loading.value = false;
|
|
||||||
message.success(msg);
|
|
||||||
updateVisible(false);
|
|
||||||
emit('done');
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
loading.value = false;
|
|
||||||
message.error(e.message);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(() => {});
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 更新visible */
|
|
||||||
const updateVisible = (value: boolean) => {
|
|
||||||
emit('update:visible', value);
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(visible) => {
|
|
||||||
if (visible) {
|
|
||||||
if (props.data) {
|
|
||||||
assignFields({
|
|
||||||
...props.data,
|
|
||||||
password: ''
|
|
||||||
});
|
|
||||||
isUpdate.value = true;
|
|
||||||
} else {
|
|
||||||
isUpdate.value = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
resetFields();
|
|
||||||
formRef.value?.clearValidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
<!-- 用户导入弹窗 -->
|
|
||||||
<template>
|
|
||||||
<ele-modal
|
|
||||||
:width="520"
|
|
||||||
:footer="null"
|
|
||||||
title="导入用户"
|
|
||||||
:visible="visible"
|
|
||||||
@update:visible="updateVisible"
|
|
||||||
>
|
|
||||||
<a-spin :spinning="loading">
|
|
||||||
<a-upload-dragger
|
|
||||||
accept=".xls,.xlsx"
|
|
||||||
:show-upload-list="false"
|
|
||||||
:customRequest="doUpload"
|
|
||||||
style="padding: 24px 0; margin-bottom: 16px"
|
|
||||||
>
|
|
||||||
<p class="ant-upload-drag-icon">
|
|
||||||
<cloud-upload-outlined />
|
|
||||||
</p>
|
|
||||||
<p class="ant-upload-hint">将文件拖到此处,或点击上传</p>
|
|
||||||
</a-upload-dragger>
|
|
||||||
</a-spin>
|
|
||||||
<div class="ele-text-center">
|
|
||||||
<span>只能上传xls、xlsx文件,</span>
|
|
||||||
<a
|
|
||||||
href="https://cdn.eleadmin.com/20200610/用户导入模板.xlsx"
|
|
||||||
download="用户导入模板.xlsx"
|
|
||||||
>
|
|
||||||
下载模板
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</ele-modal>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { message } from 'ant-design-vue/es';
|
|
||||||
import { CloudUploadOutlined } from '@ant-design/icons-vue';
|
|
||||||
import { importUsers } from '@/api/system/user';
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'done'): void;
|
|
||||||
(e: 'update:visible', visible: boolean): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
defineProps<{
|
|
||||||
// 是否打开弹窗
|
|
||||||
visible: boolean;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
// 导入请求状态
|
|
||||||
const loading = ref(false);
|
|
||||||
|
|
||||||
/* 上传 */
|
|
||||||
const doUpload = ({ file }) => {
|
|
||||||
if (
|
|
||||||
![
|
|
||||||
'application/vnd.ms-excel',
|
|
||||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
||||||
].includes(file.type)
|
|
||||||
) {
|
|
||||||
message.error('只能选择 excel 文件');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (file.size / 1024 / 1024 > 10) {
|
|
||||||
message.error('大小不能超过 10MB');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
loading.value = true;
|
|
||||||
importUsers(file)
|
|
||||||
.then((msg) => {
|
|
||||||
loading.value = false;
|
|
||||||
message.success(msg);
|
|
||||||
updateVisible(false);
|
|
||||||
emit('done');
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
loading.value = false;
|
|
||||||
message.error(e.message);
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 更新 visible */
|
|
||||||
const updateVisible = (value: boolean) => {
|
|
||||||
emit('update:visible', value);
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
<!-- 用户编辑弹窗 -->
|
|
||||||
<template>
|
|
||||||
<a-drawer
|
|
||||||
:width="680"
|
|
||||||
:visible="visible"
|
|
||||||
:confirm-loading="loading"
|
|
||||||
:title="'基本信息'"
|
|
||||||
:body-style="{ paddingBottom: '8px' }"
|
|
||||||
@update:visible="updateVisible"
|
|
||||||
:footer="null"
|
|
||||||
>
|
|
||||||
<a-form
|
|
||||||
:label-col="{ md: { span: 6 }, sm: { span: 24 } }"
|
|
||||||
:wrapper-col="{ md: { span: 19 }, sm: { span: 24 } }"
|
|
||||||
>
|
|
||||||
<a-row :gutter="16">
|
|
||||||
<a-col
|
|
||||||
v-bind="styleResponsive ? { md: 12, sm: 24, xs: 24 } : { span: 12 }"
|
|
||||||
>
|
|
||||||
<a-form-item label="账号">
|
|
||||||
<span class="ele-text">{{ user.username }}</span>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="昵称">
|
|
||||||
<span class="ele-text">{{ user.nickname }}</span>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="性别">
|
|
||||||
<span class="ele-text">{{ user.sexName }}</span>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="手机号">
|
|
||||||
<span class="ele-text">{{ user.phone }}</span>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="角色">
|
|
||||||
<a-tag v-for="item in user.roles" :key="item.roleId" color="blue">
|
|
||||||
{{ item.roleName }}
|
|
||||||
</a-tag>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="状态">
|
|
||||||
<a-badge
|
|
||||||
v-if="typeof user.status === 'number'"
|
|
||||||
:status="(['processing', 'error'][user.status] as any)"
|
|
||||||
:text="['正常', '冻结'][user.status]"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="地址">
|
|
||||||
<span class="ele-text">{{ user.address }}</span>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col
|
|
||||||
v-bind="styleResponsive ? { md: 12, sm: 24, xs: 24 } : { span: 12 }"
|
|
||||||
>
|
|
||||||
<a-form-item label="可用余额">
|
|
||||||
<span class="ele-text-success">¥{{ formatNumber(user.balance) }}</span>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="可用积分">
|
|
||||||
<span class="ele-text">{{ user.points }}</span>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="实际消费">
|
|
||||||
<span class="ele-text">{{ user.payMoney }}</span>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="机构/部门">
|
|
||||||
<span class="ele-text">{{ user.organizationName }}</span>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="头像">
|
|
||||||
<a-image :src="user.avatar" :width="36" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="生日">
|
|
||||||
<span class="ele-text">{{ user.birthday }}</span>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="创建时间">
|
|
||||||
<span class="ele-text">{{ user.createTime }}</span>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-form>
|
|
||||||
</a-drawer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, reactive, watch } from 'vue';
|
|
||||||
import { Form } from 'ant-design-vue';
|
|
||||||
import { assignObject } from 'ele-admin-pro';
|
|
||||||
import type { User } from '@/api/system/user/model';
|
|
||||||
import { useThemeStore } from '@/store/modules/theme';
|
|
||||||
import { formatNumber } from 'ele-admin-pro/es';
|
|
||||||
import { storeToRefs } from 'pinia';
|
|
||||||
|
|
||||||
const useForm = Form.useForm;
|
|
||||||
// 是否开启响应式布局
|
|
||||||
const themeStore = useThemeStore();
|
|
||||||
const { styleResponsive } = storeToRefs(themeStore);
|
|
||||||
const props = defineProps<{
|
|
||||||
// 弹窗是否打开
|
|
||||||
visible: boolean;
|
|
||||||
// 修改回显的数据
|
|
||||||
data?: User | null;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'done'): void;
|
|
||||||
(e: 'update:visible', visible: boolean): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
// 用户信息
|
|
||||||
const user = reactive<User>({
|
|
||||||
username: '',
|
|
||||||
nickname: '',
|
|
||||||
sexName: '',
|
|
||||||
phone: '',
|
|
||||||
avatar: '',
|
|
||||||
balance: undefined,
|
|
||||||
points: 0,
|
|
||||||
payMoney: 0,
|
|
||||||
birthday: '',
|
|
||||||
address: '',
|
|
||||||
roles: [],
|
|
||||||
createTime: undefined,
|
|
||||||
status: undefined
|
|
||||||
});
|
|
||||||
|
|
||||||
// 请求状态
|
|
||||||
const loading = ref(true);
|
|
||||||
|
|
||||||
const { resetFields } = useForm(user);
|
|
||||||
|
|
||||||
/* 更新visible */
|
|
||||||
const updateVisible = (value: boolean) => {
|
|
||||||
emit('update:visible', value);
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.visible,
|
|
||||||
(visible) => {
|
|
||||||
if (visible) {
|
|
||||||
if (props.data) {
|
|
||||||
loading.value = false;
|
|
||||||
assignObject(user, props.data);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
resetFields();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
<!-- 搜索表单 -->
|
|
||||||
<template>
|
|
||||||
<a-form
|
|
||||||
:label-col="
|
|
||||||
styleResponsive ? { xl: 7, lg: 5, md: 7, sm: 4 } : { flex: '90px' }
|
|
||||||
"
|
|
||||||
:wrapper-col="
|
|
||||||
styleResponsive ? { xl: 17, lg: 19, md: 17, sm: 20 } : { flex: '1' }
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<a-row :gutter="8">
|
|
||||||
<a-col
|
|
||||||
v-bind="
|
|
||||||
styleResponsive
|
|
||||||
? { xl: 6, lg: 12, md: 12, sm: 24, xs: 24 }
|
|
||||||
: { span: 6 }
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<a-form-item label="用户账号">
|
|
||||||
<a-input
|
|
||||||
v-model:value.trim="form.username"
|
|
||||||
placeholder="请输入"
|
|
||||||
allow-clear
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col
|
|
||||||
v-bind="
|
|
||||||
styleResponsive
|
|
||||||
? { xl: 6, lg: 12, md: 12, sm: 24, xs: 24 }
|
|
||||||
: { span: 6 }
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<a-form-item label="昵称">
|
|
||||||
<a-input
|
|
||||||
v-model:value.trim="form.nickname"
|
|
||||||
placeholder="请输入"
|
|
||||||
allow-clear
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col
|
|
||||||
v-bind="
|
|
||||||
styleResponsive
|
|
||||||
? { xl: 6, lg: 12, md: 12, sm: 24, xs: 24 }
|
|
||||||
: { span: 6 }
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<a-form-item label="性别">
|
|
||||||
<a-select v-model:value="form.sex" placeholder="请选择" allow-clear>
|
|
||||||
<a-select-option value="1">男</a-select-option>
|
|
||||||
<a-select-option value="2">女</a-select-option>
|
|
||||||
</a-select>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
<a-col
|
|
||||||
v-bind="
|
|
||||||
styleResponsive
|
|
||||||
? { xl: 6, lg: 12, md: 12, sm: 24, xs: 24 }
|
|
||||||
: { span: 6 }
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<a-form-item class="ele-text-right" :wrapper-col="{ span: 24 }">
|
|
||||||
<a-space>
|
|
||||||
<a-button type="primary" @click="search">查询</a-button>
|
|
||||||
<a-button @click="reset">重置</a-button>
|
|
||||||
</a-space>
|
|
||||||
</a-form-item>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</a-form>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { storeToRefs } from 'pinia';
|
|
||||||
import { useThemeStore } from '@/store/modules/theme';
|
|
||||||
import useFormData from '@/utils/use-form-data';
|
|
||||||
import type { UserParam } from '@/api/system/user/model';
|
|
||||||
|
|
||||||
// 是否开启响应式布局
|
|
||||||
const themeStore = useThemeStore();
|
|
||||||
const { styleResponsive } = storeToRefs(themeStore);
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
// 默认搜索条件
|
|
||||||
where?: UserParam;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
(e: 'search', where?: UserParam): void;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
// 表单数据
|
|
||||||
const { form, resetFields } = useFormData<UserParam>({
|
|
||||||
username: '',
|
|
||||||
nickname: '',
|
|
||||||
sex: undefined,
|
|
||||||
...props.where
|
|
||||||
});
|
|
||||||
|
|
||||||
/* 搜索 */
|
|
||||||
const search = () => {
|
|
||||||
emit('search', form);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 重置 */
|
|
||||||
const reset = () => {
|
|
||||||
resetFields();
|
|
||||||
search();
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="ele-body">
|
|
||||||
<a-card title="基本信息" :bordered="false">
|
|
||||||
<a-form
|
|
||||||
class="ele-form-detail"
|
|
||||||
:label-col="
|
|
||||||
styleResponsive ? { md: 2, sm: 4, xs: 6 } : { flex: '90px' }
|
|
||||||
"
|
|
||||||
:wrapper-col="
|
|
||||||
styleResponsive ? { md: 22, sm: 20, xs: 18 } : { flex: '1' }
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<a-form-item label="账号">
|
|
||||||
<div class="ele-text-secondary">{{ form.username }}</div>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="昵称">
|
|
||||||
<div class="ele-text-secondary">{{ form.nickname }}</div>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="性别">
|
|
||||||
<div class="ele-text-secondary">{{ form.sexName }}</div>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="手机号">
|
|
||||||
<div class="ele-text-secondary">{{ form.phone }}</div>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="真实姓名">
|
|
||||||
<div class="ele-text-secondary">{{ form.realName }}</div>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="别名">
|
|
||||||
<div class="ele-text-secondary">{{ form.alias }}</div>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="角色">
|
|
||||||
<a-tag v-for="item in form.roles" :key="item.roleId" color="blue">
|
|
||||||
{{ item.roleName }}
|
|
||||||
</a-tag>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="创建时间">
|
|
||||||
<div class="ele-text-secondary">{{ form.createTime }}</div>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item label="状态">
|
|
||||||
<a-badge
|
|
||||||
v-if="typeof form.status === 'number'"
|
|
||||||
:status="(['processing', 'error'][form.status] as any)"
|
|
||||||
:text="['正常', '冻结'][form.status]"
|
|
||||||
/>
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</a-card>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { ref, watch, unref } from 'vue';
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
import { message } from 'ant-design-vue/es';
|
|
||||||
import { toDateString } from 'ele-admin-pro/es';
|
|
||||||
import { storeToRefs } from 'pinia';
|
|
||||||
import { useThemeStore } from '@/store/modules/theme';
|
|
||||||
import useFormData from '@/utils/use-form-data';
|
|
||||||
import { setPageTabTitle } from '@/utils/page-tab-util';
|
|
||||||
import { getUser } from '@/api/system/user';
|
|
||||||
import type { User } from '@/api/system/user/model';
|
|
||||||
const ROUTE_PATH = '/system/user/details';
|
|
||||||
|
|
||||||
// 是否开启响应式布局
|
|
||||||
const themeStore = useThemeStore();
|
|
||||||
const { styleResponsive } = storeToRefs(themeStore);
|
|
||||||
|
|
||||||
const { currentRoute } = useRouter();
|
|
||||||
|
|
||||||
// 用户信息
|
|
||||||
const { form, assignFields } = useFormData<User>({
|
|
||||||
userId: undefined,
|
|
||||||
alias: '',
|
|
||||||
realName: '',
|
|
||||||
username: '',
|
|
||||||
nickname: '',
|
|
||||||
sexName: '',
|
|
||||||
phone: '',
|
|
||||||
roles: [],
|
|
||||||
createTime: undefined,
|
|
||||||
status: undefined
|
|
||||||
});
|
|
||||||
|
|
||||||
// 请求状态
|
|
||||||
const loading = ref(true);
|
|
||||||
|
|
||||||
/* */
|
|
||||||
const query = () => {
|
|
||||||
const { query } = unref(currentRoute);
|
|
||||||
const id = query.id;
|
|
||||||
if (!id || form.userId === Number(id)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
loading.value = true;
|
|
||||||
getUser(Number(id))
|
|
||||||
.then((data) => {
|
|
||||||
loading.value = false;
|
|
||||||
assignFields({
|
|
||||||
...data,
|
|
||||||
createTime: toDateString(data.createTime)
|
|
||||||
});
|
|
||||||
// 修改页签标题
|
|
||||||
if (unref(currentRoute).path === ROUTE_PATH) {
|
|
||||||
setPageTabTitle(data.nickname + '的信息');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
loading.value = false;
|
|
||||||
message.error(e.message);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(
|
|
||||||
currentRoute,
|
|
||||||
(route) => {
|
|
||||||
const { path } = unref(route);
|
|
||||||
if (path !== ROUTE_PATH) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
query();
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
export default {
|
|
||||||
name: 'SystemUserDetails'
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@@ -1,502 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="ele-body">
|
|
||||||
<a-card :bordered="false">
|
|
||||||
<!-- 表格 -->
|
|
||||||
<ele-pro-table
|
|
||||||
ref="tableRef"
|
|
||||||
row-key="userId"
|
|
||||||
:columns="columns"
|
|
||||||
:datasource="datasource"
|
|
||||||
:scroll="{ x: 1300 }"
|
|
||||||
:where="defaultWhere"
|
|
||||||
:customRow="customRow"
|
|
||||||
cache-key="proSystemUserTable"
|
|
||||||
>
|
|
||||||
<template #toolbar>
|
|
||||||
<a-space>
|
|
||||||
<a-input-search
|
|
||||||
allow-clear
|
|
||||||
v-model:value="searchText"
|
|
||||||
placeholder="请输入关键词"
|
|
||||||
@search="reload"
|
|
||||||
@pressEnter="reload"
|
|
||||||
/>
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
<template #bodyCell="{ column, record }">
|
|
||||||
<template v-if="column.key === 'nickname'">
|
|
||||||
<div class="user-box">
|
|
||||||
<a-avatar
|
|
||||||
:size="30"
|
|
||||||
:src="`${record.avatar}`"
|
|
||||||
style="margin-right: 4px"
|
|
||||||
>
|
|
||||||
<template #icon>
|
|
||||||
<UserOutlined />
|
|
||||||
</template>
|
|
||||||
</a-avatar>
|
|
||||||
<div class="user-info" @click="openEdit(record)">
|
|
||||||
<span>{{ record.nickname }}</span>
|
|
||||||
<!-- <span class="ele-text-placeholder">{{ record.nickname }}</span>-->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'mobile'">
|
|
||||||
<span>{{ record.mobile }}</span>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="column.key === 'roles'">
|
|
||||||
<a-tag v-for="item in record.roles" :key="item.roleId" color="blue">
|
|
||||||
{{ item.roleName }}
|
|
||||||
</a-tag>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'balance'">
|
|
||||||
<span class="ele-text-success">
|
|
||||||
¥{{ formatNumber(record.balance) }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template v-if="column.key === 'expendMoney'">
|
|
||||||
<span class="ele-text-warning">
|
|
||||||
¥{{ formatNumber(record.expendMoney) }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="column.key === 'status'">
|
|
||||||
<a-switch
|
|
||||||
:checked="record.status === 0"
|
|
||||||
@change="(checked: boolean) => editStatus(checked, record)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="column.key === 'action'">
|
|
||||||
<a-space>
|
|
||||||
<a @click="openEdit(record)">详情</a>
|
|
||||||
<!-- <a-divider type="vertical" />-->
|
|
||||||
<!-- <a-popconfirm-->
|
|
||||||
<!-- placement="topRight"-->
|
|
||||||
<!-- title="确定要删除此用户吗?"-->
|
|
||||||
<!-- @confirm="remove(record)"-->
|
|
||||||
<!-- >-->
|
|
||||||
<!-- <a class="ele-text-danger">删除</a>-->
|
|
||||||
<!-- </a-popconfirm>-->
|
|
||||||
</a-space>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</ele-pro-table>
|
|
||||||
</a-card>
|
|
||||||
<!-- 编辑弹窗 -->
|
|
||||||
<user-edit
|
|
||||||
v-model:visible="showEdit"
|
|
||||||
:data="current"
|
|
||||||
:organization-list="data"
|
|
||||||
@done="reload"
|
|
||||||
/>
|
|
||||||
<!-- 用户详情 -->
|
|
||||||
<user-info v-model:visible="showInfo" :data="current" @done="reload" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { createVNode, ref, reactive } from 'vue';
|
|
||||||
import { message, Modal } from 'ant-design-vue/es';
|
|
||||||
import {
|
|
||||||
PlusOutlined,
|
|
||||||
DeleteOutlined,
|
|
||||||
UploadOutlined,
|
|
||||||
EditOutlined,
|
|
||||||
UserOutlined,
|
|
||||||
ExclamationCircleOutlined
|
|
||||||
} from '@ant-design/icons-vue';
|
|
||||||
import type { EleProTable } from 'ele-admin-pro/es';
|
|
||||||
import type {
|
|
||||||
DatasourceFunction,
|
|
||||||
ColumnItem
|
|
||||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
|
||||||
import { messageLoading, formatNumber } from 'ele-admin-pro/es';
|
|
||||||
import { timeAgo } from 'ele-admin-pro';
|
|
||||||
import UserEdit from './components/user-edit.vue';
|
|
||||||
import UserImport from './components/user-import.vue';
|
|
||||||
import UserInfo from './components/user-info.vue';
|
|
||||||
import {
|
|
||||||
pageUsers,
|
|
||||||
removeUser,
|
|
||||||
removeUsers,
|
|
||||||
updateUserStatus,
|
|
||||||
updateUserPassword
|
|
||||||
} from '@/api/system/user';
|
|
||||||
import type { User, UserParam } from '@/api/system/user/model';
|
|
||||||
import { toTreeData, uuid } from 'ele-admin-pro';
|
|
||||||
import { listRoles } from '@/api/system/role';
|
|
||||||
import { listOrganizations } from '@/api/system/organization';
|
|
||||||
import { Organization } from '@/api/system/organization/model';
|
|
||||||
import { hasRole } from '@/utils/permission';
|
|
||||||
|
|
||||||
// 加载状态
|
|
||||||
const loading = ref(true);
|
|
||||||
// 树形数据
|
|
||||||
const data = ref<Organization[]>([]);
|
|
||||||
// 树展开的key
|
|
||||||
const expandedRowKeys = ref<number[]>([]);
|
|
||||||
// 树选中的key
|
|
||||||
const selectedRowKeys = ref<number[]>([]);
|
|
||||||
// 表格选中数据
|
|
||||||
const selection = ref<User[]>([]);
|
|
||||||
// 当前编辑数据
|
|
||||||
const current = ref<User | null>(null);
|
|
||||||
// 是否显示编辑弹窗
|
|
||||||
const showEdit = ref(false);
|
|
||||||
// 是否显示用户详情
|
|
||||||
const showInfo = ref(false);
|
|
||||||
// 是否显示用户导入弹窗
|
|
||||||
const showImport = ref(false);
|
|
||||||
const userType = ref<number>();
|
|
||||||
const searchText = ref('');
|
|
||||||
|
|
||||||
// 加载角色
|
|
||||||
const roles = ref<any[]>([]);
|
|
||||||
const filters = () => {
|
|
||||||
listRoles().then((result) => {
|
|
||||||
result.map((d) => {
|
|
||||||
roles.value.push({
|
|
||||||
text: d.roleName,
|
|
||||||
value: d.roleId
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
filters();
|
|
||||||
// 加载机构
|
|
||||||
listOrganizations()
|
|
||||||
.then((list) => {
|
|
||||||
loading.value = false;
|
|
||||||
const eks: number[] = [];
|
|
||||||
list.forEach((d) => {
|
|
||||||
d.key = d.organizationId;
|
|
||||||
d.value = d.organizationId;
|
|
||||||
d.title = d.organizationName;
|
|
||||||
if (typeof d.key === 'number') {
|
|
||||||
eks.push(d.key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expandedRowKeys.value = eks;
|
|
||||||
data.value = toTreeData({
|
|
||||||
data: list,
|
|
||||||
idField: 'organizationId',
|
|
||||||
parentIdField: 'parentId'
|
|
||||||
});
|
|
||||||
if (list.length) {
|
|
||||||
if (typeof list[0].key === 'number') {
|
|
||||||
selectedRowKeys.value = [list[0].key];
|
|
||||||
}
|
|
||||||
// current.value = list[0];
|
|
||||||
} else {
|
|
||||||
selectedRowKeys.value = [];
|
|
||||||
// current.value = null;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
loading.value = false;
|
|
||||||
message.error(e.message);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 表格实例
|
|
||||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
|
||||||
// 表格列配置
|
|
||||||
const columns = ref<ColumnItem[]>([
|
|
||||||
{
|
|
||||||
title: 'ID',
|
|
||||||
dataIndex: 'userId',
|
|
||||||
width: 80,
|
|
||||||
showSorterTooltip: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '昵称',
|
|
||||||
key: 'nickname',
|
|
||||||
dataIndex: 'nickname',
|
|
||||||
width: 240,
|
|
||||||
showSorterTooltip: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '手机号码',
|
|
||||||
dataIndex: 'mobile',
|
|
||||||
key: 'mobile',
|
|
||||||
showSorterTooltip: false
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// title: '客户分组',
|
|
||||||
// dataIndex: 'type',
|
|
||||||
// key: 'type',
|
|
||||||
// align: 'center',
|
|
||||||
// width: 120
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
title: '性别',
|
|
||||||
dataIndex: 'sexName',
|
|
||||||
align: 'center',
|
|
||||||
width: 180,
|
|
||||||
showSorterTooltip: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '邮箱',
|
|
||||||
dataIndex: 'email',
|
|
||||||
hideInTable: true,
|
|
||||||
width: 180,
|
|
||||||
showSorterTooltip: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '可用余额',
|
|
||||||
dataIndex: 'balance',
|
|
||||||
key: 'balance',
|
|
||||||
align: 'center',
|
|
||||||
width: 180,
|
|
||||||
sorter: true,
|
|
||||||
showSorterTooltip: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '实际消费金额',
|
|
||||||
dataIndex: 'expendMoney',
|
|
||||||
key: 'expendMoney',
|
|
||||||
sorter: true,
|
|
||||||
hideInTable: true,
|
|
||||||
showSorterTooltip: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '可用积分',
|
|
||||||
dataIndex: 'points',
|
|
||||||
hideInTable: true,
|
|
||||||
sorter: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '注册来源',
|
|
||||||
key: 'platform',
|
|
||||||
align: 'center',
|
|
||||||
dataIndex: 'platform',
|
|
||||||
hideInTable: true,
|
|
||||||
customRender: ({ text }) => ['未知', '网站', '小程序', 'APP'][text]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '证件号码',
|
|
||||||
dataIndex: 'idCard',
|
|
||||||
hideInTable: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '出生日期',
|
|
||||||
dataIndex: 'birthday',
|
|
||||||
key: 'birthday',
|
|
||||||
hideInTable: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '省份',
|
|
||||||
dataIndex: 'province',
|
|
||||||
key: 'province',
|
|
||||||
hideInTable: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '城市',
|
|
||||||
dataIndex: 'city',
|
|
||||||
key: 'city',
|
|
||||||
hideInTable: true,
|
|
||||||
showSorterTooltip: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '地区',
|
|
||||||
dataIndex: 'region',
|
|
||||||
key: 'region',
|
|
||||||
hideInTable: true,
|
|
||||||
showSorterTooltip: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '个人简介',
|
|
||||||
dataIndex: 'introduction',
|
|
||||||
key: 'introduction',
|
|
||||||
hideInTable: true,
|
|
||||||
showSorterTooltip: false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '邮箱认证',
|
|
||||||
dataIndex: 'emailVerified',
|
|
||||||
hideInTable: true,
|
|
||||||
showSorterTooltip: false,
|
|
||||||
customRender: ({ text }) => ['未认证', '已认证'][text]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '实名认证',
|
|
||||||
dataIndex: 'certification',
|
|
||||||
sorter: true,
|
|
||||||
hideInTable: true,
|
|
||||||
customRender: ({ text }) => ['未认证', '已认证'][text]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '注册时间',
|
|
||||||
dataIndex: 'createTime',
|
|
||||||
sorter: true,
|
|
||||||
align: 'center',
|
|
||||||
width: 200,
|
|
||||||
showSorterTooltip: false,
|
|
||||||
ellipsis: true,
|
|
||||||
customRender: ({ text }) => timeAgo(text)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: '操作',
|
|
||||||
key: 'action',
|
|
||||||
width: 120,
|
|
||||||
fixed: 'right',
|
|
||||||
align: 'center'
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 默认搜索条件
|
|
||||||
const defaultWhere = reactive({
|
|
||||||
username: '',
|
|
||||||
nickname: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
// 表格数据源
|
|
||||||
const datasource: DatasourceFunction = ({
|
|
||||||
page,
|
|
||||||
limit,
|
|
||||||
where,
|
|
||||||
orders,
|
|
||||||
filters
|
|
||||||
}) => {
|
|
||||||
where = {};
|
|
||||||
where.roleId = filters.roles;
|
|
||||||
where.keywords = searchText.value;
|
|
||||||
return pageUsers({ page, limit, ...where, ...orders });
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 搜索 */
|
|
||||||
const reload = (where?: UserParam) => {
|
|
||||||
selection.value = [];
|
|
||||||
tableRef?.value?.reload({ where });
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 打开编辑弹窗 */
|
|
||||||
const openEdit = (row?: User) => {
|
|
||||||
current.value = row ?? null;
|
|
||||||
showEdit.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 打开用户详情弹窗 */
|
|
||||||
const openInfo = (row?: User) => {
|
|
||||||
current.value = row ?? null;
|
|
||||||
showInfo.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 打开编辑弹窗 */
|
|
||||||
const openImport = () => {
|
|
||||||
showImport.value = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTabs = (e) => {
|
|
||||||
userType.value = Number(e.target.value);
|
|
||||||
reload();
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 删除单个 */
|
|
||||||
const remove = (row: User) => {
|
|
||||||
const hide = messageLoading('请求中..', 0);
|
|
||||||
removeUser(row.userId)
|
|
||||||
.then((msg) => {
|
|
||||||
hide();
|
|
||||||
message.success(msg);
|
|
||||||
reload();
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
hide();
|
|
||||||
message.error(e.message);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 批量删除 */
|
|
||||||
const removeBatch = () => {
|
|
||||||
if (!selection.value.length) {
|
|
||||||
message.error('请至少选择一条数据');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Modal.confirm({
|
|
||||||
title: '提示',
|
|
||||||
content: '确定要删除选中的用户吗?',
|
|
||||||
icon: createVNode(ExclamationCircleOutlined),
|
|
||||||
maskClosable: true,
|
|
||||||
onOk: () => {
|
|
||||||
const hide = messageLoading('请求中..', 0);
|
|
||||||
removeUsers(selection.value.map((d) => d.userId))
|
|
||||||
.then((msg) => {
|
|
||||||
hide();
|
|
||||||
message.success(msg);
|
|
||||||
reload();
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
hide();
|
|
||||||
message.error(e.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 重置用户密码 */
|
|
||||||
const resetPsw = (row: User) => {
|
|
||||||
Modal.confirm({
|
|
||||||
title: '提示',
|
|
||||||
content: '确定要重置此用户的密码吗?',
|
|
||||||
icon: createVNode(ExclamationCircleOutlined),
|
|
||||||
maskClosable: true,
|
|
||||||
onOk: () => {
|
|
||||||
const hide = message.loading('请求中..', 0);
|
|
||||||
const password = uuid(8);
|
|
||||||
updateUserPassword(row.userId, password)
|
|
||||||
.then((msg) => {
|
|
||||||
hide();
|
|
||||||
message.success(msg + ',新密码:' + password);
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
hide();
|
|
||||||
message.error(e.message);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 修改用户状态 */
|
|
||||||
const editStatus = (checked: boolean, row: User) => {
|
|
||||||
const status = checked ? 0 : 1;
|
|
||||||
updateUserStatus(row.userId, status)
|
|
||||||
.then((msg) => {
|
|
||||||
row.status = status;
|
|
||||||
message.success(msg);
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
message.error(e.message);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 自定义行属性 */
|
|
||||||
const customRow = (record: User) => {
|
|
||||||
return {
|
|
||||||
// 行点击事件
|
|
||||||
onClick: () => {
|
|
||||||
// console.log(record);
|
|
||||||
},
|
|
||||||
// 行双击事件
|
|
||||||
onDblclick: () => {
|
|
||||||
openEdit(record);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
export default {
|
|
||||||
name: 'SystemUser'
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="less" scoped>
|
|
||||||
.user-box {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
.user-info {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
53
src/views/shop/users/components/search.vue
Normal file
53
src/views/shop/users/components/search.vue
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
<!-- 搜索表单 -->
|
||||||
|
<template>
|
||||||
|
<a-space :size="10" style="flex-wrap: wrap">
|
||||||
|
<a-input-search
|
||||||
|
allow-clear
|
||||||
|
v-model:value="where.keywords"
|
||||||
|
placeholder="请输入关键词"
|
||||||
|
@search="search"
|
||||||
|
@pressEnter="search"
|
||||||
|
/>
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { watch } from 'vue';
|
||||||
|
import useSearch from '@/utils/use-search';
|
||||||
|
import { UsersParam } from '@/api/booking/users/model';
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
// 选中的角色
|
||||||
|
selection?: [];
|
||||||
|
}>(),
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'search', where?: UsersParam): void;
|
||||||
|
(e: 'add'): void;
|
||||||
|
(e: 'remove'): void;
|
||||||
|
(e: 'batchMove'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const { where } = useSearch<UsersParam>({
|
||||||
|
keywords: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 搜索 */
|
||||||
|
const search = () => {
|
||||||
|
emit('search', where);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 新增
|
||||||
|
const add = () => {
|
||||||
|
emit('add');
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.selection,
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
</script>
|
||||||
331
src/views/shop/users/components/userEdit.vue
Normal file
331
src/views/shop/users/components/userEdit.vue
Normal file
@@ -0,0 +1,331 @@
|
|||||||
|
<!-- 编辑弹窗 -->
|
||||||
|
<template>
|
||||||
|
<ele-modal
|
||||||
|
:width="800"
|
||||||
|
:visible="visible"
|
||||||
|
:maskClosable="false"
|
||||||
|
:maxable="maxable"
|
||||||
|
:title="isUpdate ? '编辑用户' : '添加用户'"
|
||||||
|
:body-style="{ paddingBottom: '28px' }"
|
||||||
|
@update:visible="updateVisible"
|
||||||
|
@ok="save"
|
||||||
|
>
|
||||||
|
<a-form
|
||||||
|
ref="formRef"
|
||||||
|
:model="form"
|
||||||
|
:rules="rules"
|
||||||
|
:label-col="styleResponsive ? { md: 4, sm: 5, xs: 24 } : { flex: '90px' }"
|
||||||
|
:wrapper-col="
|
||||||
|
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<a-form-item label="openid" name="openid">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入用户唯一小程序id"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.openid"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="用户秘钥" name="sessionKey">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入小程序用户秘钥"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.sessionKey"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="用户名" name="username">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入用户名"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.username"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="头像地址" name="avatarUrl">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入头像地址"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.avatarUrl"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="1男,2女" name="gender">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入1男,2女"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.sex"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="国家" name="country">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入国家"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.country"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="省份" name="province">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入省份"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.province"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="城市" name="city">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入城市"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.city"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="所在辖区" name="region">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
:disabled="true"
|
||||||
|
placeholder="请输入所在辖区"
|
||||||
|
v-model:value="form.region"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="手机号码" name="phone">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入手机号码"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.phone"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="邮箱" name="email">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入邮箱"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.email"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="积分" name="points">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
:disabled="true"
|
||||||
|
placeholder="请输入积分"
|
||||||
|
v-model:value="form.points"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="余额" name="balance">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
:disabled="true"
|
||||||
|
placeholder="请输入余额"
|
||||||
|
v-model:value="form.balance"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="注册时间" name="addTime">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入注册时间"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.addTime"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="身份证号码" name="idcard">
|
||||||
|
<a-input allow-clear placeholder="请输入" :disabled="true" v-model:value="form.idCard" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="真实姓名" name="realName">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.realName"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="注册来源" name="platform">
|
||||||
|
<a-input
|
||||||
|
allow-clear
|
||||||
|
placeholder="请输入注册来源客户端 (APP、H5、小程序等)"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.platform"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="排序" name="sortNumber">
|
||||||
|
<a-input-number
|
||||||
|
:min="0"
|
||||||
|
:max="9999"
|
||||||
|
class="ele-fluid"
|
||||||
|
placeholder="请输入排序号"
|
||||||
|
:disabled="true"
|
||||||
|
v-model:value="form.sortNumber"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="备注" name="comments">
|
||||||
|
<a-textarea
|
||||||
|
:rows="4"
|
||||||
|
:maxlength="200"
|
||||||
|
placeholder="请输入描述"
|
||||||
|
v-model:value="form.comments"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</ele-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, watch } from 'vue';
|
||||||
|
import { Form, message } from 'ant-design-vue';
|
||||||
|
import { assignObject, toDateString, uuid } from 'ele-admin-pro';
|
||||||
|
import { addUsers, updateUsers } from '@/api/shop/users';
|
||||||
|
import { Users } from '@/api/shop/users/model';
|
||||||
|
import { useThemeStore } from '@/store/modules/theme';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||||
|
import { FormInstance } from 'ant-design-vue/es/form';
|
||||||
|
import { FileRecord } from '@/api/system/file/model';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
// 是否是修改
|
||||||
|
const isUpdate = ref(false);
|
||||||
|
const useForm = Form.useForm;
|
||||||
|
// 是否开启响应式布局
|
||||||
|
const themeStore = useThemeStore();
|
||||||
|
const { styleResponsive } = storeToRefs(themeStore);
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
// 弹窗是否打开
|
||||||
|
visible: boolean;
|
||||||
|
// 修改回显的数据
|
||||||
|
data?: Users | null;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'done'): void;
|
||||||
|
(e: 'update:visible', visible: boolean): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 提交状态
|
||||||
|
const loading = ref(false);
|
||||||
|
// 是否显示最大化切换按钮
|
||||||
|
const maxable = ref(true);
|
||||||
|
// 表格选中数据
|
||||||
|
const formRef = ref<FormInstance | null>(null);
|
||||||
|
const images = ref<ItemType[]>([]);
|
||||||
|
|
||||||
|
// 用户信息
|
||||||
|
const form = reactive<Users>({
|
||||||
|
userId: undefined,
|
||||||
|
openid: undefined,
|
||||||
|
sessionKey: undefined,
|
||||||
|
username: undefined,
|
||||||
|
avatarUrl: undefined,
|
||||||
|
sex: undefined,
|
||||||
|
country: undefined,
|
||||||
|
province: undefined,
|
||||||
|
city: undefined,
|
||||||
|
region: undefined,
|
||||||
|
phone: undefined,
|
||||||
|
email: undefined,
|
||||||
|
emailVerified: undefined,
|
||||||
|
points: undefined,
|
||||||
|
balance: undefined,
|
||||||
|
addTime: undefined,
|
||||||
|
idCard: undefined,
|
||||||
|
realName: undefined,
|
||||||
|
isAdmin: undefined,
|
||||||
|
clientId: undefined,
|
||||||
|
platform: undefined,
|
||||||
|
sortNumber: undefined,
|
||||||
|
comments: undefined,
|
||||||
|
status: undefined,
|
||||||
|
deleted: undefined,
|
||||||
|
tenantId: undefined,
|
||||||
|
createTime: undefined
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 更新visible */
|
||||||
|
const updateVisible = (value: boolean) => {
|
||||||
|
emit('update:visible', value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单验证规则
|
||||||
|
const rules = reactive({
|
||||||
|
userName: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
type: 'string',
|
||||||
|
message: '请填写用户名称',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const chooseImage = (data: FileRecord) => {
|
||||||
|
images.value.push({
|
||||||
|
uid: data.id,
|
||||||
|
url: data.path,
|
||||||
|
status: 'done'
|
||||||
|
});
|
||||||
|
form.avatarUrl = data.path;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteItem = (index: number) => {
|
||||||
|
images.value.splice(index, 1);
|
||||||
|
form.avatarUrl = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const { resetFields } = useForm(form, rules);
|
||||||
|
|
||||||
|
/* 保存编辑 */
|
||||||
|
const save = () => {
|
||||||
|
if (!formRef.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
formRef.value
|
||||||
|
.validate()
|
||||||
|
.then(() => {
|
||||||
|
loading.value = true;
|
||||||
|
const formData = {
|
||||||
|
...form
|
||||||
|
};
|
||||||
|
const saveOrUpdate = isUpdate.value ? updateUsers : addUsers;
|
||||||
|
saveOrUpdate(formData)
|
||||||
|
.then((msg) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.success(msg);
|
||||||
|
updateVisible(false);
|
||||||
|
emit('done');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
loading.value = false;
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.visible,
|
||||||
|
(visible) => {
|
||||||
|
if (visible) {
|
||||||
|
images.value = [];
|
||||||
|
if (props.data) {
|
||||||
|
assignObject(form, props.data);
|
||||||
|
if (props.data.avatarUrl) {
|
||||||
|
images.value.push({
|
||||||
|
uid: uuid(),
|
||||||
|
url: props.data.avatarUrl,
|
||||||
|
status: 'done'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
isUpdate.value = true;
|
||||||
|
} else {
|
||||||
|
isUpdate.value = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resetFields();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
303
src/views/shop/users/index.vue
Normal file
303
src/views/shop/users/index.vue
Normal file
@@ -0,0 +1,303 @@
|
|||||||
|
<template>
|
||||||
|
<div class="page">
|
||||||
|
<div class="ele-body">
|
||||||
|
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||||
|
<ele-pro-table
|
||||||
|
ref="tableRef"
|
||||||
|
row-key="userId"
|
||||||
|
:columns="columns"
|
||||||
|
:datasource="datasource"
|
||||||
|
:customRow="customRow"
|
||||||
|
tool-class="ele-toolbar-form"
|
||||||
|
class="sys-org-table"
|
||||||
|
>
|
||||||
|
<template #toolbar>
|
||||||
|
<search
|
||||||
|
@search="reload"
|
||||||
|
:selection="selection"
|
||||||
|
@add="openEdit"
|
||||||
|
@remove="removeBatch"
|
||||||
|
@batchMove="openMove"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'avatarUrl'">
|
||||||
|
<a-avatar
|
||||||
|
:size="36"
|
||||||
|
:src="`${record.avatarUrl}`"
|
||||||
|
style="margin-right: 4px"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<UserOutlined />
|
||||||
|
</template>
|
||||||
|
</a-avatar>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'status'">
|
||||||
|
<a-tag v-if="record.status === 1" color="green">启用</a-tag>
|
||||||
|
<a-tag v-if="record.status === 2" color="red">禁用</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-if="column.key === 'action'">
|
||||||
|
<a-space>
|
||||||
|
<a>积分充值</a>
|
||||||
|
<a-divider type="vertical" />
|
||||||
|
<a>分配特殊卡</a>
|
||||||
|
<!-- <a-popconfirm-->
|
||||||
|
<!-- title="确定要删除此记录吗?"-->
|
||||||
|
<!-- @confirm="remove(record)"-->
|
||||||
|
<!-- >-->
|
||||||
|
<!-- <a class="ele-text-danger">删除</a>-->
|
||||||
|
<!-- </a-popconfirm>-->
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</ele-pro-table>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<!-- 编辑弹窗 -->
|
||||||
|
<UserEdit v-model:visible="showEdit" :data="current" @done="reload" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { createVNode, ref } from 'vue';
|
||||||
|
import { message, Modal } from 'ant-design-vue';
|
||||||
|
import {
|
||||||
|
ExclamationCircleOutlined,
|
||||||
|
UserOutlined
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
|
import type { EleProTable } from 'ele-admin-pro';
|
||||||
|
import { toDateString } from 'ele-admin-pro';
|
||||||
|
import type {
|
||||||
|
DatasourceFunction,
|
||||||
|
ColumnItem
|
||||||
|
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||||
|
import Search from './components/search.vue';
|
||||||
|
import UserEdit from './components/userEdit.vue';
|
||||||
|
import { pageUsers, removeBatchUsers, removeUsers } from '@/api/shop/users';
|
||||||
|
import type { Users, UsersParam } from '@/api/shop/users/model';
|
||||||
|
|
||||||
|
// 表格实例
|
||||||
|
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||||
|
|
||||||
|
// 表格选中数据
|
||||||
|
const selection = ref<Users[]>([]);
|
||||||
|
// 当前编辑数据
|
||||||
|
const current = ref<Users | null>(null);
|
||||||
|
// 是否显示编辑弹窗
|
||||||
|
const showEdit = ref(false);
|
||||||
|
// 是否显示批量移动弹窗
|
||||||
|
const showMove = ref(false);
|
||||||
|
// 加载状态
|
||||||
|
const loading = ref(true);
|
||||||
|
|
||||||
|
// 表格数据源
|
||||||
|
const datasource: DatasourceFunction = ({
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
where,
|
||||||
|
orders,
|
||||||
|
filters
|
||||||
|
}) => {
|
||||||
|
if (filters) {
|
||||||
|
where.status = filters.status;
|
||||||
|
}
|
||||||
|
return pageUsers({
|
||||||
|
...where,
|
||||||
|
...orders,
|
||||||
|
page,
|
||||||
|
limit
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格列配置
|
||||||
|
const columns = ref<ColumnItem[]>([
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
dataIndex: 'userId',
|
||||||
|
key: 'userId',
|
||||||
|
width: 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '头像',
|
||||||
|
dataIndex: 'avatarUrl',
|
||||||
|
key: 'avatarUrl',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户名',
|
||||||
|
dataIndex: 'username',
|
||||||
|
key: 'username',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '手机号码',
|
||||||
|
dataIndex: 'phone',
|
||||||
|
key: 'phone',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '性别',
|
||||||
|
dataIndex: 'sexName',
|
||||||
|
key: 'sexName',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '国家',
|
||||||
|
dataIndex: 'country',
|
||||||
|
key: 'country',
|
||||||
|
align: 'center',
|
||||||
|
hideInTable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '省份',
|
||||||
|
dataIndex: 'province',
|
||||||
|
key: 'province',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '城市',
|
||||||
|
dataIndex: 'city',
|
||||||
|
key: 'city',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '所在辖区',
|
||||||
|
dataIndex: 'region',
|
||||||
|
key: 'region',
|
||||||
|
align: 'center',
|
||||||
|
hideInTable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '邮箱是否验证, 0否, 1是',
|
||||||
|
dataIndex: 'emailVerified',
|
||||||
|
key: 'emailVerified',
|
||||||
|
align: 'center',
|
||||||
|
hideInTable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '积分',
|
||||||
|
dataIndex: 'points',
|
||||||
|
key: 'points',
|
||||||
|
sorter: true,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '余额',
|
||||||
|
dataIndex: 'balance',
|
||||||
|
key: 'balance',
|
||||||
|
sorter: true,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '状态',
|
||||||
|
dataIndex: 'status',
|
||||||
|
key: 'status',
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '注册时间',
|
||||||
|
dataIndex: 'addTime',
|
||||||
|
key: 'addTime',
|
||||||
|
align: 'center',
|
||||||
|
sorter: true,
|
||||||
|
ellipsis: true,
|
||||||
|
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
key: 'action',
|
||||||
|
width: 180,
|
||||||
|
fixed: 'right',
|
||||||
|
align: 'center',
|
||||||
|
hideInSetting: true
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
/* 搜索 */
|
||||||
|
const reload = (where?: UsersParam) => {
|
||||||
|
selection.value = [];
|
||||||
|
tableRef?.value?.reload({ where: where });
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开编辑弹窗 */
|
||||||
|
const openEdit = (row?: Users) => {
|
||||||
|
current.value = row ?? null;
|
||||||
|
showEdit.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打开批量移动弹窗 */
|
||||||
|
const openMove = () => {
|
||||||
|
showMove.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 删除单个 */
|
||||||
|
const remove = (row: Users) => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeUsers(row.userId)
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 批量删除 */
|
||||||
|
const removeBatch = () => {
|
||||||
|
if (!selection.value.length) {
|
||||||
|
message.error('请至少选择一条数据');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: '确定要删除选中的记录吗?',
|
||||||
|
icon: createVNode(ExclamationCircleOutlined),
|
||||||
|
maskClosable: true,
|
||||||
|
onOk: () => {
|
||||||
|
const hide = message.loading('请求中..', 0);
|
||||||
|
removeBatchUsers(selection.value.map((d) => d.userId))
|
||||||
|
.then((msg) => {
|
||||||
|
hide();
|
||||||
|
message.success(msg);
|
||||||
|
reload();
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
hide();
|
||||||
|
message.error(e.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 查询 */
|
||||||
|
const query = () => {
|
||||||
|
loading.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 自定义行属性 */
|
||||||
|
const customRow = (record: Users) => {
|
||||||
|
return {
|
||||||
|
// 行点击事件
|
||||||
|
onClick: () => {
|
||||||
|
// console.log(record);
|
||||||
|
},
|
||||||
|
// 行双击事件
|
||||||
|
onDblclick: () => {
|
||||||
|
openEdit(record);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
query();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'Users'
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
Reference in New Issue
Block a user