Merge remote-tracking branch 'origin/master'

# Conflicts:
#	.env.development
This commit is contained in:
2024-11-01 18:43:22 +08:00
72 changed files with 5476 additions and 192 deletions
+5 -5
View File
@@ -1,11 +1,11 @@
VITE_APP_NAME=后台管理系统
VITE_SOCKET_URL=wss://server.gxwebsoft.com
#VITE_SERVER_URL=https://server.gxwebsoft.com/api
#VITE_THINK_URL=https://gxtyzx-api.websoft.top/api
VITE_SERVER_URL=https://server.gxwebsoft.com/api
VITE_THINK_URL=https://gxtyzx-api.websoft.top/api
#VITE_API_URL=https://modules.gxwebsoft.com/api
VITE_SERVER_URL=https://server.gxwebsoft.com/api
VITE_API_URL=http://127.0.0.1:9091/api
VITE_THINK_URL=http://127.0.0.1:9099/api
#VITE_SERVER_URL=http://127.0.0.1:30000/api
VITE_API_URL=http://127.0.0.1:9002/api
#VITE_THINK_URL=http://127.0.0.1:9099/api
#/booking/bookingItem
+1 -1
View File
@@ -1,5 +1,5 @@
VITE_APP_NAME=后台管理系统
VITE_SOCKET_URL=wss://server.gxwebsoft.com
VITE_SERVER_URL=https://common-api.websoft.top/api
VITE_SERVER_URL=https://server.gxwebsoft.com/api
VITE_THINK_URL=https://gxtyzx-api.websoft.top/api
VITE_API_URL=https://modules.gxwebsoft.com/api
+106
View File
@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { CmsProductComment, CmsProductCommentParam } from './model';
import { MODULES_API_URL } from '@/config/setting';
/**
* 分页查询产品评论
*/
export async function pageCmsProductComment(params: CmsProductCommentParam) {
const res = await request.get<ApiResult<PageResult<CmsProductComment>>>(
MODULES_API_URL + '/cms/cms-product-comment/page',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询产品评论列表
*/
export async function listCmsProductComment(params?: CmsProductCommentParam) {
const res = await request.get<ApiResult<CmsProductComment[]>>(
MODULES_API_URL + '/cms/cms-product-comment',
{
params
}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加产品评论
*/
export async function addCmsProductComment(data: CmsProductComment) {
const res = await request.post<ApiResult<unknown>>(
MODULES_API_URL + '/cms/cms-product-comment',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改产品评论
*/
export async function updateCmsProductComment(data: CmsProductComment) {
const res = await request.put<ApiResult<unknown>>(
MODULES_API_URL + '/cms/cms-product-comment',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除产品评论
*/
export async function removeCmsProductComment(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/cms/cms-product-comment/' + id
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除产品评论
*/
export async function removeBatchCmsProductComment(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/cms/cms-product-comment/batch',
{
data
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询产品评论
*/
export async function getCmsProductComment(id: number) {
const res = await request.get<ApiResult<CmsProductComment>>(
MODULES_API_URL + '/cms/cms-product-comment/' + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
@@ -0,0 +1,31 @@
import type { PageParam } from '@/api';
/**
* 产品评论
*/
export interface CmsProductComment {
// ID
id?: number;
// 产品ID
productId?: number;
// 用户ID
userId?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 评论内容
comments?: string;
// 状态
status?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 产品评论搜索条件
*/
export interface CmsProductCommentParam extends PageParam {
id?: number;
keywords?: string;
}
+106
View File
@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { CmsProductRecord, CmsProductRecordParam } from './model';
import { MODULES_API_URL } from '@/config/setting';
/**
* 分页查询插件安装明细
*/
export async function pageCmsProductRecord(params: CmsProductRecordParam) {
const res = await request.get<ApiResult<PageResult<CmsProductRecord>>>(
MODULES_API_URL + '/cms/cms-product-record/page',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询插件安装明细列表
*/
export async function listCmsProductRecord(params?: CmsProductRecordParam) {
const res = await request.get<ApiResult<CmsProductRecord[]>>(
MODULES_API_URL + '/cms/cms-product-record',
{
params
}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加插件安装明细
*/
export async function addCmsProductRecord(data: CmsProductRecord) {
const res = await request.post<ApiResult<unknown>>(
MODULES_API_URL + '/cms/cms-product-record',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改插件安装明细
*/
export async function updateCmsProductRecord(data: CmsProductRecord) {
const res = await request.put<ApiResult<unknown>>(
MODULES_API_URL + '/cms/cms-product-record',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除插件安装明细
*/
export async function removeCmsProductRecord(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/cms/cms-product-record/' + id
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除插件安装明细
*/
export async function removeBatchCmsProductRecord(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/cms/cms-product-record/batch',
{
data
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询插件安装明细
*/
export async function getCmsProductRecord(id: number) {
const res = await request.get<ApiResult<CmsProductRecord>>(
MODULES_API_URL + '/cms/cms-product-record/' + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
@@ -0,0 +1,31 @@
import type { PageParam } from '@/api';
/**
* 插件安装明细
*/
export interface CmsProductRecord {
// ID
id?: number;
// 产品ID
productId?: number;
// 用户ID
userId?: number;
// 排序(数字越小越靠前)
sortNumber?: number;
// 备注
comments?: string;
// 状态, 0待处理, 1已完成
status?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 插件安装明细搜索条件
*/
export interface CmsProductRecordParam extends PageParam {
id?: number;
keywords?: string;
}
+1
View File
@@ -49,6 +49,7 @@ export interface Design {
demoUrl?: string;
account?: string;
docUrl?: string;
merchantId?: number;
}
/**
+5
View File
@@ -6,7 +6,12 @@ import type { PageParam } from '@/api';
export interface FormRecord {
formRecordId?: number;
formId?: number;
type?: string;
name?: string;
phone?: string;
age?: number;
extra?: string;
dateTime?: string;
formData?: string;
formObj?: Object;
userId?: number;
+1
View File
@@ -18,6 +18,7 @@ export interface Link {
deleted?: number;
status?: number;
createTime?: number;
merchantId?: number;
}
/**
+2
View File
@@ -42,6 +42,7 @@ export interface Navigation {
label?: string;
value?: number;
style?: string;
merchantId?: number;
}
/**
@@ -52,5 +53,6 @@ export interface NavigationParam {
path?: string;
authority?: string;
parentId?: number;
merchantId?: number;
navigationId?: number;
}
+1
View File
@@ -61,5 +61,6 @@ export interface Config {
kefu1?: string;
email?: string;
loginTitle?: string;
sysName?: string;
sysLogo?: string;
}
+2 -2
View File
@@ -47,9 +47,9 @@ export interface PageParam {
// 搜素关键词
keywords?: string;
// 起始时间
createTimeStart?: number;
createTimeStart?: string;
// 结束时间
createTimeEnd?: number;
createTimeEnd?: string;
timeStart?: number;
timeEnd?: number;
isExpireTime?: number;
+106
View File
@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { ShopMerchant, ShopMerchantParam } from './model';
import { MODULES_API_URL } from '@/config/setting';
/**
* 分页查询商户
*/
export async function pageShopMerchant(params: ShopMerchantParam) {
const res = await request.get<ApiResult<PageResult<ShopMerchant>>>(
MODULES_API_URL + '/shop/shop-merchant/page',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询商户列表
*/
export async function listShopMerchant(params?: ShopMerchantParam) {
const res = await request.get<ApiResult<ShopMerchant[]>>(
MODULES_API_URL + '/shop/shop-merchant',
{
params
}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加商户
*/
export async function addShopMerchant(data: ShopMerchant) {
const res = await request.post<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改商户
*/
export async function updateShopMerchant(data: ShopMerchant) {
const res = await request.put<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除商户
*/
export async function removeShopMerchant(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant/' + id
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除商户
*/
export async function removeBatchShopMerchant(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant/batch',
{
data
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询商户
*/
export async function getShopMerchant(id: number) {
const res = await request.get<ApiResult<ShopMerchant>>(
MODULES_API_URL + '/shop/shop-merchant/' + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
+87
View File
@@ -0,0 +1,87 @@
import type { PageParam } from '@/api';
/**
* 商户
*/
export interface ShopMerchant {
// ID
merchantId?: number;
// 商户名称
merchantName?: string;
// 商户编号
merchantCode?: string;
// 商户类型
type?: number;
// 商户图标
image?: string;
// 商户手机号
phone?: string;
// 商户姓名
realName?: string;
// 店铺类型
shopType?: string;
// 项目分类
itemType?: string;
// 商户分类
category?: string;
// 商户经营分类
merchantCategoryId?: number;
// 商户分类
merchantCategoryTitle?: string;
// 经纬度
lngAndLat?: string;
//
lng?: string;
//
lat?: string;
// 所在省份
province?: string;
// 所在城市
city?: string;
// 所在辖区
region?: string;
// 详细地址
address?: string;
// 手续费
commission?: string;
// 关键字
keywords?: string;
// 资质图片
files?: string;
// 营业时间
businessTime?: string;
// 文章内容
content?: string;
// 每小时价格
price?: string;
// 是否自营
ownStore?: number;
// 是否推荐
recommend?: number;
// 是否需要审核
goodsReview?: number;
// 管理入口
adminUrl?: string;
// 备注
comments?: string;
// 所有人
userId?: number;
// 是否删除, 0否, 1是
deleted?: number;
// 状态
status?: number;
// 排序号
sortNumber?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 商户搜索条件
*/
export interface ShopMerchantParam extends PageParam {
merchantId?: number;
keywords?: string;
}
+106
View File
@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { ShopMerchantAccount, ShopMerchantAccountParam } from './model';
import { MODULES_API_URL } from '@/config/setting';
/**
* 分页查询商户账号
*/
export async function pageShopMerchantAccount(params: ShopMerchantAccountParam) {
const res = await request.get<ApiResult<PageResult<ShopMerchantAccount>>>(
MODULES_API_URL + '/shop/shop-merchant-account/page',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询商户账号列表
*/
export async function listShopMerchantAccount(params?: ShopMerchantAccountParam) {
const res = await request.get<ApiResult<ShopMerchantAccount[]>>(
MODULES_API_URL + '/shop/shop-merchant-account',
{
params
}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加商户账号
*/
export async function addShopMerchantAccount(data: ShopMerchantAccount) {
const res = await request.post<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-account',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改商户账号
*/
export async function updateShopMerchantAccount(data: ShopMerchantAccount) {
const res = await request.put<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-account',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除商户账号
*/
export async function removeShopMerchantAccount(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-account/' + id
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除商户账号
*/
export async function removeBatchShopMerchantAccount(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-account/batch',
{
data
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询商户账号
*/
export async function getShopMerchantAccount(id: number) {
const res = await request.get<ApiResult<ShopMerchantAccount>>(
MODULES_API_URL + '/shop/shop-merchant-account/' + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
@@ -0,0 +1,39 @@
import type { PageParam } from '@/api';
/**
* 商户账号
*/
export interface ShopMerchantAccount {
// ID
id?: number;
// 商户手机号
phone?: string;
// 真实姓名
realName?: string;
// 商户ID
merchantId?: number;
// 角色ID
roleId?: number;
// 角色名称
roleName?: string;
// 用户ID
userId?: number;
// 备注
comments?: string;
// 状态
status?: number;
// 排序号
sortNumber?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 商户账号搜索条件
*/
export interface ShopMerchantAccountParam extends PageParam {
id?: number;
keywords?: string;
}
+106
View File
@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { ShopMerchantApply, ShopMerchantApplyParam } from './model';
import { MODULES_API_URL } from '@/config/setting';
/**
* 分页查询商户入驻申请
*/
export async function pageShopMerchantApply(params: ShopMerchantApplyParam) {
const res = await request.get<ApiResult<PageResult<ShopMerchantApply>>>(
MODULES_API_URL + '/shop/shop-merchant-apply/page',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询商户入驻申请列表
*/
export async function listShopMerchantApply(params?: ShopMerchantApplyParam) {
const res = await request.get<ApiResult<ShopMerchantApply[]>>(
MODULES_API_URL + '/shop/shop-merchant-apply',
{
params
}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加商户入驻申请
*/
export async function addShopMerchantApply(data: ShopMerchantApply) {
const res = await request.post<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-apply',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改商户入驻申请
*/
export async function updateShopMerchantApply(data: ShopMerchantApply) {
const res = await request.put<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-apply',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除商户入驻申请
*/
export async function removeShopMerchantApply(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-apply/' + id
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除商户入驻申请
*/
export async function removeBatchShopMerchantApply(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-apply/batch',
{
data
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询商户入驻申请
*/
export async function getShopMerchantApply(id: number) {
const res = await request.get<ApiResult<ShopMerchantApply>>(
MODULES_API_URL + '/shop/shop-merchant-apply/' + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
@@ -0,0 +1,59 @@
import type { PageParam } from '@/api';
/**
* 商户入驻申请
*/
export interface ShopMerchantApply {
// ID
applyId?: number;
// 商户名称
merchantName?: string;
// 商户图标
image?: string;
// 商户手机号
phone?: string;
// 商户姓名
realName?: string;
// 身份证号码
idCard?: string;
// 店铺类型
shopType?: string;
// 商户分类
category?: string;
// 手续费
commission?: string;
// 关键字
keywords?: string;
// 资质图片
files?: string;
// 所有人
userId?: number;
// 是否自营
ownStore?: number;
// 是否推荐
recommend?: number;
// 是否需要审核
goodsReview?: number;
// 工作负责人
name2?: string;
// 驳回原因
reason?: string;
// 备注
comments?: string;
// 状态
status?: number;
// 排序号
sortNumber?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 商户入驻申请搜索条件
*/
export interface ShopMerchantApplyParam extends PageParam {
applyId?: number;
keywords?: string;
}
+106
View File
@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { ShopMerchantCount, ShopMerchantCountParam } from './model';
import { MODULES_API_URL } from '@/config/setting';
/**
* 分页查询门店销售统计表
*/
export async function pageShopMerchantCount(params: ShopMerchantCountParam) {
const res = await request.get<ApiResult<PageResult<ShopMerchantCount>>>(
MODULES_API_URL + '/shop/shop-merchant-count/page',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询门店销售统计表列表
*/
export async function listShopMerchantCount(params?: ShopMerchantCountParam) {
const res = await request.get<ApiResult<ShopMerchantCount[]>>(
MODULES_API_URL + '/shop/shop-merchant-count',
{
params
}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加门店销售统计表
*/
export async function addShopMerchantCount(data: ShopMerchantCount) {
const res = await request.post<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-count',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改门店销售统计表
*/
export async function updateShopMerchantCount(data: ShopMerchantCount) {
const res = await request.put<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-count',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除门店销售统计表
*/
export async function removeShopMerchantCount(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-count/' + id
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除门店销售统计表
*/
export async function removeBatchShopMerchantCount(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-count/batch',
{
data
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询门店销售统计表
*/
export async function getShopMerchantCount(id: number) {
const res = await request.get<ApiResult<ShopMerchantCount>>(
MODULES_API_URL + '/shop/shop-merchant-count/' + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
@@ -0,0 +1,29 @@
import type { PageParam } from '@/api';
/**
* 门店销售统计表
*/
export interface ShopMerchantCount {
// ID
id?: number;
// 店铺名称
name?: string;
// 店铺说明
comments?: string;
// 状态
status?: number;
// 排序号
sortNumber?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 门店销售统计表搜索条件
*/
export interface ShopMerchantCountParam extends PageParam {
id?: number;
keywords?: string;
}
+106
View File
@@ -0,0 +1,106 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type { ShopMerchantType, ShopMerchantTypeParam } from './model';
import { MODULES_API_URL } from '@/config/setting';
/**
* 分页查询商户类型
*/
export async function pageShopMerchantType(params: ShopMerchantTypeParam) {
const res = await request.get<ApiResult<PageResult<ShopMerchantType>>>(
MODULES_API_URL + '/shop/shop-merchant-type/page',
{
params
}
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 查询商户类型列表
*/
export async function listShopMerchantType(params?: ShopMerchantTypeParam) {
const res = await request.get<ApiResult<ShopMerchantType[]>>(
MODULES_API_URL + '/shop/shop-merchant-type',
{
params
}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 添加商户类型
*/
export async function addShopMerchantType(data: ShopMerchantType) {
const res = await request.post<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-type',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 修改商户类型
*/
export async function updateShopMerchantType(data: ShopMerchantType) {
const res = await request.put<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-type',
data
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 删除商户类型
*/
export async function removeShopMerchantType(id?: number) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-type/' + id
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 批量删除商户类型
*/
export async function removeBatchShopMerchantType(data: (number | undefined)[]) {
const res = await request.delete<ApiResult<unknown>>(
MODULES_API_URL + '/shop/shop-merchant-type/batch',
{
data
}
);
if (res.data.code === 0) {
return res.data.message;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 根据id查询商户类型
*/
export async function getShopMerchantType(id: number) {
const res = await request.get<ApiResult<ShopMerchantType>>(
MODULES_API_URL + '/shop/shop-merchant-type/' + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
@@ -0,0 +1,29 @@
import type { PageParam } from '@/api';
/**
* 商户类型
*/
export interface ShopMerchantType {
// ID
id?: number;
// 店铺类型
name?: string;
// 店铺入驻条件
comments?: string;
// 状态
status?: number;
// 排序号
sortNumber?: number;
// 租户id
tenantId?: number;
// 创建时间
createTime?: string;
}
/**
* 商户类型搜索条件
*/
export interface ShopMerchantTypeParam extends PageParam {
id?: number;
keywords?: string;
}
+2 -2
View File
@@ -5,7 +5,7 @@ import type {
WebsiteField,
WebsiteFieldParam
} from '@/api/cms/website/field/model';
import { SERVER_API_URL } from '@/config/setting';
import { MODULES_API_URL, SERVER_API_URL } from "@/config/setting";
/**
* 分页查询项目参数
@@ -134,7 +134,7 @@ export async function checkExistence(
*/
export async function configWebsiteField(params?: WebsiteFieldParam) {
const res = await request.get<ApiResult<Config>>(
SERVER_API_URL + '/cms/website-field/config',
MODULES_API_URL + '/cms/website-field/config',
{
params
}
@@ -60,4 +60,5 @@ export interface Config {
email?: string;
loginTitle?: string;
sysLogo?: string;
sysName?: string;
}
@@ -27,13 +27,16 @@
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image
v-if="record.image"
:src="record.image"
:preview="false"
:width="45"
/>
<template v-if="column.key === 'merchantName'">
<a-space>
<a-avatar
v-if="record.image"
:src="record.image"
:preview="false"
:width="45"
/>
{{ record.merchantName }}
</a-space>
</template>
<template v-if="column.key === 'shopType'">
<a-tag v-if="record.shopType === 10">企业</a-tag>
@@ -86,12 +89,6 @@
// 表格配置
const columns = ref<ColumnItem[]>([
{
title: 'LOGO',
dataIndex: 'image',
key: 'image',
align: 'center'
},
{
title: '商户名称',
dataIndex: 'merchantName'
@@ -79,7 +79,7 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { listNavigation, pageNavigation } from '@/api/cms/navigation';
import { listNavigation } from '@/api/cms/navigation';
import { EleProTable } from 'ele-admin-pro';
import { toTreeData, eachTreeData } from 'ele-admin-pro/es';
import type {
@@ -88,7 +88,7 @@
EleProTableDone
} from 'ele-admin-pro/es/ele-pro-table/types';
import type { Navigation, NavigationParam } from '@/api/cms/navigation/model';
import type { Menu } from '@/api/system/menu/model';
import { getMerchantId } from '@/utils/common';
const props = defineProps<{
// 弹窗是否打开
@@ -154,6 +154,7 @@
where.bottom = 0;
}
where.isMpWeixin = false;
where.merchantId = getMerchantId();
return listNavigation({ ...where });
};
+10 -8
View File
@@ -68,11 +68,8 @@
<div class="user-profile">
<div class="user-info">
<div class="nickname">
<span class="ele-text-heading">
{{ loginUser.realName || loginUser.nickname }}
</span>
<div class="ele-text-placeholder">
用户ID:<span class="ele-text-secondary">{{
UID:<span class="ele-text-secondary">{{
loginUser.userId
}}</span>
<copy-outlined
@@ -80,6 +77,12 @@
@click="copyText(loginUser.userId)"
/>
</div>
<span class="ele-text-placeholder">
昵称:
<span class="ele-text-secondary">{{
loginUser.nickname
}}</span>
</span>
<div class="role" style="margin-top: 10px">
<template
v-for="(item, index) in loginUser.roles"
@@ -166,7 +169,7 @@
SearchOutlined
} from '@ant-design/icons-vue';
import { storeToRefs } from 'pinia';
import { copyText, openNew, openUrl } from '@/utils/common';
import { copyText, getMerchantId, openNew, openUrl } from '@/utils/common';
import { useThemeStore } from '@/store/modules/theme';
import HeaderNotice from './header-notice.vue';
import PasswordModal from './password-modal.vue';
@@ -331,8 +334,8 @@
}
// 更新商户ID和名称
if (hasRole('merchant') && loginUser.value.merchantId == null) {
listMerchant({ phone: loginUser.value.phone }).then((res) => {
if (!getMerchantId() && loginUser.value.merchantId == null) {
listMerchantAccount({ phone: loginUser.value.phone }).then((res) => {
if (res.length > 0) {
const item = res[0];
authUser({
@@ -342,7 +345,6 @@
});
localStorage.setItem('MerchantId', `${item.merchantId}`);
localStorage.setItem('MerchantName', `${item.merchantName}`);
localStorage.setItem('MerchantLogo', `${item.image}`);
}
});
}
+9 -6
View File
@@ -128,10 +128,16 @@
const themeStore = useThemeStore();
// 租户信息
const { company } = storeToRefs(tenantStore);
// 当前用户信息
const loginUser = computed(() => userStore.info ?? {});
// 菜单数据
const { menus } = storeToRefs(userStore);
// 网站名称
const projectName = company.value?.shortName || 'WEBSOFT';
const projectName = ref<string>('控制台');
// 当前用户信息
// const loginUser = computed(() => userStore.info ?? {});
if (localStorage.getItem('TenantName')) {
projectName.value = `${localStorage.getItem('TenantName')}`;
}
// 网站LOGO
const logoPath =
company.value?.companyLogo || 'https://www.gxwebsoft.com/ws-logo.svg';
@@ -139,9 +145,6 @@
// 是否全屏
const fullscreen = ref(false);
// 菜单数据
const { menus } = storeToRefs(userStore);
// 布局风格
const {
tabs,
+9
View File
@@ -8,11 +8,14 @@ import type { User } from '@/api/system/user/model';
import { TOKEN_STORE_NAME, USER_MENUS } from '@/config/setting';
import { getUserInfo } from '@/api/layout';
import { initialization } from '@/api/system/tenant';
import { Config } from '@/api/system/website/field/model';
import { configWebsiteField } from '@/api/system/website/field';
// import { isExternalLink } from 'ele-admin-pro';
// import { message } from 'ant-design-vue';
const EXTRA_MENUS: any = [];
export interface UserState {
config: Config | null;
info: User | null;
menus: MenuItemType[] | null | undefined;
authorities: (string | undefined)[];
@@ -22,6 +25,7 @@ export interface UserState {
export const useUserStore = defineStore({
id: 'user',
state: (): UserState => ({
config: null,
// 当前登录用户的信息
info: null,
// 当前登录用户的菜单
@@ -37,6 +41,11 @@ export const useUserStore = defineStore({
* 请求用户信息、权限、角色、菜单
*/
async fetchUserInfo() {
this.config = await configWebsiteField({});
// await configWebsiteField({}).then((data) => {
// console.log(data, 'data');
// this.config = data;
// });
const result = await getUserInfo().catch(() => {});
if (!result) {
return {};
+11 -1
View File
@@ -66,9 +66,15 @@ export function openUrl(url: string, params?: any): void {
* @param id 128
* @param d 项目数据
* 拼接规则: {域名}{path}?spm=c.{用户ID}.{租户ID}.{栏目ID}.{商品ID}.{timestamp}&token={token}
* @param onlyUrl
* @return https:///websoft.top/product/detail/128.html?spm=c.5.3057.10005.undefined&token=DDkr1PpE9DouIVMjLEMt9733QsgG7oNV
*/
export function openSpmUrl(path?: string, d?: any, id = 0): void {
export function openSpmUrl(
path?: string,
d?: any,
id = 0,
onlyUrl?: boolean
): any {
// const domain = getSiteDomain();
const domain = localStorage.getItem('Domain');
const spm = ref<string>('');
@@ -104,6 +110,10 @@ export function openSpmUrl(path?: string, d?: any, id = 0): void {
return;
}
if (onlyUrl == true) {
return `https://${domain}${path}${spm.value}`;
}
// TODO 开发环境
if (import.meta.env.DEV) {
console.log('开发环境');
+3 -1
View File
@@ -334,7 +334,9 @@
// 加载栏目数据
if (!navigationList.value) {
listNavigation({}).then((res) => {
listNavigation({
merchantId: getMerchantId()
}).then((res) => {
navigationList.value = toTreeData({
data: res?.map((d) => {
d.value = d.navigationId;
@@ -0,0 +1,204 @@
<!-- 编辑弹窗 -->
<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="产品ID" name="productId">
<a-input
allow-clear
placeholder="请输入产品ID"
v-model:value="form.productId"
/>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="排序(数字越小越靠前)" name="sortNumber">
<a-input-number
:min="0"
:max="9999"
class="ele-fluid"
placeholder="请输入排序号"
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-item label="状态" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</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, uuid } from 'ele-admin-pro';
import { addCmsProductComment, updateCmsProductComment } from '@/api/cms/cmsProductComment';
import { CmsProductComment } from '@/api/cms/cmsProductComment/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';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: CmsProductComment | 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<CmsProductComment>({
id: undefined,
productId: undefined,
userId: undefined,
sortNumber: undefined,
comments: undefined,
status: undefined,
tenantId: undefined,
createTime: undefined,
cmsProductCommentId: undefined,
cmsProductCommentName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
cmsProductCommentName: [
{
required: true,
type: 'string',
message: '请填写产品评论名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
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 ? updateCmsProductComment : addCmsProductComment;
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.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
+245
View File
@@ -0,0 +1,245 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="cmsProductCommentId"
: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 === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<CmsProductCommentEdit 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 } 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 CmsProductCommentEdit from './components/cmsProductCommentEdit.vue';
import { pageCmsProductComment, removeCmsProductComment, removeBatchCmsProductComment } from '@/api/cms/cmsProductComment';
import type { CmsProductComment, CmsProductCommentParam } from '@/api/cms/cmsProductComment/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<CmsProductComment[]>([]);
// 当前编辑数据
const current = ref<CmsProductComment | 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 pageCmsProductComment({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '产品ID',
dataIndex: 'productId',
key: 'productId',
align: 'center',
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '排序(数字越小越靠前)',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '评论内容',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
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?: CmsProductCommentParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsProductComment) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: CmsProductComment) => {
const hide = message.loading('请求中..', 0);
removeCmsProductComment(row.cmsProductCommentId)
.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);
removeBatchCmsProductComment(selection.value.map((d) => d.cmsProductCommentId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: CmsProductComment) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'CmsProductComment'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,204 @@
<!-- 编辑弹窗 -->
<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="产品ID" name="productId">
<a-input
allow-clear
placeholder="请输入产品ID"
v-model:value="form.productId"
/>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="排序(数字越小越靠前)" name="sortNumber">
<a-input-number
:min="0"
:max="9999"
class="ele-fluid"
placeholder="请输入排序号"
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-item label="状态, 0待处理, 1已完成" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</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, uuid } from 'ele-admin-pro';
import { addCmsProductRecord, updateCmsProductRecord } from '@/api/cms/cmsProductRecord';
import { CmsProductRecord } from '@/api/cms/cmsProductRecord/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';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: CmsProductRecord | 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<CmsProductRecord>({
id: undefined,
productId: undefined,
userId: undefined,
sortNumber: undefined,
comments: undefined,
status: undefined,
tenantId: undefined,
createTime: undefined,
cmsProductRecordId: undefined,
cmsProductRecordName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
cmsProductRecordName: [
{
required: true,
type: 'string',
message: '请填写插件安装明细名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
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 ? updateCmsProductRecord : addCmsProductRecord;
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.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
+245
View File
@@ -0,0 +1,245 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="cmsProductRecordId"
: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 === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<CmsProductRecordEdit 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 } 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 CmsProductRecordEdit from './components/cmsProductRecordEdit.vue';
import { pageCmsProductRecord, removeCmsProductRecord, removeBatchCmsProductRecord } from '@/api/cms/cmsProductRecord';
import type { CmsProductRecord, CmsProductRecordParam } from '@/api/cms/cmsProductRecord/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<CmsProductRecord[]>([]);
// 当前编辑数据
const current = ref<CmsProductRecord | 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 pageCmsProductRecord({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '产品ID',
dataIndex: 'productId',
key: 'productId',
align: 'center',
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '排序(数字越小越靠前)',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态, 0待处理, 1已完成',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
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?: CmsProductRecordParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: CmsProductRecord) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: CmsProductRecord) => {
const hide = message.loading('请求中..', 0);
removeCmsProductRecord(row.cmsProductRecordId)
.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);
removeBatchCmsProductRecord(selection.value.map((d) => d.cmsProductRecordId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: CmsProductRecord) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'CmsProductRecord'
};
</script>
<style lang="less" scoped></style>
+2 -2
View File
@@ -98,7 +98,7 @@
import type { Design, DesignParam } from '@/api/cms/design/model';
import { useRouter } from 'vue-router';
import { toTreeData } from 'ele-admin-pro';
import { openUrl } from '@/utils/common';
import { getMerchantId, openUrl } from '@/utils/common';
import { getSiteDomain } from '@/utils/domain';
import { Navigation } from '@/api/cms/navigation/model';
import { listNavigation } from '@/api/cms/navigation';
@@ -275,7 +275,7 @@
loading.value = true;
// 加载栏目数据
if (!navigationList.value) {
listNavigation({}).then((res) => {
listNavigation({ merchantId: getMerchantId() }).then((res) => {
navigationList.value = toTreeData({
data: res?.map((d) => {
d.value = d.navigationId;
@@ -28,28 +28,27 @@
<a-input
allow-clear
:maxlength="100"
placeholder="SiteLogo"
placeholder="SiteName"
v-model:value="form.name"
@pressEnter="save"
/>
</a-form-item>
<a-form-item label="参数名称" name="comments">
<a-input
allow-clear
:maxlength="100"
placeholder="参数名称"
v-model:value="form.comments"
@pressEnter="save"
/>
</a-form-item>
<a-form-item label="配置值" name="value">
<a-textarea
:rows="4"
:maxlength="200"
placeholder="网站名称"
placeholder="华为官网"
v-model:value="form.value"
/>
</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-item label="css样式" name="style">
<a-textarea
:rows="4"
@@ -175,6 +174,7 @@
assignFields(data);
form.value = data.defaultValue;
form.template = data.defaultValue;
form.comments = data.comments;
if (data.type == 1) {
images.value.push({
uid: `${data.id}`,
+10 -3
View File
@@ -124,9 +124,9 @@
// 表格列配置
const columns = ref<any[]>([
{
title: '参数名',
dataIndex: 'comments',
key: 'comments',
title: '参数',
dataIndex: 'name',
key: 'name',
width: 250,
ellipsis: true
},
@@ -136,6 +136,13 @@
key: 'value',
ellipsis: true
},
{
title: '描述',
dataIndex: 'comments',
key: 'comments',
width: 250,
ellipsis: true
},
{
title: '排序',
dataIndex: 'sortNumber',
+92 -11
View File
@@ -1,6 +1,30 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button
danger
type="primary"
class="ele-btn-icon"
:disabled="selection?.length === 0"
@click="removeBatch"
>
<template #icon>
<DeleteOutlined />
</template>
<span>批量删除</span>
</a-button>
<FormSelect
v-model:value="where.formId"
:placeholder="`选择表单名称`"
style="width: 220px"
@change="chooseFormName"
/>
<a-range-picker
v-model:value="dateRange"
@change="search"
value-format="YYYY-MM-DD"
class="ele-fluid"
/>
<a-input-search
allow-clear
placeholder="请输入关键词"
@@ -8,30 +32,28 @@
@pressEnter="search"
@search="search"
/>
<FormSelect
v-model:value="where.formId"
:placeholder="`选择表单名称`"
style="width: 220px"
@change="chooseFormName"
/>
<a-button @click="reset">重置</a-button>
<a-button type="primary" class="ele-btn-icon">
<a-button type="primary" class="ele-btn-icon" @click="handleExport">
<span>导出xls</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { watch } from 'vue';
import { ref, watch } from 'vue';
import useSearch from '@/utils/use-search';
import { FormRecordParam } from '@/api/cms/form-record/model';
import { FormRecord, FormRecordParam } from '@/api/cms/form-record/model';
import { Form } from '@/api/cms/form/model';
import {assignObject} from "ele-admin-pro";
import { toDateString } from 'ele-admin-pro';
import { DeleteOutlined } from '@ant-design/icons-vue';
import { BookingOrder } from '@/api/booking/bookingOrder/model';
import { utils, writeFile } from 'xlsx';
import { message } from 'ant-design-vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
selection?: FormRecord[];
data?: Form;
}>(),
{}
@@ -52,21 +74,80 @@
keywords: undefined
});
// 请求状态
const loading = ref(false);
// 日期范围选择
const dateRange = ref<[string, string]>(['', '']);
const orders = ref<BookingOrder[] | any[]>();
const xlsFileName = ref<string>();
const chooseFormName = (id: number) => {
where.formId = id;
emit('search', where);
};
const search = () => {
const [d1, d2] = dateRange.value ?? [];
xlsFileName.value = `${d1}至${d2}`;
where.createTimeStart = d1 ? d1 + ' 00:00:00' : '';
where.createTimeEnd = d2 ? d2 + ' 23:59:59' : '';
emit('search', where);
};
// 批量删除
const removeBatch = () => {
emit('remove');
};
/* 重置 */
const reset = () => {
resetFields();
dateRange.value = ['', ''];
search();
};
// 导出
const handleExport = async () => {
loading.value = true;
const array: (string | number)[][] = [
['姓名', '电话', '年龄', '类型', '预定信息', '预约日期']
];
orders.value = props.selection?.map((d) => {
array.push([
`${d.name}`,
`${d.phone}`,
`${d.age}`,
`${d.type}`,
`${d.extra}`,
`${d.dateTime}`,
]);
});
const sheetName = `预约记录导出`;
const workbook = {
SheetNames: [sheetName],
Sheets: {}
};
const sheet = utils.aoa_to_sheet(array);
workbook.Sheets[sheetName] = sheet;
// 设置列宽
sheet['!cols'] = [
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 10 },
{ wch: 10 }
];
message.loading('正在导出...');
setTimeout(() => {
writeFile(
workbook,
`${where.createTimeEnd ? xlsFileName.value + '_' : ''}${sheetName}.xlsx`
);
loading.value = false;
}, 2000);
};
watch(
() => props.selection,
() => {}
+39 -14
View File
@@ -8,6 +8,7 @@
:columns="columns"
:datasource="datasource"
:customRow="customRow"
v-model:selection="selection"
tool-class="ele-toolbar-form"
class="sys-org-table"
>
@@ -137,27 +138,51 @@
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
width: 90,
dataIndex: 'formRecordId'
},
{
title: '手机号码',
dataIndex: 'phone',
width: 180,
key: 'phone'
},
// {
// title: 'ID',
// width: 90,
// dataIndex: 'formRecordId'
// },
{
title: '姓名',
dataIndex: 'name',
key: 'name'
},
{
title: '其他数据',
dataIndex: 'component',
key: 'component'
title: '手机号码',
dataIndex: 'phone',
key: 'phone'
},
{
title: '类型',
dataIndex: 'type',
key: 'type'
},
{
title: '年龄',
dataIndex: 'age',
key: 'age'
},
{
title: '本次接种的剂次',
dataIndex: 'extra',
key: 'extra'
},
{
title: '备注信息',
dataIndex: 'comments',
key: 'comments'
},
{
title: '预约时间',
dataIndex: 'dateTime',
key: 'dateTime'
},
// {
// title: '其他数据',
// dataIndex: 'component',
// key: 'component'
// },
// {
// title: '状态',
// dataIndex: 'status',
+29 -34
View File
@@ -21,9 +21,11 @@
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'name'">
<span @click="openPreview('/form/' + record.formId)">{{
record.name
}}</span>
<span
class="cursor-pointer"
@click="openSpmUrl('/form', record, record.formId, true)"
>{{ record.name }}</span
>
</template>
<template v-if="column.key === 'path'">
<span class="ele-text-placeholder">{{ record.path }}</span>
@@ -31,7 +33,7 @@
<template v-if="column.key === 'component'">
<span class="ele-text-placeholder">{{ record.component }}</span>
</template>
<template v-if="column.key === 'formData'"> </template>
<template v-if="column.key === 'formData'"></template>
<template v-if="column.key === 'status'">
<a-badge
v-if="record.status === 0"
@@ -48,15 +50,21 @@
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openUrl('/cms/form-record?id=' + record.formId)"
><SolutionOutlined />表单数据</a
<a @click="openUrl('/cms/form-record?id=' + record.formId)">
<SolutionOutlined />
表单数据</a
>
<a-divider type="vertical" />
<a-popover>
<template #content>
<div class="ele-cell">
<ele-qr-code
:value="`${domain}/form/${record.formId}`"
:value="`${openSpmUrl(
'/form',
record,
record.formId,
true
)}`"
:size="160"
level="M"
:margin="1"
@@ -64,7 +72,10 @@
手机扫一扫
</div>
</template>
<a @click="onShare"><QrcodeOutlined />分享</a>
<a @click="onShare">
<QrcodeOutlined />
分享</a
>
</a-popover>
<a-divider type="vertical" />
<a @click="openEdit(record)">设计</a>
@@ -120,10 +131,11 @@
} from '@/api/cms/form';
import type { Form, FormParam } from '@/api/cms/form/model';
import { useRouter } from 'vue-router';
import { openPreview, openUrl } from '@/utils/common';
import { openPreview, openSpmUrl, openUrl } from '@/utils/common';
import { useTenantStore } from '@/store/modules/tenant';
import { storeToRefs } from 'pinia';
import { getSiteInfo } from '@/api/layout';
const { push } = useRouter();
const { currentRoute } = useRouter();
// 表格实例
@@ -135,19 +147,16 @@
const current = ref<Form | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// 二维码
const showQrCode = ref(false);
// 加载状态
const loading = ref(true);
// 网站域名
const domain = ref('');
const domain = ref(localStorage.getItem('Domain'));
getSiteInfo().then((data) => {
// tenantId.value = data.tenantId;
domain.value = String(data.domain);
});
// getSiteInfo().then((data) => {
// domain.value = String(data.domain);
// });
// 表格数据源
const datasource: DatasourceFunction = ({
@@ -225,22 +234,6 @@
});
};
const onOpen = (e) => {
console.log(e);
};
const openForm = (row?: Form) => {
push({
path: '/cms/form/detail',
query: { id: row?.formId }
});
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: Form) => {
const hide = message.loading('请求中..', 0);
@@ -298,8 +291,8 @@
},
// 行双击事件
onDblclick: () => {
openUrl('/cms/form-record?id=' + record.formId);
// openEdit(record);
// openUrl('/cms/form-record?id=' + record.formId);
openEdit(record);
}
};
};
@@ -329,6 +322,7 @@
padding: 0 4px;
margin-bottom: 0;
}
.design-item {
margin: auto;
display: flex;
@@ -341,6 +335,7 @@
border-radius: 70px;
background: url('data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20version%3D%221.1%22%3E%3Cdefs%3E%3ClinearGradient%20id%3D%221%22%20x1%3D%220%22%20x2%3D%221%22%20y1%3D%220%22%20y2%3D%220%22%20gradientTransform%3D%22matrix(6.123233995736766e-17%2C%201%2C%20-0.024693877551020406%2C%206.123233995736766e-17%2C%200.5%2C%200)%22%3E%3Cstop%20stop-color%3D%22%230a060d%22%20stop-opacity%3D%221%22%20offset%3D%220%22%3E%3C%2Fstop%3E%3Cstop%20stop-color%3D%22%23660061%22%20stop-opacity%3D%221%22%20offset%3D%220.95%22%3E%3C%2Fstop%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Crect%20width%3D%22100%25%22%20height%3D%22100%25%22%20fill%3D%22url(%231)%22%3E%3C%2Frect%3E%3C%2Fsvg%3E');
}
.ele-cell {
display: flex;
flex-direction: column;
+3 -1
View File
@@ -103,7 +103,7 @@
import type { Link } from '@/api/cms/link/model';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import { uploadFile } from '@/api/system/file';
import { getDictionaryOptions } from '@/utils/common';
import { getDictionaryOptions, getMerchantId } from "@/utils/common";
import { FileRecord } from '@/api/system/file/model';
import { Navigation } from '@/api/cms/navigation/model';
@@ -143,6 +143,7 @@
sortNumber: 100,
linkType: undefined,
categoryId: undefined,
merchantId: undefined,
comments: undefined
});
@@ -226,6 +227,7 @@
.then(() => {
loading.value = true;
const saveOrUpdate = isUpdate.value ? updateLink : addLink;
form.merchantId = getMerchantId();
saveOrUpdate(form)
.then((msg) => {
loading.value = false;
+3 -2
View File
@@ -81,7 +81,7 @@
import { pageLink, removeLink } from '@/api/cms/link';
import { toTreeData } from 'ele-admin-pro';
import type { Link, LinkParam } from '@/api/cms/link/model';
import { openSpmUrl, openUrl } from '@/utils/common';
import { getMerchantId, openSpmUrl, openUrl } from '@/utils/common';
import LinkSearch from './components/link-search.vue';
import { listNavigation } from '@/api/cms/navigation';
import { Navigation } from '@/api/cms/navigation/model';
@@ -146,6 +146,7 @@
// 表格数据源
const datasource: DatasourceFunction = ({ page, limit, where, orders }) => {
where.merchantId = getMerchantId();
return pageLink({ ...where, ...orders, limit, page });
};
@@ -163,7 +164,7 @@
// 加载栏目数据
if (!navigationList.value) {
listNavigation({}).then((res) => {
listNavigation({ merchantId: getMerchantId() }).then((res) => {
navigationList.value = toTreeData({
data: res?.map((d) => {
d.value = d.navigationId;
@@ -166,7 +166,7 @@ import TinymceEditor from "@/components/TinymceEditor/index.vue";
import useFormData from "@/utils/use-form-data";
import {removeSiteInfoCache} from "@/api/cms/website";
import {FileRecord} from "@/api/system/file/model";
import { openSpmUrl } from "@/utils/common";
import { getMerchantId, openSpmUrl } from "@/utils/common";
// 是否是修改
const isUpdate = ref(false);
@@ -224,8 +224,8 @@ const { form, resetFields, assignFields } = useFormData<Design>({
buyUrl: '',
demoUrl: '',
account: '',
docUrl: ''
docUrl: '',
merchantId: undefined
});
const editorRef = ref<InstanceType<typeof TinymceEditor> | null>(null);
@@ -443,6 +443,7 @@ const save = () => {
...form,
layout: JSON.stringify(form),
categoryId: props.categoryId,
merchantId: getMerchantId(),
content: content.value,
};
console.log(formData);
@@ -162,7 +162,7 @@
import { removeSiteInfoCache } from '@/api/cms/website';
import { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
import { FileRecord } from '@/api/system/file/model';
import { uuid } from '@/components/TinymceEditor/util';
import { getMerchantId } from '@/utils/common';
// 是否开启响应式布局
const themeStore = useThemeStore();
@@ -221,7 +221,8 @@
articleCategoryId: 0,
articleId: 0,
pageName: '',
isMpWeixin: false
isMpWeixin: false,
merchantId: undefined
});
// 表单验证规则
@@ -373,7 +374,8 @@
.then(() => {
const navigationForm = {
...form,
parentId: form.parentId || 0
parentId: form.parentId || 0,
merchantId: getMerchantId()
};
const saveOrUpdate = isUpdate.value ? updateNavigation : addNavigation;
saveOrUpdate(navigationForm)
+4 -7
View File
@@ -19,12 +19,7 @@
>
<template #toolbar>
<a-space>
<a-button
v-if="!merchantId"
type="primary"
class="ele-btn-icon"
@click="openEdit()"
>
<a-button type="primary" class="ele-btn-icon" @click="openEdit()">
<template #icon>
<plus-outlined />
</template>
@@ -140,7 +135,7 @@
>
</template>
<template v-else-if="column.key === 'action'">
<a-space v-if="!merchantId">
<a-space>
<a-tooltip :title="`配置SEO及页面内容`">
<a class="text-fuchsia-300" @click="openDesign(record)">设计</a>
</a-tooltip>
@@ -217,6 +212,7 @@
import { Design } from '@/api/cms/design/model';
import { getMerchantId } from '@/utils/merchant';
import { removeSiteInfoCache } from '@/api/cms/website';
import { getMerchant } from "@/api/shop/merchant";
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
@@ -358,6 +354,7 @@
where.bottom = undefined;
}
where.isMpWeixin = false;
where.merchantId = getMerchantId();
return listNavigation({ ...where });
};
+15 -4
View File
@@ -18,9 +18,9 @@
/>
<h4>{{ config.siteName }}</h4>
</div>
<div class="company-name" v-if="config?.loginTitle">{{
config?.loginTitle
}}</div>
<div class="company-name" v-if="config?.loginTitle"
>{{ config?.loginTitle }}
</div>
<a-form
ref="formRef"
:model="form"
@@ -125,7 +125,7 @@
v-model:value="form.phone"
:placeholder="`请输入手机号码`"
>
<template #addonBefore> +86 </template>
<template #addonBefore> +86</template>
</a-input>
</a-form-item>
<a-form-item name="smsCode">
@@ -502,6 +502,7 @@
background: rgba(0, 0, 0, 0.2);
}
}
.company-name {
position: absolute;
top: 17%;
@@ -510,6 +511,7 @@
font-size: 24px;
color: #ffffff;
}
/* 卡片 */
.login-form {
width: 380px;
@@ -526,18 +528,22 @@
padding: 22px 0;
text-align: center;
}
.title-btn {
cursor: pointer;
}
.login-title {
display: flex;
justify-content: space-around;
line-height: 50px;
.active {
color: #007dff;
}
}
}
.login-form-right .login-form {
margin: 0 15% 0 auto;
}
@@ -578,6 +584,7 @@
border-radius: 50%;
cursor: pointer;
}
.work-icon {
width: 50px;
height: 50px;
@@ -637,9 +644,11 @@
transform: translateX(-50%);
}
}
.wwLogin_qrcode_head {
padding: 10px 0 40px 0 !important;
}
.logo-login {
position: absolute;
top: 20px;
@@ -647,11 +656,13 @@
display: flex;
align-items: center;
cursor: pointer;
img {
width: 28px;
height: 28px;
border-radius: 4px;
}
h4 {
margin-left: 6px;
color: #ffffff;
+2 -2
View File
@@ -7,8 +7,8 @@
if (getTokenBySpm()) {
setToken(getTokenBySpm(), true);
localStorage.setItem('TenantId', String(getIdBySpm(5)));
localStorage.setItem('UserId', String(getIdBySpm(1)));
localStorage.setItem('TenantId', String(getIdBySpm(1)));
localStorage.setItem('UserId', String(getIdBySpm(5)));
push('/');
}
</script>
@@ -19,7 +19,7 @@
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="商户图标" name="image">
<a-form-item label="店铺图标" name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
+20 -20
View File
@@ -7,24 +7,24 @@
</template>
<span>添加</span>
</a-button>
<a-button class="ele-btn-icon" @click="openUrl(`/shop/index`)">
<span>店铺管理</span>
</a-button>
<a-button class="ele-btn-icon" @click="openUrl(`/shop/index`)">
<span>门店职员</span>
</a-button>
<a-button class="ele-btn-icon" @click="openUrl(`/goods/category/:id`)">
<span>商品分类</span>
</a-button>
<a-button class="ele-btn-icon" @click="openUrl(`/shop/apply`)">
<span>入驻申请</span>
</a-button>
<a-button class="ele-btn-icon" @click="openUrl(`/shop/desk`)">
<span>桌号管理</span>
</a-button>
<a-button class="ele-btn-icon" @click="openUrl(`/shop/type`)">
<span>店铺类型</span>
</a-button>
<!-- <a-button class="ele-btn-icon" @click="openUrl(`/shop/index`)">-->
<!-- <span>店铺管理</span>-->
<!-- </a-button>-->
<!-- <a-button class="ele-btn-icon" @click="openUrl(`/shop/index`)">-->
<!-- <span>门店职员</span>-->
<!-- </a-button>-->
<!-- <a-button class="ele-btn-icon" @click="openUrl(`/goods/category/:id`)">-->
<!-- <span>商品分类</span>-->
<!-- </a-button>-->
<!-- <a-button class="ele-btn-icon" @click="openUrl(`/shop/apply`)">-->
<!-- <span>入驻申请</span>-->
<!-- </a-button>-->
<!-- <a-button class="ele-btn-icon" @click="openUrl(`/shop/desk`)">-->
<!-- <span>桌号管理</span>-->
<!-- </a-button>-->
<!-- <a-button class="ele-btn-icon" @click="openUrl(`/shop/type`)">-->
<!-- <span>店铺类型</span>-->
<!-- </a-button>-->
</a-space>
</template>
@@ -35,8 +35,8 @@
import { openUrl } from '@/utils/common';
import router from '@/router';
import { getMerchant } from '@/api/shop/merchant';
import merchant from "@/views/shop/merchant/index.vue";
import { getMerchantId } from "@/utils/merchant";
import merchant from '@/views/shop/merchant/index.vue';
import { getMerchantId } from '@/utils/merchant';
const props = withDefaults(
defineProps<{
+2 -2
View File
@@ -127,13 +127,13 @@
align: 'center'
},
{
title: '商户姓名',
title: '姓名',
dataIndex: 'realName',
key: 'realName',
align: 'center'
},
{
title: '商户手机号',
title: '登录账号',
dataIndex: 'phone',
key: 'phone',
align: 'center'
@@ -4,7 +4,7 @@
:width="600"
:visible="visible"
:maskClosable="false"
:title="isUpdate ? '编辑商户职员' : '添加商户职员'"
:title="isUpdate ? '编辑账号' : '添加账号'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
@@ -18,30 +18,34 @@
styleResponsive ? { md: 19, sm: 19, xs: 24 } : { flex: '1' }
"
>
<a-form-item label="职员名称" name="realName">
<a-form-item label="选择商户" name="merchantId">
<SelectMerchant
:placeholder="`选择商户`"
v-model:value="form.merchantName"
@done="chooseMerchantId"
/>
</a-form-item>
<a-form-item label="选择用户" name="userId">
<SelectUser
:placeholder="`选择用户`"
v-model:value="form.phone"
@done="chooseUserId"
/>
</a-form-item>
<a-form-item label="选择角色" name="roleId">
<SelectRole
:placeholder="`选择角色`"
v-model:value="form.roleName"
@done="chooseRoleId"
/>
</a-form-item>
<a-form-item label="真实名称" name="realName">
<a-input
allow-clear
placeholder="请输入真实姓名"
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="登录账号" name="phone">
<a-input
allow-clear
placeholder="请输入手机号码"
:maxlength="11"
:disabled="isUpdate && form.phone"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="密码" name="password" v-if="!isUpdate">
<a-input-password
allow-clear
placeholder="请输入登录密码"
:disabled="isUpdate"
v-model:value="form.password"
/>
</a-form-item>
<a-form-item label="备注" name="comments">
<a-textarea
:rows="4"
@@ -74,6 +78,9 @@
getRoleIdByMerchant,
getRoleNameByMerchant
} from '@/utils/merchant';
import { User } from '@/api/system/user/model';
import { Role } from '@/api/system/role/model';
import { Merchant } from '@/api/shop/merchant/model';
// 是否是修改
const isUpdate = ref(false);
@@ -191,6 +198,22 @@
]
});
const chooseUserId = (user: User) => {
form.userId = user.userId;
form.realName = user.realName;
form.phone = user.phone;
};
const chooseMerchantId = (data: Merchant) => {
form.merchantId = data.merchantId;
form.merchantName = data.merchantName;
};
const chooseRoleId = (data: Role) => {
form.roleId = data.roleId;
form.roleName = data.roleName;
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
@@ -203,12 +226,12 @@
.then(() => {
loading.value = true;
const formData = {
...form,
merchantId: getMerchantId(),
merchantName: getMerchantName(),
merchantAvatar: getMerchantAvatar(),
roleId: getRoleIdByMerchant(),
roleName: getRoleNameByMerchant()
...form
// merchantId: getMerchantId(),
// merchantName: getMerchantName(),
// merchantAvatar: getMerchantAvatar(),
// roleId: getRoleIdByMerchant(),
// roleName: getRoleNameByMerchant()
};
const saveOrUpdate = isUpdate.value
? updateMerchantAccount
+2 -5
View File
@@ -30,10 +30,7 @@
</template>
<template v-if="column.key === 'action'">
<a-space>
<a-popconfirm
title="确定要移除该门店用户吗?"
@confirm="remove(record)"
>
<a-popconfirm title="确定要移除吗?" @confirm="remove(record)">
<a class="ele-text-danger">移除</a>
</a-popconfirm>
</a-space>
@@ -122,7 +119,7 @@
width: 90
},
{
title: '门店名称',
title: '店铺名称',
dataIndex: 'merchantName',
key: 'merchantName',
align: 'center'
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,427 @@
<!-- 编辑弹窗 -->
<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="商户名称" name="merchantName">
<a-input
allow-clear
placeholder="请输入商户名称"
v-model:value="form.merchantName"
/>
</a-form-item>
<a-form-item label="商户编号" name="merchantCode">
<a-input
allow-clear
placeholder="请输入商户编号"
v-model:value="form.merchantCode"
/>
</a-form-item>
<a-form-item label="商户类型" name="type">
<a-input
allow-clear
placeholder="请输入商户类型"
v-model:value="form.type"
/>
</a-form-item>
<a-form-item
label="商户图标"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="商户手机号" name="phone">
<a-input
allow-clear
placeholder="请输入商户手机号"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="商户姓名" name="realName">
<a-input
allow-clear
placeholder="请输入商户姓名"
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="店铺类型" name="shopType">
<a-input
allow-clear
placeholder="请输入店铺类型"
v-model:value="form.shopType"
/>
</a-form-item>
<a-form-item label="项目分类" name="itemType">
<a-input
allow-clear
placeholder="请输入项目分类"
v-model:value="form.itemType"
/>
</a-form-item>
<a-form-item label="商户分类" name="category">
<a-input
allow-clear
placeholder="请输入商户分类"
v-model:value="form.category"
/>
</a-form-item>
<a-form-item label="商户经营分类" name="merchantCategoryId">
<a-input
allow-clear
placeholder="请输入商户经营分类"
v-model:value="form.merchantCategoryId"
/>
</a-form-item>
<a-form-item label="商户分类" name="merchantCategoryTitle">
<a-input
allow-clear
placeholder="请输入商户分类"
v-model:value="form.merchantCategoryTitle"
/>
</a-form-item>
<a-form-item label="经纬度" name="lngAndLat">
<a-input
allow-clear
placeholder="请输入经纬度"
v-model:value="form.lngAndLat"
/>
</a-form-item>
<a-form-item label="" name="lng">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.lng"
/>
</a-form-item>
<a-form-item label="" name="lat">
<a-input
allow-clear
placeholder="请输入"
v-model:value="form.lat"
/>
</a-form-item>
<a-form-item label="所在省份" name="province">
<a-input
allow-clear
placeholder="请输入所在省份"
v-model:value="form.province"
/>
</a-form-item>
<a-form-item label="所在城市" name="city">
<a-input
allow-clear
placeholder="请输入所在城市"
v-model:value="form.city"
/>
</a-form-item>
<a-form-item label="所在辖区" name="region">
<a-input
allow-clear
placeholder="请输入所在辖区"
v-model:value="form.region"
/>
</a-form-item>
<a-form-item label="详细地址" name="address">
<a-input
allow-clear
placeholder="请输入详细地址"
v-model:value="form.address"
/>
</a-form-item>
<a-form-item label="手续费" name="commission">
<a-input
allow-clear
placeholder="请输入手续费"
v-model:value="form.commission"
/>
</a-form-item>
<a-form-item label="关键字" name="keywords">
<a-input
allow-clear
placeholder="请输入关键字"
v-model:value="form.keywords"
/>
</a-form-item>
<a-form-item label="资质图片" name="files">
<a-input
allow-clear
placeholder="请输入资质图片"
v-model:value="form.files"
/>
</a-form-item>
<a-form-item label="营业时间" name="businessTime">
<a-input
allow-clear
placeholder="请输入营业时间"
v-model:value="form.businessTime"
/>
</a-form-item>
<a-form-item label="文章内容" name="content">
<a-input
allow-clear
placeholder="请输入文章内容"
v-model:value="form.content"
/>
</a-form-item>
<a-form-item label="每小时价格" name="price">
<a-input
allow-clear
placeholder="请输入每小时价格"
v-model:value="form.price"
/>
</a-form-item>
<a-form-item label="是否自营" name="ownStore">
<a-input
allow-clear
placeholder="请输入是否自营"
v-model:value="form.ownStore"
/>
</a-form-item>
<a-form-item label="是否推荐" name="recommend">
<a-input
allow-clear
placeholder="请输入是否推荐"
v-model:value="form.recommend"
/>
</a-form-item>
<a-form-item label="是否需要审核" name="goodsReview">
<a-input
allow-clear
placeholder="请输入是否需要审核"
v-model:value="form.goodsReview"
/>
</a-form-item>
<a-form-item label="管理入口" name="adminUrl">
<a-input
allow-clear
placeholder="请输入管理入口"
v-model:value="form.adminUrl"
/>
</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-item label="所有人" name="userId">
<a-input
allow-clear
placeholder="请输入所有人"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="是否删除, 0否, 1是" name="deleted">
<a-input
allow-clear
placeholder="请输入是否删除, 0否, 1是"
v-model:value="form.deleted"
/>
</a-form-item>
<a-form-item label="状态" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="排序号" name="sortNumber">
<a-input-number
:min="0"
:max="9999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</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, uuid } from 'ele-admin-pro';
import { addShopMerchant, updateShopMerchant } from '@/api/shop/shopMerchant';
import { ShopMerchant } from '@/api/shop/shopMerchant/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';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ShopMerchant | 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<ShopMerchant>({
merchantId: undefined,
merchantName: undefined,
merchantCode: undefined,
type: undefined,
image: undefined,
phone: undefined,
realName: undefined,
shopType: undefined,
itemType: undefined,
category: undefined,
merchantCategoryId: undefined,
merchantCategoryTitle: undefined,
lngAndLat: undefined,
lng: undefined,
lat: undefined,
province: undefined,
city: undefined,
region: undefined,
address: undefined,
commission: undefined,
keywords: undefined,
files: undefined,
businessTime: undefined,
content: undefined,
price: undefined,
ownStore: undefined,
recommend: undefined,
goodsReview: undefined,
adminUrl: undefined,
userId: undefined,
deleted: undefined,
tenantId: undefined,
createTime: undefined,
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopMerchantName: [
{
required: true,
type: 'string',
message: '请填写商户名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
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 ? updateShopMerchant : addShopMerchant;
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.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
+413
View File
@@ -0,0 +1,413 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopMerchantId"
: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 === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopMerchantEdit 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 } 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 ShopMerchantEdit from './components/shopMerchantEdit.vue';
import { pageShopMerchant, removeShopMerchant, removeBatchShopMerchant } from '@/api/shop/shopMerchant';
import type { ShopMerchant, ShopMerchantParam } from '@/api/shop/shopMerchant/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopMerchant[]>([]);
// 当前编辑数据
const current = ref<ShopMerchant | 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 pageShopMerchant({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'merchantId',
key: 'merchantId',
align: 'center',
width: 90,
},
{
title: '商户名称',
dataIndex: 'merchantName',
key: 'merchantName',
align: 'center',
},
{
title: '商户编号',
dataIndex: 'merchantCode',
key: 'merchantCode',
align: 'center',
},
{
title: '商户类型',
dataIndex: 'type',
key: 'type',
align: 'center',
},
{
title: '商户图标',
dataIndex: 'image',
key: 'image',
align: 'center',
},
{
title: '商户手机号',
dataIndex: 'phone',
key: 'phone',
align: 'center',
},
{
title: '商户姓名',
dataIndex: 'realName',
key: 'realName',
align: 'center',
},
{
title: '店铺类型',
dataIndex: 'shopType',
key: 'shopType',
align: 'center',
},
{
title: '项目分类',
dataIndex: 'itemType',
key: 'itemType',
align: 'center',
},
{
title: '商户分类',
dataIndex: 'category',
key: 'category',
align: 'center',
},
{
title: '商户经营分类',
dataIndex: 'merchantCategoryId',
key: 'merchantCategoryId',
align: 'center',
},
{
title: '商户分类',
dataIndex: 'merchantCategoryTitle',
key: 'merchantCategoryTitle',
align: 'center',
},
{
title: '经纬度',
dataIndex: 'lngAndLat',
key: 'lngAndLat',
align: 'center',
},
{
title: '',
dataIndex: 'lng',
key: 'lng',
align: 'center',
},
{
title: '',
dataIndex: 'lat',
key: 'lat',
align: 'center',
},
{
title: '所在省份',
dataIndex: 'province',
key: 'province',
align: 'center',
},
{
title: '所在城市',
dataIndex: 'city',
key: 'city',
align: 'center',
},
{
title: '所在辖区',
dataIndex: 'region',
key: 'region',
align: 'center',
},
{
title: '详细地址',
dataIndex: 'address',
key: 'address',
align: 'center',
},
{
title: '手续费',
dataIndex: 'commission',
key: 'commission',
align: 'center',
},
{
title: '关键字',
dataIndex: 'keywords',
key: 'keywords',
align: 'center',
},
{
title: '资质图片',
dataIndex: 'files',
key: 'files',
align: 'center',
},
{
title: '营业时间',
dataIndex: 'businessTime',
key: 'businessTime',
align: 'center',
},
{
title: '文章内容',
dataIndex: 'content',
key: 'content',
align: 'center',
},
{
title: '每小时价格',
dataIndex: 'price',
key: 'price',
align: 'center',
},
{
title: '是否自营',
dataIndex: 'ownStore',
key: 'ownStore',
align: 'center',
},
{
title: '是否推荐',
dataIndex: 'recommend',
key: 'recommend',
align: 'center',
},
{
title: '是否需要审核',
dataIndex: 'goodsReview',
key: 'goodsReview',
align: 'center',
},
{
title: '管理入口',
dataIndex: 'adminUrl',
key: 'adminUrl',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '所有人',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '是否删除, 0否, 1是',
dataIndex: 'deleted',
key: 'deleted',
align: 'center',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
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?: ShopMerchantParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopMerchant) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopMerchant) => {
const hide = message.loading('请求中..', 0);
removeShopMerchant(row.shopMerchantId)
.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);
removeBatchShopMerchant(selection.value.map((d) => d.shopMerchantId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopMerchant) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopMerchant'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,236 @@
<!-- 编辑弹窗 -->
<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="商户手机号" name="phone">
<a-input
allow-clear
placeholder="请输入商户手机号"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="真实姓名" name="realName">
<a-input
allow-clear
placeholder="请输入真实姓名"
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="商户ID" name="merchantId">
<a-input
allow-clear
placeholder="请输入商户ID"
v-model:value="form.merchantId"
/>
</a-form-item>
<a-form-item label="角色ID" name="roleId">
<a-input
allow-clear
placeholder="请输入角色ID"
v-model:value="form.roleId"
/>
</a-form-item>
<a-form-item label="角色名称" name="roleName">
<a-input
allow-clear
placeholder="请输入角色名称"
v-model:value="form.roleName"
/>
</a-form-item>
<a-form-item label="用户ID" name="userId">
<a-input
allow-clear
placeholder="请输入用户ID"
v-model:value="form.userId"
/>
</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-item label="状态" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="排序号" name="sortNumber">
<a-input-number
:min="0"
:max="9999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</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, uuid } from 'ele-admin-pro';
import { addShopMerchantAccount, updateShopMerchantAccount } from '@/api/shop/shopMerchantAccount';
import { ShopMerchantAccount } from '@/api/shop/shopMerchantAccount/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';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ShopMerchantAccount | 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<ShopMerchantAccount>({
id: undefined,
phone: undefined,
realName: undefined,
merchantId: undefined,
roleId: undefined,
roleName: undefined,
userId: undefined,
comments: undefined,
status: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
shopMerchantAccountId: undefined,
shopMerchantAccountName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopMerchantAccountName: [
{
required: true,
type: 'string',
message: '请填写商户账号名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
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 ? updateShopMerchantAccount : addShopMerchantAccount;
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.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
@@ -0,0 +1,269 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopMerchantAccountId"
: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 === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopMerchantAccountEdit 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 } 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 ShopMerchantAccountEdit from './components/shopMerchantAccountEdit.vue';
import { pageShopMerchantAccount, removeShopMerchantAccount, removeBatchShopMerchantAccount } from '@/api/shop/shopMerchantAccount';
import type { ShopMerchantAccount, ShopMerchantAccountParam } from '@/api/shop/shopMerchantAccount/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopMerchantAccount[]>([]);
// 当前编辑数据
const current = ref<ShopMerchantAccount | 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 pageShopMerchantAccount({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '商户手机号',
dataIndex: 'phone',
key: 'phone',
align: 'center',
},
{
title: '真实姓名',
dataIndex: 'realName',
key: 'realName',
align: 'center',
},
{
title: '商户ID',
dataIndex: 'merchantId',
key: 'merchantId',
align: 'center',
},
{
title: '角色ID',
dataIndex: 'roleId',
key: 'roleId',
align: 'center',
},
{
title: '角色名称',
dataIndex: 'roleName',
key: 'roleName',
align: 'center',
},
{
title: '用户ID',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
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?: ShopMerchantAccountParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopMerchantAccount) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopMerchantAccount) => {
const hide = message.loading('请求中..', 0);
removeShopMerchantAccount(row.shopMerchantAccountId)
.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);
removeBatchShopMerchantAccount(selection.value.map((d) => d.shopMerchantAccountId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopMerchantAccount) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopMerchantAccount'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,320 @@
<!-- 编辑弹窗 -->
<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="商户名称" name="merchantName">
<a-input
allow-clear
placeholder="请输入商户名称"
v-model:value="form.merchantName"
/>
</a-form-item>
<a-form-item
label="商户图标"
name="image">
<SelectFile
:placeholder="`请选择图片`"
:limit="1"
:data="images"
@done="chooseImage"
@del="onDeleteItem"
/>
</a-form-item>
<a-form-item label="商户手机号" name="phone">
<a-input
allow-clear
placeholder="请输入商户手机号"
v-model:value="form.phone"
/>
</a-form-item>
<a-form-item label="商户姓名" name="realName">
<a-input
allow-clear
placeholder="请输入商户姓名"
v-model:value="form.realName"
/>
</a-form-item>
<a-form-item label="身份证号码" name="idCard">
<a-input
allow-clear
placeholder="请输入身份证号码"
v-model:value="form.idCard"
/>
</a-form-item>
<a-form-item label="店铺类型" name="shopType">
<a-input
allow-clear
placeholder="请输入店铺类型"
v-model:value="form.shopType"
/>
</a-form-item>
<a-form-item label="商户分类" name="category">
<a-input
allow-clear
placeholder="请输入商户分类"
v-model:value="form.category"
/>
</a-form-item>
<a-form-item label="手续费" name="commission">
<a-input
allow-clear
placeholder="请输入手续费"
v-model:value="form.commission"
/>
</a-form-item>
<a-form-item label="关键字" name="keywords">
<a-input
allow-clear
placeholder="请输入关键字"
v-model:value="form.keywords"
/>
</a-form-item>
<a-form-item label="资质图片" name="files">
<a-input
allow-clear
placeholder="请输入资质图片"
v-model:value="form.files"
/>
</a-form-item>
<a-form-item label="所有人" name="userId">
<a-input
allow-clear
placeholder="请输入所有人"
v-model:value="form.userId"
/>
</a-form-item>
<a-form-item label="是否自营" name="ownStore">
<a-input
allow-clear
placeholder="请输入是否自营"
v-model:value="form.ownStore"
/>
</a-form-item>
<a-form-item label="是否推荐" name="recommend">
<a-input
allow-clear
placeholder="请输入是否推荐"
v-model:value="form.recommend"
/>
</a-form-item>
<a-form-item label="是否需要审核" name="goodsReview">
<a-input
allow-clear
placeholder="请输入是否需要审核"
v-model:value="form.goodsReview"
/>
</a-form-item>
<a-form-item label="工作负责人" name="name2">
<a-input
allow-clear
placeholder="请输入工作负责人"
v-model:value="form.name2"
/>
</a-form-item>
<a-form-item label="驳回原因" name="reason">
<a-input
allow-clear
placeholder="请输入驳回原因"
v-model:value="form.reason"
/>
</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-item label="状态" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="排序号" name="sortNumber">
<a-input-number
:min="0"
:max="9999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</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, uuid } from 'ele-admin-pro';
import { addShopMerchantApply, updateShopMerchantApply } from '@/api/shop/shopMerchantApply';
import { ShopMerchantApply } from '@/api/shop/shopMerchantApply/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';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ShopMerchantApply | 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<ShopMerchantApply>({
applyId: undefined,
merchantName: undefined,
image: undefined,
phone: undefined,
realName: undefined,
idCard: undefined,
shopType: undefined,
category: undefined,
commission: undefined,
keywords: undefined,
files: undefined,
userId: undefined,
ownStore: undefined,
recommend: undefined,
goodsReview: undefined,
name2: undefined,
reason: undefined,
comments: undefined,
status: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
shopMerchantApplyId: undefined,
shopMerchantApplyName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopMerchantApplyName: [
{
required: true,
type: 'string',
message: '请填写商户入驻申请名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
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 ? updateShopMerchantApply : addShopMerchantApply;
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.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
+329
View File
@@ -0,0 +1,329 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopMerchantApplyId"
: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 === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopMerchantApplyEdit 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 } 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 ShopMerchantApplyEdit from './components/shopMerchantApplyEdit.vue';
import { pageShopMerchantApply, removeShopMerchantApply, removeBatchShopMerchantApply } from '@/api/shop/shopMerchantApply';
import type { ShopMerchantApply, ShopMerchantApplyParam } from '@/api/shop/shopMerchantApply/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopMerchantApply[]>([]);
// 当前编辑数据
const current = ref<ShopMerchantApply | 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 pageShopMerchantApply({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'applyId',
key: 'applyId',
align: 'center',
width: 90,
},
{
title: '商户名称',
dataIndex: 'merchantName',
key: 'merchantName',
align: 'center',
},
{
title: '商户图标',
dataIndex: 'image',
key: 'image',
align: 'center',
},
{
title: '商户手机号',
dataIndex: 'phone',
key: 'phone',
align: 'center',
},
{
title: '商户姓名',
dataIndex: 'realName',
key: 'realName',
align: 'center',
},
{
title: '身份证号码',
dataIndex: 'idCard',
key: 'idCard',
align: 'center',
},
{
title: '店铺类型',
dataIndex: 'shopType',
key: 'shopType',
align: 'center',
},
{
title: '商户分类',
dataIndex: 'category',
key: 'category',
align: 'center',
},
{
title: '手续费',
dataIndex: 'commission',
key: 'commission',
align: 'center',
},
{
title: '关键字',
dataIndex: 'keywords',
key: 'keywords',
align: 'center',
},
{
title: '资质图片',
dataIndex: 'files',
key: 'files',
align: 'center',
},
{
title: '所有人',
dataIndex: 'userId',
key: 'userId',
align: 'center',
},
{
title: '是否自营',
dataIndex: 'ownStore',
key: 'ownStore',
align: 'center',
},
{
title: '是否推荐',
dataIndex: 'recommend',
key: 'recommend',
align: 'center',
},
{
title: '是否需要审核',
dataIndex: 'goodsReview',
key: 'goodsReview',
align: 'center',
},
{
title: '工作负责人',
dataIndex: 'name2',
key: 'name2',
align: 'center',
},
{
title: '驳回原因',
dataIndex: 'reason',
key: 'reason',
align: 'center',
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
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?: ShopMerchantApplyParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopMerchantApply) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopMerchantApply) => {
const hide = message.loading('请求中..', 0);
removeShopMerchantApply(row.shopMerchantApplyId)
.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);
removeBatchShopMerchantApply(selection.value.map((d) => d.shopMerchantApplyId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopMerchantApply) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopMerchantApply'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,196 @@
<!-- 编辑弹窗 -->
<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="店铺名称" name="name">
<a-input
allow-clear
placeholder="请输入店铺名称"
v-model:value="form.name"
/>
</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-item label="状态" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="排序号" name="sortNumber">
<a-input-number
:min="0"
:max="9999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</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, uuid } from 'ele-admin-pro';
import { addShopMerchantCount, updateShopMerchantCount } from '@/api/shop/shopMerchantCount';
import { ShopMerchantCount } from '@/api/shop/shopMerchantCount/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';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ShopMerchantCount | 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<ShopMerchantCount>({
id: undefined,
name: undefined,
comments: undefined,
status: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
shopMerchantCountId: undefined,
shopMerchantCountName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopMerchantCountName: [
{
required: true,
type: 'string',
message: '请填写门店销售统计表名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
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 ? updateShopMerchantCount : addShopMerchantCount;
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.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
+239
View File
@@ -0,0 +1,239 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopMerchantCountId"
: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 === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopMerchantCountEdit 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 } 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 ShopMerchantCountEdit from './components/shopMerchantCountEdit.vue';
import { pageShopMerchantCount, removeShopMerchantCount, removeBatchShopMerchantCount } from '@/api/shop/shopMerchantCount';
import type { ShopMerchantCount, ShopMerchantCountParam } from '@/api/shop/shopMerchantCount/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopMerchantCount[]>([]);
// 当前编辑数据
const current = ref<ShopMerchantCount | 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 pageShopMerchantCount({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '店铺名称',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '店铺说明',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
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?: ShopMerchantCountParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopMerchantCount) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopMerchantCount) => {
const hide = message.loading('请求中..', 0);
removeShopMerchantCount(row.shopMerchantCountId)
.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);
removeBatchShopMerchantCount(selection.value.map((d) => d.shopMerchantCountId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopMerchantCount) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopMerchantCount'
};
</script>
<style lang="less" scoped></style>
@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>
@@ -0,0 +1,196 @@
<!-- 编辑弹窗 -->
<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="店铺类型" name="name">
<a-input
allow-clear
placeholder="请输入店铺类型"
v-model:value="form.name"
/>
</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-item label="状态" name="status">
<a-radio-group v-model:value="form.status">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item label="排序号" name="sortNumber">
<a-input-number
:min="0"
:max="9999"
class="ele-fluid"
placeholder="请输入排序号"
v-model:value="form.sortNumber"
/>
</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, uuid } from 'ele-admin-pro';
import { addShopMerchantType, updateShopMerchantType } from '@/api/shop/shopMerchantType';
import { ShopMerchantType } from '@/api/shop/shopMerchantType/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';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ShopMerchantType | 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<ShopMerchantType>({
id: undefined,
name: undefined,
comments: undefined,
status: undefined,
sortNumber: undefined,
tenantId: undefined,
createTime: undefined,
shopMerchantTypeId: undefined,
shopMerchantTypeName: '',
status: 0,
comments: '',
sortNumber: 100
});
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
shopMerchantTypeName: [
{
required: true,
type: 'string',
message: '请填写商户类型名称',
trigger: 'blur'
}
]
});
const chooseImage = (data: FileRecord) => {
images.value.push({
uid: data.id,
url: data.path,
status: 'done'
});
form.image = data.path;
};
const onDeleteItem = (index: number) => {
images.value.splice(index, 1);
form.image = '';
};
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 ? updateShopMerchantType : addShopMerchantType;
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.image){
images.value.push({
uid: uuid(),
url: props.data.image,
status: 'done'
})
}
isUpdate.value = true;
} else {
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
</script>
+239
View File
@@ -0,0 +1,239 @@
<template>
<div class="page">
<div class="ele-body">
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="shopMerchantTypeId"
: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 === 'image'">
<a-image :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">显示</a-tag>
<a-tag v-if="record.status === 1" color="red">隐藏</a-tag>
</template>
<template v-if="column.key === 'action'">
<a-space>
<a @click="openEdit(record)">修改</a>
<a-divider type="vertical" />
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<ShopMerchantTypeEdit 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 } 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 ShopMerchantTypeEdit from './components/shopMerchantTypeEdit.vue';
import { pageShopMerchantType, removeShopMerchantType, removeBatchShopMerchantType } from '@/api/shop/shopMerchantType';
import type { ShopMerchantType, ShopMerchantTypeParam } from '@/api/shop/shopMerchantType/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<ShopMerchantType[]>([]);
// 当前编辑数据
const current = ref<ShopMerchantType | 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 pageShopMerchantType({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: 'ID',
dataIndex: 'id',
key: 'id',
align: 'center',
width: 90,
},
{
title: '店铺类型',
dataIndex: 'name',
key: 'name',
align: 'center',
},
{
title: '店铺入驻条件',
dataIndex: 'comments',
key: 'comments',
align: 'center',
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
align: 'center',
},
{
title: '排序号',
dataIndex: 'sortNumber',
key: 'sortNumber',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
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?: ShopMerchantTypeParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: ShopMerchantType) => {
current.value = row ?? null;
showEdit.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: ShopMerchantType) => {
const hide = message.loading('请求中..', 0);
removeShopMerchantType(row.shopMerchantTypeId)
.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);
removeBatchShopMerchantType(selection.value.map((d) => d.shopMerchantTypeId))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: ShopMerchantType) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'ShopMerchantType'
};
</script>
<style lang="less" scoped></style>
+1
View File
@@ -74,6 +74,7 @@
<span class="ele-text-heading">{{ form.createTime }}</span>
</a-form-item>
<a-form-item label="到期时间" v-if="form.version != 30">
<a-tag color="red">已到期</a-tag>
<span class="ele-text-heading">{{ form.expirationTime }}</span>
</a-form-item>
<a-divider style="padding-bottom: 20px" />
+4 -1
View File
@@ -110,7 +110,10 @@
"
style="max-width: 580px; margin-top: 20px"
>
<a-form-item label="登录账号" v-bind="validateInfos.username">
<a-form-item label="用户ID" v-bind="validateInfos.userId">
<a-input disabled v-model:value="form.userId" allow-clear />
</a-form-item>
<a-form-item label="用户名" v-bind="validateInfos.username">
<a-input
disabled
v-model:value="form.username"