Compare commits
47 Commits
8f235ffd91
...
test
| Author | SHA1 | Date | |
|---|---|---|---|
| 647e32567b | |||
| ead5aaf458 | |||
| e2fa92d33d | |||
| f01cbf0f5b | |||
| ea2b9fcf9e | |||
| b87b4c000e | |||
| ddd39ec031 | |||
| 76af0f5a83 | |||
| a5b11cf4f4 | |||
| 782bd19e4e | |||
| 25a8fbbe9f | |||
| 058c8dcadc | |||
| 20de427175 | |||
| 3855ed4b75 | |||
| 60ea128a10 | |||
| 45727d8005 | |||
| c035442628 | |||
| 62c6b755af | |||
| 71bec03475 | |||
| ca182dc325 | |||
| ee3a54abf0 | |||
| 84116bb951 | |||
| 000f715bd8 | |||
| 9991248b08 | |||
| c607155734 | |||
| fdc939b0b7 | |||
| da125b0238 | |||
| 6e66f9138d | |||
| 527cfcdcf8 | |||
| 5d28477db9 | |||
| 92c3a45049 | |||
| 042dacec98 | |||
| ed8be8a16a | |||
| 3b19d58f27 | |||
| c95ab6fda5 | |||
| 084084c008 | |||
| db467815dd | |||
| e61a297d9a | |||
| 348ecdfc54 | |||
| 4c06f07ac6 | |||
| b28fdeaf11 | |||
| 8b3a802092 | |||
| d3aab47dad | |||
| 1516fefb2c | |||
| 98c7908417 | |||
| ce0878c23f | |||
| fb13b0a502 |
@@ -10,6 +10,7 @@ VITE_APP_BASE_API=/dev-api
|
|||||||
# VITE_APP_API_URL=https://cashier.sxczgkj.com/ # 正式
|
# VITE_APP_API_URL=https://cashier.sxczgkj.com/ # 正式
|
||||||
VITE_APP_API_URL=http://192.168.1.42/ # 本地
|
VITE_APP_API_URL=http://192.168.1.42/ # 本地
|
||||||
VITE_APP_API_PHP_URL=http://192.168.1.42:8000 #php抖音美团测试环境
|
VITE_APP_API_PHP_URL=http://192.168.1.42:8000 #php抖音美团测试环境
|
||||||
|
VITE_APP_API_PHP_IMPORT_URL=http://192.168.1.42:8789 #本地php批量导入
|
||||||
|
|
||||||
|
|
||||||
# WebSocket 端点(不配置则关闭),线上 ws://api.youlai.tech/ws ,本地 ws://localhost:8989/ws
|
# WebSocket 端点(不配置则关闭),线上 ws://api.youlai.tech/ws ,本地 ws://localhost:8989/ws
|
||||||
|
|||||||
@@ -67,7 +67,7 @@
|
|||||||
"vue-clipboard3": "^2.0.0",
|
"vue-clipboard3": "^2.0.0",
|
||||||
"vue-i18n": "^11.1.0",
|
"vue-i18n": "^11.1.0",
|
||||||
"vue-router": "^4.5.0",
|
"vue-router": "^4.5.0",
|
||||||
"ysk-utils": "^1.0.77"
|
"ysk-utils": "^1.0.85"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^19.7.1",
|
"@commitlint/cli": "^19.7.1",
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import request from "@/utils/request";
|
import request from "@/utils/request";
|
||||||
import { Account_BaseUrl } from "@/api/config";
|
import { Account_BaseUrl, Order_BaseUrl } from "@/api/config";
|
||||||
const baseURL = Account_BaseUrl + "/admin/shopMerchant";
|
const baseURL = Account_BaseUrl + "/admin/shopMerchant";
|
||||||
|
const orderURL = Order_BaseUrl + "/admin/shopMerchant";
|
||||||
const API = {
|
const API = {
|
||||||
get(shopId: string | number) {
|
get(shopId: string | number) {
|
||||||
return request({
|
return request({
|
||||||
url: `${baseURL}`,
|
url: `${orderURL}`,
|
||||||
method: "get",
|
method: "get",
|
||||||
params: {
|
params: {
|
||||||
shopId: shopId
|
shopId: shopId
|
||||||
@@ -14,7 +15,7 @@ const API = {
|
|||||||
edit(shopId: string | number, data: shopMerchantType) {
|
edit(shopId: string | number, data: shopMerchantType) {
|
||||||
delete data.id
|
delete data.id
|
||||||
return request({
|
return request({
|
||||||
url: `${baseURL}`,
|
url: `${orderURL}`,
|
||||||
method: "put",
|
method: "put",
|
||||||
data: { ...data, shopId },
|
data: { ...data, shopId },
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -71,7 +71,16 @@ const API = {
|
|||||||
method: "get",
|
method: "get",
|
||||||
params
|
params
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
// 导出
|
||||||
|
export(params: any) {
|
||||||
|
return request({
|
||||||
|
url: `${baseURL}/export`,
|
||||||
|
method: "get",
|
||||||
|
params,
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
},
|
||||||
}
|
}
|
||||||
export default API;
|
export default API;
|
||||||
export interface getRequest {
|
export interface getRequest {
|
||||||
|
|||||||
166
src/api/common/index.ts
Normal file
166
src/api/common/index.ts
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
import request from "@/utils/request";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有地域
|
||||||
|
* @param params
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const getRegion = () => {
|
||||||
|
return request<any, any[]>({
|
||||||
|
url: `/system/admin/common/region`,
|
||||||
|
method: "get"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有银行
|
||||||
|
* @param params
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const getBankInfo = (params: Object) => {
|
||||||
|
return request<any, any[]>({
|
||||||
|
url: `/system/admin/common/bankInfo`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类目信息表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const getCategory = () => {
|
||||||
|
return request<any, any[]>({
|
||||||
|
url: `/system/admin/common/category`,
|
||||||
|
method: "get"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
interface getBankBranchListParams {
|
||||||
|
bankAliceCode?: string;
|
||||||
|
cityCode?: string;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取所有支行
|
||||||
|
* @params
|
||||||
|
* bankAliceCode 银行别名code bankAliasCode 从 /system/admin/common/bankInfo 获取
|
||||||
|
* cityCode 市编码 wxProvinceCode 从 /system/admin/common/region 获取
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const getBankBranchList = (params: getBankBranchListParams) => {
|
||||||
|
return request<any, any[]>({
|
||||||
|
url: `/order/admin/data/entryManager/bankBranchList`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请进件
|
||||||
|
* @data Object
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const entryManagerPost = (data: Object) => {
|
||||||
|
return request<any, any[]>({
|
||||||
|
url: `/order/admin/data/entryManager`,
|
||||||
|
method: "post",
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请进件
|
||||||
|
* @data {
|
||||||
|
* url string 图片地址
|
||||||
|
* type string 可选
|
||||||
|
* IdCard 身份证
|
||||||
|
* BankCard 银行卡
|
||||||
|
* BusinessLicense 营业执照
|
||||||
|
* }
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const getInfoByImg = (params: Object) => {
|
||||||
|
return request<any, any[]>({
|
||||||
|
url: `/order/admin/data/entryManager/getInfoByImg`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取进件信息详情
|
||||||
|
* @data { shopId }
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const entryManagerDetail = (params: Object) => {
|
||||||
|
return request<any, any[]>({
|
||||||
|
url: `/order/admin/data/entryManager`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取进件列表
|
||||||
|
* @data { params }
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const entryManagerList = (params: Object) => {
|
||||||
|
return request<any, any[]>({
|
||||||
|
url: `/order/admin/data/entryManager/list`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主动查询进件信息状态
|
||||||
|
* @data { params }
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const queryEntry = (params: Object) => {
|
||||||
|
return request<any, any[]>({
|
||||||
|
url: `/order/admin/data/entryManager/queryEntry`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户支付信息获取
|
||||||
|
* @data { params }
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const shopMerchantGet = (params: Object) => {
|
||||||
|
return request<any, any[]>({
|
||||||
|
url: `/order/admin/shopMerchant`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商户支付信息修改 修改聚合支付信息
|
||||||
|
* @data { params }
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const shopMerchantPut = (data: Object) => {
|
||||||
|
return request<any, any[]>({
|
||||||
|
url: `/order/admin/shopMerchant`,
|
||||||
|
method: "put",
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前店铺的主店进件信息
|
||||||
|
* @data { params }
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const getMainMerchant = (params: Object) => {
|
||||||
|
return request<any, any[]>({
|
||||||
|
url: `/order/admin/shopMerchant/getMainMerchant`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ export function searchstorestatus(type) {
|
|||||||
return request_php({
|
return request_php({
|
||||||
method: "post",
|
method: "post",
|
||||||
headers: {
|
headers: {
|
||||||
clint_type: type
|
'ClintType': type
|
||||||
},
|
},
|
||||||
url: "/meituan/searchstorestatus"
|
url: "/meituan/searchstorestatus"
|
||||||
});
|
});
|
||||||
@@ -79,7 +79,7 @@ export function getuisdk(data) {
|
|||||||
return request_php({
|
return request_php({
|
||||||
method: "post",
|
method: "post",
|
||||||
headers: {
|
headers: {
|
||||||
clint_type: 2
|
'ClintType': 2
|
||||||
},
|
},
|
||||||
url: "/douyin/getuisdk",
|
url: "/douyin/getuisdk",
|
||||||
data,
|
data,
|
||||||
@@ -214,7 +214,7 @@ export function thirdPartyCoupon_bindUrl(data) {
|
|||||||
return request_php({
|
return request_php({
|
||||||
method: "post",
|
method: "post",
|
||||||
headers: {
|
headers: {
|
||||||
clint_type: 1
|
'ClintType': 1
|
||||||
},
|
},
|
||||||
url: "/meituan/getuisdkurl",
|
url: "/meituan/getuisdkurl",
|
||||||
data,
|
data,
|
||||||
|
|||||||
@@ -801,6 +801,68 @@ export function attendanceDetail(params) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 分享奖励基础:新增/修改
|
||||||
|
export function shareBasePost(data) {
|
||||||
|
return request({
|
||||||
|
url: `${Market_BaseUrl}/admin/shareBase`,
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分享奖励基础 查询
|
||||||
|
export function shareBaseGet(params) {
|
||||||
|
return request({
|
||||||
|
url: `${Market_BaseUrl}/admin/shareBase`,
|
||||||
|
method: 'GET',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 轮播图配置:新增/修改
|
||||||
|
export function shareCarouselPost(data) {
|
||||||
|
return request({
|
||||||
|
url: `${Market_BaseUrl}/admin/carousel`,
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分享轮播图配置
|
||||||
|
export function shareCarouselGet(params) {
|
||||||
|
return request({
|
||||||
|
url: `${Market_BaseUrl}/admin/carousel`,
|
||||||
|
method: 'GET',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分享 轮播图配置 删除
|
||||||
|
export function shareCarouselDel(id) {
|
||||||
|
return request({
|
||||||
|
url: `${Market_BaseUrl}/admin/carousel/${id}`,
|
||||||
|
method: 'DELETE'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全民股东群聊 配置信息获取
|
||||||
|
export function disGroupGet(params) {
|
||||||
|
return request({
|
||||||
|
url: `${Market_BaseUrl}/admin/disGroup`,
|
||||||
|
method: 'get',
|
||||||
|
params
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全民股东群聊:新增/修改
|
||||||
|
export function disGroupPost(data) {
|
||||||
|
return request({
|
||||||
|
url: `${Market_BaseUrl}/admin/disGroup`,
|
||||||
|
method: 'POST',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,23 @@ const OrderApi = {
|
|||||||
data
|
data
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// 查询财务报表
|
||||||
|
financeSts(params: any) {
|
||||||
|
return request<any>({
|
||||||
|
url: `${Order_BaseUrl}/admin/finance/sts`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 导出财务报表
|
||||||
|
financeExport(params: any) {
|
||||||
|
return request<any>({
|
||||||
|
url: `${Order_BaseUrl}/admin/finance/export`,
|
||||||
|
method: "get",
|
||||||
|
params,
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default OrderApi;
|
export default OrderApi;
|
||||||
@@ -150,7 +167,7 @@ export type statusType =
|
|||||||
| "done"
|
| "done"
|
||||||
| "refunding"
|
| "refunding"
|
||||||
| "refund"
|
| "refund"
|
||||||
| "part-refund"
|
| "part_refund"
|
||||||
| "cancelled"
|
| "cancelled"
|
||||||
| "";
|
| "";
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { Order_BaseUrl } from "@/api/config";
|
|||||||
const baseURL = Order_BaseUrl + "/pay";
|
const baseURL = Order_BaseUrl + "/pay";
|
||||||
const Api = {
|
const Api = {
|
||||||
// h5支付
|
// h5支付
|
||||||
|
|
||||||
h5Pay(data: h5PayRequest) {
|
h5Pay(data: h5PayRequest) {
|
||||||
return request<any>({
|
return request<any>({
|
||||||
url: `${baseURL}/h5Pay`,
|
url: `${baseURL}/h5Pay`,
|
||||||
@@ -67,7 +66,6 @@ const Api = {
|
|||||||
params
|
params
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Api;
|
export default Api;
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ const Api = {
|
|||||||
method: "get",
|
method: "get",
|
||||||
params,
|
params,
|
||||||
responseType: 'blob'
|
responseType: 'blob'
|
||||||
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -51,6 +51,15 @@ const AuthAPI = {
|
|||||||
method: "delete",
|
method: "delete",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// 导出常用单位
|
||||||
|
exportUnits(params: any) {
|
||||||
|
return request<any, Responseres>({
|
||||||
|
url: `${baseURL}/export`,
|
||||||
|
method: "get",
|
||||||
|
params,
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -181,6 +181,15 @@ const AuthAPI = {
|
|||||||
method: "get",
|
method: "get",
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
// 导出商品
|
||||||
|
exportProducts(params: any) {
|
||||||
|
return request<any, Responseres>({
|
||||||
|
url: `${baseURL}/export`,
|
||||||
|
method: "get",
|
||||||
|
params,
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,15 @@ const AuthAPI = {
|
|||||||
method: "delete",
|
method: "delete",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
// 导出商品分类
|
||||||
|
exportCategories(params: any) {
|
||||||
|
return request<any, Responseres>({
|
||||||
|
url: `${baseURL}/export`,
|
||||||
|
method: "get",
|
||||||
|
params,
|
||||||
|
responseType: 'blob'
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
src/assets/applocation/fxpz.png
Normal file
BIN
src/assets/applocation/fxpz.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
161
src/components/AddressSelect/index.vue
Normal file
161
src/components/AddressSelect/index.vue
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
<template>
|
||||||
|
<div class="center">
|
||||||
|
<el-select placeholder="请选择省" style="width: 100px" v-model="prov" @change="provChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in provList"
|
||||||
|
:key="item.regionId"
|
||||||
|
:label="item.regionName"
|
||||||
|
:value="item.regionName"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-select
|
||||||
|
placeholder="请选择市"
|
||||||
|
style="width: 100px"
|
||||||
|
:disabled="!prov"
|
||||||
|
v-model="city"
|
||||||
|
@change="cityChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in cityList"
|
||||||
|
:key="item.regionId"
|
||||||
|
:label="item.regionName"
|
||||||
|
:value="item.regionName"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-select
|
||||||
|
placeholder="请选择区"
|
||||||
|
style="width: 100px"
|
||||||
|
:disabled="!city"
|
||||||
|
v-model="area"
|
||||||
|
@change="areaChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in areaList"
|
||||||
|
:key="item.regionId"
|
||||||
|
:label="item.regionName"
|
||||||
|
:value="item.regionName"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from "vue";
|
||||||
|
import { getRegion } from "@/api/common";
|
||||||
|
|
||||||
|
const provList = ref<any[]>([]);
|
||||||
|
const cityList = ref<any[]>([]);
|
||||||
|
const areaList = ref<any[]>([]);
|
||||||
|
|
||||||
|
const provCode = defineModel("provCode", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听省份code变化
|
||||||
|
watch(
|
||||||
|
provCode,
|
||||||
|
async (n, o) => {
|
||||||
|
await getRegionAjax();
|
||||||
|
if (n && n !== undefined) {
|
||||||
|
provChange(n, true);
|
||||||
|
|
||||||
|
// 监听市区code变化
|
||||||
|
watch(
|
||||||
|
cityCode,
|
||||||
|
async (n, o) => {
|
||||||
|
if (n !== undefined && n) {
|
||||||
|
cityChange(n, true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true, // 可选:初始化立即执行,验证是否监听到初始值
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true, // 可选:初始化立即执行,验证是否监听到初始值
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const cityCode = defineModel("cityCode", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const areaCode = defineModel("areaCode", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const prov = defineModel("prov", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const city = defineModel("city", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const area = defineModel("area", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const wxProvinceCode = defineModel("wxProvinceCode", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 省份变化 e code isEcho是否回显
|
||||||
|
function provChange(e: string, isEcho: boolean = false) {
|
||||||
|
console.log("provChange", e);
|
||||||
|
if (!isEcho) {
|
||||||
|
city.value = "";
|
||||||
|
area.value = "";
|
||||||
|
cityList.value = [];
|
||||||
|
areaList.value = [];
|
||||||
|
}
|
||||||
|
const provObj = provList.value.find((item) => item.regionName == e);
|
||||||
|
if (provObj && provObj.children) {
|
||||||
|
cityList.value = provObj.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 市区变化
|
||||||
|
function cityChange(e: string, isEcho: boolean = false) {
|
||||||
|
if (!isEcho) {
|
||||||
|
area.value = "";
|
||||||
|
areaList.value = [];
|
||||||
|
}
|
||||||
|
const cityObj = cityList.value.find((item) => item.regionName == e);
|
||||||
|
|
||||||
|
if (cityObj && cityObj.children) {
|
||||||
|
areaList.value = cityObj.children;
|
||||||
|
wxProvinceCode.value = cityObj.wxProvinceCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 区变化
|
||||||
|
function areaChange(e: string) {}
|
||||||
|
|
||||||
|
// 获取省市区数据
|
||||||
|
async function getRegionAjax() {
|
||||||
|
try {
|
||||||
|
const res = await getRegion();
|
||||||
|
provList.value = res;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取省市区数据失败:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.center {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -3,68 +3,49 @@
|
|||||||
<!-- 表格工具栏 -->
|
<!-- 表格工具栏 -->
|
||||||
<div class="flex-x-between mb-[10px]">
|
<div class="flex-x-between mb-[10px]">
|
||||||
<!-- 左侧工具栏 -->
|
<!-- 左侧工具栏 -->
|
||||||
<div>
|
<div style="display: flex;">
|
||||||
<template v-for="item in toolbar" :key="item">
|
<template v-for="item in toolbar" :key="item">
|
||||||
<template v-if="typeof item === 'string'">
|
<template v-if="typeof item === 'string'">
|
||||||
<!-- 新增 -->
|
<!-- 新增 -->
|
||||||
<template v-if="item === 'add'">
|
<template v-if="item === 'add'">
|
||||||
<el-button
|
<el-button v-hasPerm="[`${contentConfig.pageName}:${item}`]" type="primary" icon="plus"
|
||||||
v-hasPerm="[`${contentConfig.pageName}:${item}`]"
|
@click="handleToolbar(item)">
|
||||||
type="primary"
|
|
||||||
icon="plus"
|
|
||||||
@click="handleToolbar(item)"
|
|
||||||
>
|
|
||||||
新增
|
新增
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
<!-- 删除 -->
|
<!-- 删除 -->
|
||||||
<template v-else-if="item === 'delete'">
|
<template v-else-if="item === 'delete'">
|
||||||
<el-button
|
<el-button v-hasPerm="[`${contentConfig.pageName}:${item}`]" type="danger" icon="delete"
|
||||||
v-hasPerm="[`${contentConfig.pageName}:${item}`]"
|
:disabled="removeIds.length === 0" @click="handleToolbar(item)">
|
||||||
type="danger"
|
|
||||||
icon="delete"
|
|
||||||
:disabled="removeIds.length === 0"
|
|
||||||
@click="handleToolbar(item)"
|
|
||||||
>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
<!-- 导入 -->
|
<!-- 导入 -->
|
||||||
<template v-else-if="item === 'import'">
|
<template v-else-if="item === 'import'">
|
||||||
<el-button
|
<el-button v-hasPerm="[`${contentConfig.pageName}:${item}`]" type="default" icon="upload"
|
||||||
v-hasPerm="[`${contentConfig.pageName}:${item}`]"
|
@click="handleToolbar(item)">
|
||||||
type="default"
|
|
||||||
icon="upload"
|
|
||||||
@click="handleToolbar(item)"
|
|
||||||
>
|
|
||||||
导入
|
导入
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
<!-- 导出 -->
|
<!-- 导出 -->
|
||||||
<template v-else-if="item === 'export'">
|
<template v-else-if="item === 'export'">
|
||||||
<el-button
|
<el-button v-hasPerm="[`${contentConfig.pageName}:${item}`]" type="default" icon="download"
|
||||||
v-hasPerm="[`${contentConfig.pageName}:${item}`]"
|
@click="handleToolbar(item)">
|
||||||
type="default"
|
|
||||||
icon="download"
|
|
||||||
@click="handleToolbar(item)"
|
|
||||||
>
|
|
||||||
导出
|
导出
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<!-- 其他 -->
|
<!-- 其他 -->
|
||||||
<template v-else-if="typeof item === 'object'">
|
<template v-else-if="typeof item === 'object'">
|
||||||
<el-button
|
<el-button v-if="item.hidden === undefined || item.hidden === false"
|
||||||
v-if="item.hidden === undefined || item.hidden === false"
|
v-hasPerm="[`${contentConfig.pageName}:${item.auth}`]" :icon="item.icon" :type="item.type ?? 'default'"
|
||||||
v-hasPerm="[`${contentConfig.pageName}:${item.auth}`]"
|
@click="handleToolbar(item.name)">
|
||||||
:icon="item.icon"
|
|
||||||
:type="item.type ?? 'default'"
|
|
||||||
@click="handleToolbar(item.name)"
|
|
||||||
>
|
|
||||||
{{ item.text }}
|
{{ item.text }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
<!-- 插槽 -->
|
||||||
|
<slot name="custom" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 右侧工具栏 -->
|
<!-- 右侧工具栏 -->
|
||||||
<div>
|
<div>
|
||||||
@@ -89,68 +70,36 @@
|
|||||||
</template>
|
</template>
|
||||||
<!-- 导出 -->
|
<!-- 导出 -->
|
||||||
<template v-else-if="item === 'exports'">
|
<template v-else-if="item === 'exports'">
|
||||||
<el-button
|
<el-button v-hasPerm="[`${contentConfig.pageName}:export`]" icon="download" circle title="导出"
|
||||||
v-hasPerm="[`${contentConfig.pageName}:export`]"
|
@click="handleToolbar(item)" />
|
||||||
icon="download"
|
|
||||||
circle
|
|
||||||
title="导出"
|
|
||||||
@click="handleToolbar(item)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- 导入 -->
|
<!-- 导入 -->
|
||||||
<template v-else-if="item === 'imports'">
|
<template v-else-if="item === 'imports'">
|
||||||
<el-button
|
<el-button v-hasPerm="[`${contentConfig.pageName}:import`]" icon="upload" circle title="导入"
|
||||||
v-hasPerm="[`${contentConfig.pageName}:import`]"
|
@click="handleToolbar(item)" />
|
||||||
icon="upload"
|
|
||||||
circle
|
|
||||||
title="导入"
|
|
||||||
@click="handleToolbar(item)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- 搜索 -->
|
<!-- 搜索 -->
|
||||||
<template v-else-if="item === 'search'">
|
<template v-else-if="item === 'search'">
|
||||||
<el-button
|
<el-button v-hasPerm="[`${contentConfig.pageName}:query`]" icon="search" circle title="搜索"
|
||||||
v-hasPerm="[`${contentConfig.pageName}:query`]"
|
@click="handleToolbar(item)" />
|
||||||
icon="search"
|
|
||||||
circle
|
|
||||||
title="搜索"
|
|
||||||
@click="handleToolbar(item)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<!-- 其他 -->
|
<!-- 其他 -->
|
||||||
<template v-else-if="typeof item === 'object'">
|
<template v-else-if="typeof item === 'object'">
|
||||||
<template v-if="item.auth">
|
<template v-if="item.auth">
|
||||||
<el-button
|
<el-button v-hasPerm="[`${contentConfig.pageName}:${item.auth}`]" :icon="item.icon" circle
|
||||||
v-hasPerm="[`${contentConfig.pageName}:${item.auth}`]"
|
:title="item.title" @click="handleToolbar(item.name)" />
|
||||||
:icon="item.icon"
|
|
||||||
circle
|
|
||||||
:title="item.title"
|
|
||||||
@click="handleToolbar(item.name)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<el-button
|
<el-button :icon="item.icon" circle :title="item.title" @click="handleToolbar(item.name)" />
|
||||||
:icon="item.icon"
|
|
||||||
circle
|
|
||||||
:title="item.title"
|
|
||||||
@click="handleToolbar(item.name)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 列表 -->
|
<!-- 列表 -->
|
||||||
<el-table
|
<el-table ref="tableRef" v-loading="loading" v-bind="contentConfig.table" :data="pageData" :row-key="pk"
|
||||||
ref="tableRef"
|
@selection-change="handleSelectionChange" @filter-change="handleFilterChange">
|
||||||
v-loading="loading"
|
|
||||||
v-bind="contentConfig.table"
|
|
||||||
:data="pageData"
|
|
||||||
:row-key="pk"
|
|
||||||
@selection-change="handleSelectionChange"
|
|
||||||
@filter-change="handleFilterChange"
|
|
||||||
>
|
|
||||||
<template v-for="col in cols" :key="col">
|
<template v-for="col in cols" :key="col">
|
||||||
<el-table-column v-if="col.show" v-bind="col">
|
<el-table-column v-if="col.show" v-bind="col">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -159,24 +108,15 @@
|
|||||||
<template v-if="col.prop">
|
<template v-if="col.prop">
|
||||||
<template v-if="Array.isArray(scope.row[col.prop])">
|
<template v-if="Array.isArray(scope.row[col.prop])">
|
||||||
<template v-for="(item, index) in scope.row[col.prop]" :key="item">
|
<template v-for="(item, index) in scope.row[col.prop]" :key="item">
|
||||||
<el-image
|
<el-image :src="item" :preview-src-list="scope.row[col.prop]" :initial-index="index"
|
||||||
:src="item"
|
:preview-teleported="true" :style="`width: ${col.imageWidth ?? 40}px; height: ${col.imageHeight ?? 40
|
||||||
:preview-src-list="scope.row[col.prop]"
|
}px`" />
|
||||||
:initial-index="index"
|
|
||||||
:preview-teleported="true"
|
|
||||||
:style="`width: ${col.imageWidth ?? 40}px; height: ${
|
|
||||||
col.imageHeight ?? 40
|
|
||||||
}px`"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<el-image
|
<el-image :src="scope.row[col.prop]" :preview-src-list="[scope.row[col.prop]]"
|
||||||
:src="scope.row[col.prop]"
|
|
||||||
:preview-src-list="[scope.row[col.prop]]"
|
|
||||||
:preview-teleported="true"
|
:preview-teleported="true"
|
||||||
:style="`width: ${col.imageWidth ?? 40}px; height: ${col.imageHeight ?? 40}px`"
|
:style="`width: ${col.imageWidth ?? 40}px; height: ${col.imageHeight ?? 40}px`" />
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
@@ -198,30 +138,20 @@
|
|||||||
<template v-else-if="col.templet === 'switch'">
|
<template v-else-if="col.templet === 'switch'">
|
||||||
<template v-if="col.prop">
|
<template v-if="col.prop">
|
||||||
<!-- pageData.length>0: 解决el-switch组件会在表格初始化的时候触发一次change事件 -->
|
<!-- pageData.length>0: 解决el-switch组件会在表格初始化的时候触发一次change事件 -->
|
||||||
<el-switch
|
<el-switch v-model="scope.row[col.prop]" :active-value="col.activeValue ?? 1"
|
||||||
v-model="scope.row[col.prop]"
|
:inactive-value="col.inactiveValue ?? 0" :inline-prompt="true" :active-text="col.activeText ?? ''"
|
||||||
:active-value="col.activeValue ?? 1"
|
:inactive-text="col.inactiveText ?? ''" :validate-event="false"
|
||||||
:inactive-value="col.inactiveValue ?? 0"
|
:disabled="!hasAuth(`${contentConfig.pageName}:modify`)" @change="
|
||||||
:inline-prompt="true"
|
|
||||||
:active-text="col.activeText ?? ''"
|
|
||||||
:inactive-text="col.inactiveText ?? ''"
|
|
||||||
:validate-event="false"
|
|
||||||
:disabled="!hasAuth(`${contentConfig.pageName}:modify`)"
|
|
||||||
@change="
|
|
||||||
pageData.length > 0 && handleModify(col.prop, scope.row[col.prop], scope.row)
|
pageData.length > 0 && handleModify(col.prop, scope.row[col.prop], scope.row)
|
||||||
"
|
" />
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<!-- 生成输入框组件 -->
|
<!-- 生成输入框组件 -->
|
||||||
<template v-else-if="col.templet === 'input'">
|
<template v-else-if="col.templet === 'input'">
|
||||||
<template v-if="col.prop">
|
<template v-if="col.prop">
|
||||||
<el-input
|
<el-input v-model="scope.row[col.prop]" :type="col.inputType ?? 'text'"
|
||||||
v-model="scope.row[col.prop]"
|
|
||||||
:type="col.inputType ?? 'text'"
|
|
||||||
:disabled="!hasAuth(`${contentConfig.pageName}:modify`)"
|
:disabled="!hasAuth(`${contentConfig.pageName}:modify`)"
|
||||||
@blur="handleModify(col.prop, scope.row[col.prop], scope.row)"
|
@blur="handleModify(col.prop, scope.row[col.prop], scope.row)" />
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<!-- 格式化为价格 -->
|
<!-- 格式化为价格 -->
|
||||||
@@ -253,7 +183,7 @@
|
|||||||
{{
|
{{
|
||||||
scope.row[col.prop]
|
scope.row[col.prop]
|
||||||
? useDateFormat(scope.row[col.prop], col.dateFormat ?? "YYYY-MM-DD HH:mm:ss")
|
? useDateFormat(scope.row[col.prop], col.dateFormat ?? "YYYY-MM-DD HH:mm:ss")
|
||||||
.value
|
.value
|
||||||
: ""
|
: ""
|
||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
@@ -264,21 +194,15 @@
|
|||||||
<template v-if="typeof item === 'string'">
|
<template v-if="typeof item === 'string'">
|
||||||
<!-- 编辑/删除 -->
|
<!-- 编辑/删除 -->
|
||||||
<template v-if="item === 'edit' || item === 'delete'">
|
<template v-if="item === 'edit' || item === 'delete'">
|
||||||
<el-button
|
<el-button v-hasPerm="[`${contentConfig.pageName}:${item}`]"
|
||||||
v-hasPerm="[`${contentConfig.pageName}:${item}`]"
|
:type="item === 'edit' ? 'primary' : 'danger'" :icon="item" size="small" link @click="
|
||||||
:type="item === 'edit' ? 'primary' : 'danger'"
|
|
||||||
:icon="item"
|
|
||||||
size="small"
|
|
||||||
link
|
|
||||||
@click="
|
|
||||||
handleOperat({
|
handleOperat({
|
||||||
name: item,
|
name: item,
|
||||||
row: scope.row,
|
row: scope.row,
|
||||||
column: scope.column,
|
column: scope.column,
|
||||||
$index: scope.$index,
|
$index: scope.$index,
|
||||||
})
|
})
|
||||||
"
|
">
|
||||||
>
|
|
||||||
{{ item === "edit" ? "编辑" : "删除" }}
|
{{ item === "edit" ? "编辑" : "删除" }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -286,63 +210,43 @@
|
|||||||
<!-- 其他 -->
|
<!-- 其他 -->
|
||||||
<template v-else-if="typeof item === 'object'">
|
<template v-else-if="typeof item === 'object'">
|
||||||
<template v-if="item.hidden === undefined || item.hidden === false">
|
<template v-if="item.hidden === undefined || item.hidden === false">
|
||||||
<el-button
|
<el-button v-if="item.isBtn" v-hasPerm="[`${contentConfig.pageName}:${item.auth}`]"
|
||||||
v-if="item.isBtn"
|
:icon="item.icon" :type="item.type ?? 'primary'" size="small" link @click="
|
||||||
v-hasPerm="[`${contentConfig.pageName}:${item.auth}`]"
|
|
||||||
:icon="item.icon"
|
|
||||||
:type="item.type ?? 'primary'"
|
|
||||||
size="small"
|
|
||||||
link
|
|
||||||
@click="
|
|
||||||
handleOperat({
|
handleOperat({
|
||||||
name: item.name,
|
name: item.name,
|
||||||
row: scope.row,
|
row: scope.row,
|
||||||
column: scope.column,
|
column: scope.column,
|
||||||
$index: scope.$index,
|
$index: scope.$index,
|
||||||
})
|
})
|
||||||
"
|
">
|
||||||
>
|
|
||||||
{{ item.text }}
|
{{ item.text }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<el-dropdown style="margin-top: 4px" v-else>
|
<el-dropdown style="margin-top: 4px" v-else>
|
||||||
<el-button
|
<el-button v-if="item.render === undefined || item.render(scope.row)" v-bind="item.auth
|
||||||
v-if="item.render === undefined || item.render(scope.row)"
|
? { 'v-hasPerm': [`${contentConfig.pageName}:${item.auth}`] }
|
||||||
v-bind="
|
: {}
|
||||||
item.auth
|
" :icon="item.icon" :type="item.type ?? 'primary'" size="small" link @click="
|
||||||
? { 'v-hasPerm': [`${contentConfig.pageName}:${item.auth}`] }
|
|
||||||
: {}
|
|
||||||
"
|
|
||||||
:icon="item.icon"
|
|
||||||
:type="item.type ?? 'primary'"
|
|
||||||
size="small"
|
|
||||||
link
|
|
||||||
@click="
|
|
||||||
handleOperat({
|
handleOperat({
|
||||||
name: item.name,
|
name: item.name,
|
||||||
row: scope.row,
|
row: scope.row,
|
||||||
column: scope.column,
|
column: scope.column,
|
||||||
$index: scope.$index,
|
$index: scope.$index,
|
||||||
})
|
})
|
||||||
"
|
">
|
||||||
>
|
|
||||||
{{ item.text }}
|
{{ item.text }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<template #dropdown v-if="item.options && item.options.length > 0">
|
<template #dropdown v-if="item.options && item.options.length > 0">
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item
|
<el-dropdown-item @click="
|
||||||
@click="
|
handleOperat({
|
||||||
handleOperat({
|
name: item.name,
|
||||||
name: item.name,
|
row: scope.row,
|
||||||
row: scope.row,
|
column: scope.column,
|
||||||
column: scope.column,
|
$index: scope.$index,
|
||||||
$index: scope.$index,
|
command: opt.command ? opt.command : '',
|
||||||
command: opt.command ? opt.command : '',
|
})
|
||||||
})
|
" v-for="opt in item.options" :key="opt.value">
|
||||||
"
|
|
||||||
v-for="opt in item.options"
|
|
||||||
:key="opt.value"
|
|
||||||
>
|
|
||||||
{{ opt.label }}
|
{{ opt.label }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
@@ -364,33 +268,18 @@
|
|||||||
<template v-if="showPagination">
|
<template v-if="showPagination">
|
||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
<div class="mt-[12px]">
|
<div class="mt-[12px]">
|
||||||
<el-pagination
|
<el-pagination v-bind="pagination" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
|
||||||
v-bind="pagination"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="handleCurrentChange"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</el-scrollbar>
|
</el-scrollbar>
|
||||||
</template>
|
</template>
|
||||||
<!-- 导出弹窗 -->
|
<!-- 导出弹窗 -->
|
||||||
<el-dialog
|
<el-dialog v-model="exportsModalVisible" :align-center="true" title="导出数据" width="600px" style="padding-right: 0"
|
||||||
v-model="exportsModalVisible"
|
@close="handleCloseExportsModal">
|
||||||
:align-center="true"
|
|
||||||
title="导出数据"
|
|
||||||
width="600px"
|
|
||||||
style="padding-right: 0"
|
|
||||||
@close="handleCloseExportsModal"
|
|
||||||
>
|
|
||||||
<!-- 滚动 -->
|
<!-- 滚动 -->
|
||||||
<el-scrollbar max-height="60vh">
|
<el-scrollbar max-height="60vh">
|
||||||
<!-- 表单 -->
|
<!-- 表单 -->
|
||||||
<el-form
|
<el-form ref="exportsFormRef" label-width="auto" style="padding-right: var(--el-dialog-padding-primary)"
|
||||||
ref="exportsFormRef"
|
:model="exportsFormData" :rules="exportsFormRules">
|
||||||
label-width="auto"
|
|
||||||
style="padding-right: var(--el-dialog-padding-primary)"
|
|
||||||
:model="exportsFormData"
|
|
||||||
:rules="exportsFormRules"
|
|
||||||
>
|
|
||||||
<el-form-item label="文件名" prop="filename">
|
<el-form-item label="文件名" prop="filename">
|
||||||
<el-input v-model="exportsFormData.filename" clearable />
|
<el-input v-model="exportsFormData.filename" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -400,16 +289,10 @@
|
|||||||
<el-form-item label="数据源" prop="origin">
|
<el-form-item label="数据源" prop="origin">
|
||||||
<el-select v-model="exportsFormData.origin">
|
<el-select v-model="exportsFormData.origin">
|
||||||
<el-option label="当前数据 (当前页的数据)" :value="ExportsOriginEnum.CURRENT" />
|
<el-option label="当前数据 (当前页的数据)" :value="ExportsOriginEnum.CURRENT" />
|
||||||
<el-option
|
<el-option label="选中数据 (所有选中的数据)" :value="ExportsOriginEnum.SELECTED"
|
||||||
label="选中数据 (所有选中的数据)"
|
:disabled="selectionData.length <= 0" />
|
||||||
:value="ExportsOriginEnum.SELECTED"
|
<el-option label="全量数据 (所有分页的数据)" :value="ExportsOriginEnum.REMOTE"
|
||||||
:disabled="selectionData.length <= 0"
|
:disabled="contentConfig.exportsAction === undefined" />
|
||||||
/>
|
|
||||||
<el-option
|
|
||||||
label="全量数据 (所有分页的数据)"
|
|
||||||
:value="ExportsOriginEnum.REMOTE"
|
|
||||||
:disabled="contentConfig.exportsAction === undefined"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="字段" prop="fields">
|
<el-form-item label="字段" prop="fields">
|
||||||
@@ -430,35 +313,17 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<!-- 导入弹窗 -->
|
<!-- 导入弹窗 -->
|
||||||
<el-dialog
|
<el-dialog v-model="importModalVisible" :align-center="true" title="导入数据" width="600px" style="padding-right: 0"
|
||||||
v-model="importModalVisible"
|
@close="handleCloseImportModal">
|
||||||
:align-center="true"
|
|
||||||
title="导入数据"
|
|
||||||
width="600px"
|
|
||||||
style="padding-right: 0"
|
|
||||||
@close="handleCloseImportModal"
|
|
||||||
>
|
|
||||||
<!-- 滚动 -->
|
<!-- 滚动 -->
|
||||||
<el-scrollbar max-height="60vh">
|
<el-scrollbar max-height="60vh">
|
||||||
<!-- 表单 -->
|
<!-- 表单 -->
|
||||||
<el-form
|
<el-form ref="importFormRef" label-width="auto" style="padding-right: var(--el-dialog-padding-primary)"
|
||||||
ref="importFormRef"
|
:model="importFormData" :rules="importFormRules">
|
||||||
label-width="auto"
|
|
||||||
style="padding-right: var(--el-dialog-padding-primary)"
|
|
||||||
:model="importFormData"
|
|
||||||
:rules="importFormRules"
|
|
||||||
>
|
|
||||||
<el-form-item label="文件名" prop="files">
|
<el-form-item label="文件名" prop="files">
|
||||||
<el-upload
|
<el-upload ref="uploadRef" v-model:file-list="importFormData.files" class="w-full"
|
||||||
ref="uploadRef"
|
|
||||||
v-model:file-list="importFormData.files"
|
|
||||||
class="w-full"
|
|
||||||
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
|
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
|
||||||
:drag="true"
|
:drag="true" :limit="1" :auto-upload="false" :on-exceed="handleFileExceed">
|
||||||
:limit="1"
|
|
||||||
:auto-upload="false"
|
|
||||||
:on-exceed="handleFileExceed"
|
|
||||||
>
|
|
||||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||||
<div class="el-upload__text">
|
<div class="el-upload__text">
|
||||||
<span>将文件拖到此处,或</span>
|
<span>将文件拖到此处,或</span>
|
||||||
@@ -467,13 +332,8 @@
|
|||||||
<template #tip>
|
<template #tip>
|
||||||
<div class="el-upload__tip">
|
<div class="el-upload__tip">
|
||||||
*.xlsx / *.xls
|
*.xlsx / *.xls
|
||||||
<el-link
|
<el-link v-if="contentConfig.importTemplate" type="primary" icon="download" :underline="false"
|
||||||
v-if="contentConfig.importTemplate"
|
@click="handleDownloadTemplate">
|
||||||
type="primary"
|
|
||||||
icon="download"
|
|
||||||
:underline="false"
|
|
||||||
@click="handleDownloadTemplate"
|
|
||||||
>
|
|
||||||
下载模板
|
下载模板
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
@@ -485,11 +345,7 @@
|
|||||||
<!-- 弹窗底部操作按钮 -->
|
<!-- 弹窗底部操作按钮 -->
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div style="padding-right: var(--el-dialog-padding-primary)">
|
<div style="padding-right: var(--el-dialog-padding-primary)">
|
||||||
<el-button
|
<el-button type="primary" :disabled="importFormData.files.length === 0" @click="handleImportSubmit">
|
||||||
type="primary"
|
|
||||||
:disabled="importFormData.files.length === 0"
|
|
||||||
@click="handleImportSubmit"
|
|
||||||
>
|
|
||||||
确 定
|
确 定
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button @click="handleCloseImportModal">取 消</el-button>
|
<el-button @click="handleCloseImportModal">取 消</el-button>
|
||||||
@@ -1005,10 +861,10 @@ function fetchPageData(formData: IObject = {}, isRestart = false) {
|
|||||||
.indexAction(
|
.indexAction(
|
||||||
showPagination
|
showPagination
|
||||||
? {
|
? {
|
||||||
[request.pageName]: pagination.currentPage,
|
[request.pageName]: pagination.currentPage,
|
||||||
[request.limitName]: pagination.pageSize,
|
[request.limitName]: pagination.pageSize,
|
||||||
...formData,
|
...formData,
|
||||||
}
|
}
|
||||||
: formData
|
: formData
|
||||||
)
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
@@ -1073,7 +929,7 @@ function saveXlsx(fileData: BlobPart, fileName: string) {
|
|||||||
document.body.removeChild(downloadLink);
|
document.body.removeChild(downloadLink);
|
||||||
window.URL.revokeObjectURL(downloadUrl);
|
window.URL.revokeObjectURL(downloadUrl);
|
||||||
}
|
}
|
||||||
function test(rows: any[]) {}
|
function test(rows: any[]) { }
|
||||||
|
|
||||||
const defaultSelData = ref<IObject[]>([]);
|
const defaultSelData = ref<IObject[]>([]);
|
||||||
// 设置默认选择
|
// 设置默认选择
|
||||||
@@ -1115,17 +971,21 @@ defineExpose({
|
|||||||
:deep(.el-table .el-table__cell) {
|
:deep(.el-table .el-table__cell) {
|
||||||
z-index: inherit;
|
z-index: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-card {
|
.el-card {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-table) {
|
:deep(.el-table) {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
|
||||||
.el-table__header-wrapper {
|
.el-table__header-wrapper {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
z-index: calc(var(--el-table-index) + 2);
|
z-index: calc(var(--el-table-index) + 2);
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.el-table td.el-table__cell div) {
|
:deep(.el-table td.el-table__cell div) {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,44 +1,42 @@
|
|||||||
<!-- 文件上传组件 -->
|
<!-- 文件上传组件 -->
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-upload
|
<el-upload v-model:file-list="fileList" :style="props.style" :before-upload="handleBeforeUpload"
|
||||||
v-model:file-list="fileList"
|
:http-request="handleUpload" :on-progress="handleProgress" :on-success="handleSuccess" :on-error="handleError"
|
||||||
:style="props.style"
|
:accept="props.accept" :limit="props.limit" multiple drag :tip="'支持多个文件上传,单个文件不超过 ' + props.maxFileSize + 'MB'">
|
||||||
:before-upload="handleBeforeUpload"
|
<!-- 拖拽上传区域 -->
|
||||||
:http-request="handleUpload"
|
<div>
|
||||||
:on-progress="handleProgress"
|
<el-icon class="el-icon--upload">
|
||||||
:on-success="handleSuccess"
|
<UploadFilled />
|
||||||
:on-error="handleError"
|
</el-icon>
|
||||||
:accept="props.accept"
|
<div class="el-upload__text">
|
||||||
:limit="props.limit"
|
将文件拖到此处,或 <em>点击上传</em>
|
||||||
multiple
|
<br />
|
||||||
>
|
<small>支持格式:{{ props.accept }}</small>
|
||||||
<!-- 上传文件按钮 -->
|
</div>
|
||||||
<el-button type="primary" :disabled="fileList.length >= props.limit">
|
</div>
|
||||||
{{ props.uploadBtnText }}
|
|
||||||
</el-button>
|
|
||||||
|
|
||||||
<!-- 文件列表 -->
|
<!-- 文件列表 -->
|
||||||
<template #file="{ file }">
|
<template #file="{ file }">
|
||||||
<div class="el-upload-list__item-info">
|
<div class="el-upload-list__item-info">
|
||||||
<a class="el-upload-list__item-name" @click="handleDownload(file)">
|
<a class="el-upload-list__item-name" @click="handleDownload(file)">
|
||||||
<el-icon><Document /></el-icon>
|
<el-icon>
|
||||||
|
<Document />
|
||||||
|
</el-icon>
|
||||||
<span class="el-upload-list__item-file-name">{{ file.name }}</span>
|
<span class="el-upload-list__item-file-name">{{ file.name }}</span>
|
||||||
<span class="el-icon--close" @click="handleRemove(file.url!)">
|
<span class="el-icon--close" @click="handleRemove(file.url)">
|
||||||
<el-icon><Close /></el-icon>
|
<el-icon>
|
||||||
|
<Close />
|
||||||
|
</el-icon>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
|
<el-progress :style="{
|
||||||
<el-progress
|
display: showProgress ? 'inline-flex' : 'none',
|
||||||
:style="{
|
width: '100%',
|
||||||
display: showProgress ? 'inline-flex' : 'none',
|
marginTop: '10px',
|
||||||
width: '100%',
|
}" :percentage="progressPercent" />
|
||||||
}"
|
|
||||||
:percentage="progressPercent"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
@@ -48,9 +46,14 @@ import {
|
|||||||
UploadProgressEvent,
|
UploadProgressEvent,
|
||||||
UploadRequestOptions,
|
UploadRequestOptions,
|
||||||
} from "element-plus";
|
} from "element-plus";
|
||||||
|
import { Upload, Document, Close } from "@element-plus/icons-vue";
|
||||||
|
|
||||||
import CommonApi, { FileInfo, uploadResponse } from "@/api/account/common";
|
import CommonApi, { FileInfo, uploadResponse } from "@/api/account/common";
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
"upload-success": [fileInfo: string];
|
||||||
|
}>();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
/**
|
/**
|
||||||
* 请求携带的额外参数
|
* 请求携带的额外参数
|
||||||
@@ -96,7 +99,6 @@ const props = defineProps({
|
|||||||
type: String,
|
type: String,
|
||||||
default: "上传文件",
|
default: "上传文件",
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 样式
|
* 样式
|
||||||
*/
|
*/
|
||||||
@@ -104,7 +106,7 @@ const props = defineProps({
|
|||||||
type: Object,
|
type: Object,
|
||||||
default: () => {
|
default: () => {
|
||||||
return {
|
return {
|
||||||
width: "300px",
|
width: "100%",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -147,6 +149,7 @@ function handleBeforeUpload(file: UploadRawFile) {
|
|||||||
ElMessage.warning("上传图片不能大于" + props.maxFileSize + "M");
|
ElMessage.warning("上传图片不能大于" + props.maxFileSize + "M");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
showProgress.value = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,10 +193,13 @@ const handleProgress = (event: UploadProgressEvent) => {
|
|||||||
const handleSuccess = (fileInfo: string) => {
|
const handleSuccess = (fileInfo: string) => {
|
||||||
ElMessage.success("上传成功");
|
ElMessage.success("上传成功");
|
||||||
modelValue.value = [...modelValue.value, fileInfo];
|
modelValue.value = [...modelValue.value, fileInfo];
|
||||||
|
emit("upload-success", fileInfo);
|
||||||
|
showProgress.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleError = (error: any) => {
|
const handleError = (error: any) => {
|
||||||
ElMessage.error("上传失败");
|
ElMessage.error("上传失败");
|
||||||
|
showProgress.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
242
src/components/Upload/GfileUpload.vue
Normal file
242
src/components/Upload/GfileUpload.vue
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
<!-- 文件上传组件 -->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-upload v-model:file-list="fileList" :style="props.style" :before-upload="handleBeforeUpload"
|
||||||
|
:on-change="handleChange" :accept="accept" multiple drag :tip="'支持多个文件上传,单个文件不超过 ' + props.maxFileSize + 'MB'"
|
||||||
|
:auto-upload="false">
|
||||||
|
<!-- 拖拽上传区域 -->
|
||||||
|
<div>
|
||||||
|
<el-icon class="el-icon--upload">
|
||||||
|
<UploadFilled />
|
||||||
|
</el-icon>
|
||||||
|
<div class="el-upload__text">
|
||||||
|
将文件拖到此处,或 <em>点击上传</em>
|
||||||
|
<br />
|
||||||
|
<small>支持格式:{{ accept }}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 文件列表 -->
|
||||||
|
<template #file="{ file }">
|
||||||
|
<div class="el-upload-list__item-info">
|
||||||
|
<a class="el-upload-list__item-name" @click="handleDownload(file)">
|
||||||
|
<el-icon>
|
||||||
|
<Document />
|
||||||
|
</el-icon>
|
||||||
|
<span class="el-upload-list__item-file-name">{{ file.name }}</span>
|
||||||
|
<span class="el-icon--close" @click="handleRemove(file.url)">
|
||||||
|
<el-icon>
|
||||||
|
<Close />
|
||||||
|
</el-icon>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-upload>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { UploadFilled, Document, Close } from "@element-plus/icons-vue";
|
||||||
|
|
||||||
|
const emit = defineEmits({
|
||||||
|
"file-selected": null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
/**
|
||||||
|
* 文件上传数量限制
|
||||||
|
*/
|
||||||
|
limit: {
|
||||||
|
type: Number,
|
||||||
|
default: 10,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 单个文件上传大小限制(单位MB)
|
||||||
|
*/
|
||||||
|
maxFileSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 10,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 上传文件类型
|
||||||
|
*/
|
||||||
|
accept: {
|
||||||
|
type: String,
|
||||||
|
default: "*",
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 选择文件成功的回调函数
|
||||||
|
*/
|
||||||
|
successCallback: {
|
||||||
|
type: Function,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 样式
|
||||||
|
*/
|
||||||
|
style: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
width: "100%",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const fileList = defineModel({
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件选择变化
|
||||||
|
*/
|
||||||
|
function handleChange(file, fileList) {
|
||||||
|
if (file.status === 'ready') {
|
||||||
|
// 如果限制为1个文件,移除之前的文件,只保留当前新文件
|
||||||
|
if (props.limit === 1 && fileList.length > 1) {
|
||||||
|
fileList.splice(0, fileList.length - 1);
|
||||||
|
}
|
||||||
|
const rawFile = file.raw;
|
||||||
|
// 限制文件类型
|
||||||
|
if (props.accept !== "*") {
|
||||||
|
const acceptedTypes = props.accept.split(',').map(type => type.trim());
|
||||||
|
const isAccepted = acceptedTypes.some(type => {
|
||||||
|
let checkType = type;
|
||||||
|
if (!type.startsWith('.') && !type.includes('/')) {
|
||||||
|
checkType = '.' + type;
|
||||||
|
}
|
||||||
|
if (checkType.startsWith('.')) {
|
||||||
|
return rawFile.name.toLowerCase().endsWith(checkType.toLowerCase());
|
||||||
|
} else if (checkType.includes('*')) {
|
||||||
|
const [main] = checkType.split('/');
|
||||||
|
return rawFile.type.startsWith(main + '/');
|
||||||
|
} else {
|
||||||
|
return rawFile.type === checkType;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!isAccepted) {
|
||||||
|
ElMessage.warning("文件类型不符合要求");
|
||||||
|
// 从 fileList 中移除不符合的文件
|
||||||
|
fileList.splice(fileList.indexOf(file), 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (props.successCallback) {
|
||||||
|
props.successCallback(rawFile);
|
||||||
|
} else {
|
||||||
|
emit("file-selected", rawFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传前校验
|
||||||
|
*/
|
||||||
|
function handleBeforeUpload(file) {
|
||||||
|
// 限制文件大小
|
||||||
|
if (file.size > props.maxFileSize * 1024 * 1024) {
|
||||||
|
ElMessage.warning("上传文件不能大于" + props.maxFileSize + "M");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 限制文件类型
|
||||||
|
if (props.accept !== "*") {
|
||||||
|
const acceptedTypes = props.accept.split(',').map(type => type.trim());
|
||||||
|
const isAccepted = acceptedTypes.some(type => {
|
||||||
|
if (type.startsWith('.')) {
|
||||||
|
return file.name.toLowerCase().endsWith(type.toLowerCase());
|
||||||
|
} else {
|
||||||
|
return file.type === type;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!isAccepted) {
|
||||||
|
ElMessage.warning("文件类型不符合要求");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除文件
|
||||||
|
*/
|
||||||
|
function handleRemove(fileUrl) {
|
||||||
|
// 从 fileList 中移除
|
||||||
|
fileList.value = fileList.value.filter(f => f.url !== fileUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载文件
|
||||||
|
*/
|
||||||
|
function handleDownload(file) {
|
||||||
|
// 本地文件,不支持下载
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.el-upload-list__item .el-icon--close {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 5px;
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0.75;
|
||||||
|
transition: opacity var(--el-transition-duration);
|
||||||
|
transform: translateY(-50%);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
color: var(--el-color-danger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-upload-list) {
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-upload-list__item) {
|
||||||
|
margin: 5px 0;
|
||||||
|
background: #f5f5f5;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #f0f0f0;
|
||||||
|
border-color: var(--el-color-primary-light-3);
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-upload-list__item-info {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--el-text-color-primary);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
margin-right: 8px;
|
||||||
|
color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-upload-list__item-file-name {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon--close {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -172,12 +172,12 @@ const onError = (error: any) => {
|
|||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px var(--el-border-color) solid;
|
// border: 1px var(--el-border-color) solid;
|
||||||
border-radius: 5px;
|
// border-radius: 5px;
|
||||||
|
|
||||||
&:hover {
|
// &:hover {
|
||||||
border-color: var(--el-color-primary);
|
// border-color: var(--el-color-primary);
|
||||||
}
|
// }
|
||||||
|
|
||||||
&__delete-btn {
|
&__delete-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|||||||
258
src/components/importData/index.vue
Normal file
258
src/components/importData/index.vue
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
<!-- 批量导入数据dialog -->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="btn_row">
|
||||||
|
<el-button type="primary" icon="Upload" @click="show">批量导入</el-button>
|
||||||
|
<el-button icon="Download" @click="downloadTemplateAjax">下载银收客模板</el-button>
|
||||||
|
</div>
|
||||||
|
<el-dialog title="批量导入" width="800px" v-model="visible" :close-on-click-modal="false" :close-on-press-escape="false"
|
||||||
|
@close="dialogClose">
|
||||||
|
<div class="row">
|
||||||
|
<tabHeader v-model="tabActive" :list="tabs" />
|
||||||
|
</div>
|
||||||
|
<div class="row mt14">
|
||||||
|
<div class="import_container" v-if="tabActive == 0">
|
||||||
|
<div class="header_title">第一步:选择模板</div>
|
||||||
|
<div class="row mt14 pb50">
|
||||||
|
<div class="list">
|
||||||
|
<div class="item" :class="{ active: platformActive == index }" v-for="(item, index) in platformList"
|
||||||
|
:key="item.id" @click="selectPlatform(item)">
|
||||||
|
<img class="img" :src="item.img" alt="">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="header_title">第二步:上传文件
|
||||||
|
<span>单次仅可上传一个文件</span>
|
||||||
|
</div>
|
||||||
|
<div class="row mt14">
|
||||||
|
<GfileUpload v-model="form.files" :accept="platformList[platformActive]?.file_type || ''" :limit="1"
|
||||||
|
@file-selected="fileSelected" />
|
||||||
|
</div>
|
||||||
|
<div class="row mt14">
|
||||||
|
<div class="footer_wrap">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" :disabled="!form.files.length" :loading="loading" @click="startImportHandle">
|
||||||
|
<template v-if="!form.files.length">请选择文件</template>
|
||||||
|
<template v-else>开始导入</template>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-table :data="tableData" border stripe v-if="tabActive == 1" height="419px">
|
||||||
|
<el-table-column prop="file_name" label="文件名称" width="300" />
|
||||||
|
<el-table-column prop="created_time" label="导入时间" width="200" />
|
||||||
|
<el-table-column prop="status_text" label="导入状态" width="150">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag v-if="scope.row.status == 0" type="info" disable-transitions>待处理...</el-tag>
|
||||||
|
<el-tag v-else-if="scope.row.status == 1" type="warning" disable-transitions>处理中...</el-tag>
|
||||||
|
<el-tag v-else-if="scope.row.status == 2" type="success" disable-transitions>处理完成</el-tag>
|
||||||
|
<el-tag v-else-if="scope.row.status == -1" type="danger" disable-transitions>导入失败</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="importResult" label="导入结果">
|
||||||
|
<template #default="scope">
|
||||||
|
<template v-if="scope.row.status == 2">
|
||||||
|
<div class="column">
|
||||||
|
<div>
|
||||||
|
<el-text type="success">成功:{{ scope.row.success_num }} 条</el-text>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-text type="danger">失败:{{ scope.row.fail_num }} 条</el-text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, watch } from 'vue';
|
||||||
|
import { getplatlist, uploadFile, importlist, downloadTemp } from '@/importDataApi/index.js';
|
||||||
|
import GfileUpload from '../Upload/GfileUpload.vue';
|
||||||
|
import tabHeader from '@/views/marketing_center/components/tabHeader.vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
type: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: 3, // 3商品 4台桌区域 5台桌 6会员 7菜品销售统计 8台桌销售统计 9订单销售统计
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const platformList = ref([]);
|
||||||
|
const platformActive = ref(0);
|
||||||
|
function selectPlatform(item) {
|
||||||
|
form.value.files = [];
|
||||||
|
platformActive.value = platformList.value.findIndex(i => i.id === item.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tabs = ref([
|
||||||
|
{ label: '导入数据', name: 'importData' },
|
||||||
|
{ label: '导入记录', name: 'importRecord' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const tabActive = ref(0)
|
||||||
|
|
||||||
|
watch(tabActive, (newVal) => {
|
||||||
|
if (newVal === 1) {
|
||||||
|
getImportRecord();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
const loading = ref(false);
|
||||||
|
const form = ref({
|
||||||
|
files: [],
|
||||||
|
platform: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
function fileSelected(file) {
|
||||||
|
console.log('fileSelected', file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始导入
|
||||||
|
async function startImportHandle() {
|
||||||
|
try {
|
||||||
|
form.value.platform = platformList.value[platformActive.value]?.id;
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', form.value.files[0].raw);
|
||||||
|
formData.append('shop_id', localStorage.getItem('shopId'));
|
||||||
|
formData.append('type', props.type);
|
||||||
|
formData.append('platform', form.value.platform);
|
||||||
|
loading.value = true;
|
||||||
|
await uploadFile(formData);
|
||||||
|
ElMessage.success('文件上传成功,正在导入数据,请在导入记录中查看导入结果');
|
||||||
|
form.value.files = []
|
||||||
|
tabActive.value = 1
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = false;
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取平台列表
|
||||||
|
async function getPlatformList() {
|
||||||
|
try {
|
||||||
|
const res = await getplatlist({ plat_type: props.type });
|
||||||
|
platformList.value = res;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导入记录
|
||||||
|
const tableData = ref([]);
|
||||||
|
async function getImportRecord() {
|
||||||
|
try {
|
||||||
|
const res = await importlist({ shop_id: localStorage.getItem('shopId') });
|
||||||
|
tableData.value = res;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载模板
|
||||||
|
async function downloadTemplateAjax() {
|
||||||
|
try {
|
||||||
|
const res = await downloadTemp({ plat_type: props.type });
|
||||||
|
window.open(res, '_blank');
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const emits = defineEmits(['close'])
|
||||||
|
|
||||||
|
function dialogClose() {
|
||||||
|
emits('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getPlatformList()
|
||||||
|
});
|
||||||
|
|
||||||
|
function show() {
|
||||||
|
visible.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
show,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.btn_row {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
margin-left: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999999;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
&.mt14 {
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pb50 {
|
||||||
|
padding-bottom: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.import_container {
|
||||||
|
.list {
|
||||||
|
display: flex;
|
||||||
|
gap: 24px;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
width: 122px;
|
||||||
|
height: 42px;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_wrap {
|
||||||
|
display: flex;
|
||||||
|
gap: 14px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
34
src/components/selectCoupon/index.vue
Normal file
34
src/components/selectCoupon/index.vue
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<template>
|
||||||
|
<el-select v-model="modelValue" placeholder="请选择优惠券" clearable style="width: 300px;" @change="changHandle">
|
||||||
|
<el-option v-for="coupon in couponList" :key="coupon.id" :label="coupon.title" :value="coupon.id" />
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import couponApi from "@/api/market/coupon";
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
|
||||||
|
const modelValue = defineModel({
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const name = defineModel('name', {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
function changHandle(value) {
|
||||||
|
name.value = couponList.value.find(item => item.id === value)?.title || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优惠券列表
|
||||||
|
const couponList = ref([]);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
couponApi.getList({ size: 999 }).then((res) => {
|
||||||
|
if (res) {
|
||||||
|
couponList.value = res.records || [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
57
src/importDataApi/index.js
Normal file
57
src/importDataApi/index.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import request from "@/utils/request-import-php";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平台列表
|
||||||
|
* @param {*} data
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getplatlist(data) {
|
||||||
|
return request({
|
||||||
|
url: "plat/getplatlist",
|
||||||
|
method: "post",
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入
|
||||||
|
* @param {*} data
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function uploadFile(data) {
|
||||||
|
return request({
|
||||||
|
url: "upload",
|
||||||
|
method: "post",
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data',
|
||||||
|
},
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入记录
|
||||||
|
* @param {*} data
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function importlist(data) {
|
||||||
|
return request({
|
||||||
|
url: "plat/importlist",
|
||||||
|
method: "post",
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载模板
|
||||||
|
* @param {*} data
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function downloadTemp(data) {
|
||||||
|
return request({
|
||||||
|
url: "plat/downloadTemp",
|
||||||
|
method: "post",
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@@ -63,6 +63,14 @@ export const constantRoutes: RouteRecordRaw[] = [
|
|||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "finance",
|
||||||
|
name: "",
|
||||||
|
component: () => import("@/views/data/finance.vue"),
|
||||||
|
meta: {
|
||||||
|
title: "财务报表"
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "work",
|
path: "work",
|
||||||
name: "workStatistics",
|
name: "workStatistics",
|
||||||
|
|||||||
@@ -111,8 +111,16 @@ export function downloadFile(obj: BlobPart, name: string, suffix: string, useUni
|
|||||||
const link = document.createElement("a");
|
const link = document.createElement("a");
|
||||||
link.style.display = "none";
|
link.style.display = "none";
|
||||||
link.href = url;
|
link.href = url;
|
||||||
const newFilename = useUnix ? (parseTime(new Date(), undefined) + "-") : '' + name.trim()
|
// 期望行为:
|
||||||
const fileName = newFilename + "." + suffix;
|
// - 当 useUnix 为 true 且传入 name 时:`${timestamp}-${name}`
|
||||||
|
// - 当 useUnix 为 true 且 name 为空时:仅 `${timestamp}`(不带多余的 `-`)
|
||||||
|
// - 当 useUnix 为 false:使用传入的 name(如为空则回退到时间戳)
|
||||||
|
const safeName = (name || "").trim();
|
||||||
|
const timeStamp = parseTime(new Date(), undefined);
|
||||||
|
const fileBase = useUnix
|
||||||
|
? (safeName ? `${timeStamp}-${safeName}` : timeStamp)
|
||||||
|
: (safeName || timeStamp);
|
||||||
|
const fileName = fileBase + "." + suffix;
|
||||||
link.setAttribute("download", fileName);
|
link.setAttribute("download", fileName);
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
@@ -300,3 +308,17 @@ export function includesString(target, searchStr, options = {}) {
|
|||||||
// 4. 执行包含判断
|
// 4. 执行包含判断
|
||||||
return processedTarget.includes(processedSearch);
|
return processedTarget.includes(processedSearch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验手机号码(中国大陆)
|
||||||
|
* - 支持 11 位手机号,号段 13x-19x
|
||||||
|
* @param {string} phone
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function isValidMobile(phone: string): boolean {
|
||||||
|
if (!phone && phone !== 0) return false;
|
||||||
|
const s = String(phone).trim();
|
||||||
|
// 中国大陆手机号正则:以1开头,第二位3-9,后面9位数字,总共11位
|
||||||
|
const mobileRegex = /^1[3-9]\d{9}$/;
|
||||||
|
return mobileRegex.test(s);
|
||||||
|
}
|
||||||
|
|||||||
131
src/utils/request-import-php.js
Normal file
131
src/utils/request-import-php.js
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import router from "@/router";
|
||||||
|
import { getDouyinToken, getToken } from "@/utils/auth";
|
||||||
|
|
||||||
|
// 创建axios实例
|
||||||
|
const service = axios.create({
|
||||||
|
baseURL: import.meta.env.VITE_APP_API_PHP_IMPORT_URL, // api 的 base_url
|
||||||
|
// baseURL: "/import_api", // api 的 base_url
|
||||||
|
timeout: 1000 * 20, // 请求超时时间
|
||||||
|
});
|
||||||
|
|
||||||
|
// request拦截器
|
||||||
|
service.interceptors.request.use(
|
||||||
|
(config) => {
|
||||||
|
if (getToken()) {
|
||||||
|
config.headers["token"] = getToken();
|
||||||
|
}
|
||||||
|
if (!config.headers["Content-Type"]) {
|
||||||
|
config.headers["Content-Type"] = "application/json";
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
// 确保错误回调返回Promise,避免状态异常
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// response 拦截器
|
||||||
|
service.interceptors.response.use(
|
||||||
|
(response) => {
|
||||||
|
const data = response.data;
|
||||||
|
console.log(data);
|
||||||
|
if (data.code == 0) {
|
||||||
|
ElNotification.error({
|
||||||
|
title: data.msg,
|
||||||
|
duration: 5000,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data.code == 439 || data.code == 303) {
|
||||||
|
ElNotification.error({
|
||||||
|
title: "请登录",
|
||||||
|
duration: 5000,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data.code == 4399) {
|
||||||
|
ElNotification.error({
|
||||||
|
title: data.msg,
|
||||||
|
duration: 5000,
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
// if (data.code == 1 && !data.data) {
|
||||||
|
// ElNotification.success({
|
||||||
|
// title: data.msg,
|
||||||
|
// duration: 5000
|
||||||
|
// })
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
return data.data;
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
console.log(error);
|
||||||
|
if (axios.isCancel(error)) {
|
||||||
|
console.log("请求已取消");
|
||||||
|
ElNotification.error({
|
||||||
|
title: "请求已取消",
|
||||||
|
duration: 5000,
|
||||||
|
});
|
||||||
|
return Promise.reject("请求已取消");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 兼容blob下载出错json提示
|
||||||
|
if (
|
||||||
|
error.response.data instanceof Blob &&
|
||||||
|
error.response.data.type.toLowerCase().indexOf("json") !== -1
|
||||||
|
) {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsText(error.response.data, "utf-8");
|
||||||
|
reader.onload = function (e) {
|
||||||
|
const errorMsg = JSON.parse(reader.result).message;
|
||||||
|
ElNotification.error({
|
||||||
|
title: errorMsg,
|
||||||
|
duration: 5000,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
let code = 0;
|
||||||
|
try {
|
||||||
|
code = error.response.data.status;
|
||||||
|
} catch (e) {
|
||||||
|
if (error.toString().indexOf("Error: timeout") !== -1) {
|
||||||
|
ElNotification.error({
|
||||||
|
title: "网络请求超时",
|
||||||
|
duration: 5000,
|
||||||
|
});
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(code);
|
||||||
|
if (code) {
|
||||||
|
if (code === 401) {
|
||||||
|
// store.dispatch("LogOut").then(() => {
|
||||||
|
// // 用户登录界面提示
|
||||||
|
// Cookies.set("point", 401);
|
||||||
|
// location.reload();
|
||||||
|
// });
|
||||||
|
} else if (code === 403) {
|
||||||
|
router.push({ path: "/401" });
|
||||||
|
} else {
|
||||||
|
const errorMsg = error.response.data.message;
|
||||||
|
if (errorMsg !== undefined) {
|
||||||
|
ElNotification.error({
|
||||||
|
title: errorMsg,
|
||||||
|
duration: 5000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ElNotification.error({
|
||||||
|
title: "接口请求失败",
|
||||||
|
duration: 5000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default service;
|
||||||
@@ -91,7 +91,7 @@ service.interceptors.response.use(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ElMessage.error(formatErrorMsg(msg || "Error"));
|
ElMessage.error(formatErrorMsg(msg || "Error"));
|
||||||
return Promise.reject(new Error(formatErrorMsg(msg || "Error")));
|
return Promise.reject(response.data);
|
||||||
},
|
},
|
||||||
async (error: any) => {
|
async (error: any) => {
|
||||||
|
|
||||||
|
|||||||
915
src/views/applyments/applyment_in.vue
Normal file
915
src/views/applyments/applyment_in.vue
Normal file
@@ -0,0 +1,915 @@
|
|||||||
|
<!-- 选择商户以及进件渠道 -->
|
||||||
|
<template>
|
||||||
|
<div class="gyq_container">
|
||||||
|
<div class="gyq_content" ref="containerRef">
|
||||||
|
<div class="row">
|
||||||
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="250px" label-position="right">
|
||||||
|
<el-form-item label="选择商户类型" prop="merchantBaseInfo.userType">
|
||||||
|
<el-radio-group v-model="form.merchantBaseInfo.userType">
|
||||||
|
<el-radio label="个体商户" value="0"></el-radio>
|
||||||
|
<el-radio label="企业商户" value="1"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<div class="title_row">
|
||||||
|
<div class="t">
|
||||||
|
<el-text size="large" type="primary">商户基础信息</el-text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-form-item label="企业类型" v-if="form.merchantBaseInfo.userType == '1'">
|
||||||
|
<el-radio-group v-model="form.merchantBaseInfo.companyChildType">
|
||||||
|
<el-radio label="普通企业" value="1"></el-radio>
|
||||||
|
<el-radio label="事业单位" value="2"></el-radio>
|
||||||
|
<el-radio label="政府机关" value="3"></el-radio>
|
||||||
|
<el-radio label="社会组织" value="4"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商户简称" prop="merchantBaseInfo.shortName">
|
||||||
|
<el-input v-model.trim="form.merchantBaseInfo.shortName" placeholder="请输入商户简称"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="行业类别码" prop="merchantBaseInfo.mccCode">
|
||||||
|
<selectCategory v-model="form.merchantBaseInfo.mccCode" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="支付宝账号" prop="merchantBaseInfo.alipayAccount">
|
||||||
|
<el-input v-model.trim="form.merchantBaseInfo.alipayAccount" placeholder="请输入支付宝账号"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="联系人类型">
|
||||||
|
<el-radio-group v-model="form.merchantBaseInfo.contactPersonType">
|
||||||
|
<el-radio label="经营者/法定代表人" :value="'LEGAL'"></el-radio>
|
||||||
|
<el-radio label="经办人" :value="'SUPER'"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="证件类型">
|
||||||
|
<el-radio-group v-model="form.merchantBaseInfo.certType">
|
||||||
|
<el-radio label="身份证" value="0"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="联系人身份证号" prop="merchantBaseInfo.contactPersonId">
|
||||||
|
<el-input v-model.trim="form.merchantBaseInfo.contactPersonId" placeholder="请输入联系人身份证号"
|
||||||
|
style="width: 300px;" v-loading="contactIdCardFrontPicUploadLoading"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="联系人证件有效期开始日期" prop="merchantBaseInfo.contactPersonIdStartDate"
|
||||||
|
v-loading="contactIdCardBackPicUploadLoading">
|
||||||
|
<el-date-picker v-model="form.merchantBaseInfo.contactPersonIdStartDate" type="date" placeholder="选择日期"
|
||||||
|
value-format="YYYY-MM-DD" style="width: 300px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="联系人证件有效期结束日期" prop="merchantBaseInfo.contactPersonIdEndDate"
|
||||||
|
v-loading="contactIdCardBackPicUploadLoading">
|
||||||
|
<div class="center">
|
||||||
|
<el-date-picker v-model="form.merchantBaseInfo.contactPersonIdEndDate" type="date" placeholder="选择日期"
|
||||||
|
value-format="YYYY-MM-DD" style="width: 300px;" />
|
||||||
|
<el-checkbox
|
||||||
|
@change="e => e ? form.merchantBaseInfo.contactPersonIdEndDate = longTime : form.merchantBaseInfo.contactPersonIdEndDate = ''">长期有效</el-checkbox>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="联系人身份证正面照片" prop="merchantBaseInfo.contactIdCardFrontPic.url">
|
||||||
|
<div class="column">
|
||||||
|
<single-image-upload :maxFileSize="2" v-model="form.merchantBaseInfo.contactIdCardFrontPic.url"
|
||||||
|
@on-success="contactIdCardFrontPicUpload" />
|
||||||
|
<div class="tips">国徽面为正面 (上传图片自动识别 有效期)</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="联系人身份证反面照片" prop="merchantBaseInfo.contactIdCardBackPic.url">
|
||||||
|
<div class="column">
|
||||||
|
<single-image-upload :maxFileSize="2" v-model="form.merchantBaseInfo.contactIdCardBackPic.url"
|
||||||
|
@on-success="contactIdCardBackPicUpload" />
|
||||||
|
<div class="tips">人像面为反面 (上传图片自动识别 身份证名称 身份证号)</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="联系人手机号" prop="merchantBaseInfo.contactPhone">
|
||||||
|
<el-input v-model.trim="form.merchantBaseInfo.contactPhone" placeholder="请输入联系人手机号"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="联系人地址" prop="merchantBaseInfo.contactAddr">
|
||||||
|
<el-input v-model.trim="form.merchantBaseInfo.contactAddr" placeholder="请输入联系人地址"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="联系人电子邮箱" prop="merchantBaseInfo.contactEmail">
|
||||||
|
<el-input v-model.trim="form.merchantBaseInfo.contactEmail" placeholder="请输入联系人电子邮箱"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<div class="title_row">
|
||||||
|
<div class="t">
|
||||||
|
<el-text size="large" type="primary">法人信息</el-text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-form-item label="身份证手持图片" prop="legalPersonInfo.idCardHandPic.url">
|
||||||
|
<single-image-upload :maxFileSize="2" v-model="form.legalPersonInfo.idCardHandPic.url" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="身份证正面图片" prop="legalPersonInfo.idCardFrontPic.url">
|
||||||
|
<div class="column">
|
||||||
|
<single-image-upload :maxFileSize="2" v-model="form.legalPersonInfo.idCardFrontPic.url"
|
||||||
|
@on-success="idCardFrontPicSuccess" />
|
||||||
|
<div class="tips">国徽面为正面 (上传图片自动识别 有效期)</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="身份证反面图片" prop="legalPersonInfo.idCardBackPic.url">
|
||||||
|
<div class="column">
|
||||||
|
<single-image-upload :maxFileSize="2" v-model="form.legalPersonInfo.idCardBackPic.url"
|
||||||
|
@on-success="idCardBackPicSuccess" />
|
||||||
|
<div class="tips">人像面为反面 (上传图片自动识别 身份证名称 身份证号)</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="法定代表人姓名" prop="legalPersonInfo.legalPersonName" v-loading="idCardFrontPicSuccessLoading">
|
||||||
|
<el-input v-model.trim="form.legalPersonInfo.legalPersonName" placeholder="请输入法定代表人姓名"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="法定代表人身份证号" prop="legalPersonInfo.legalPersonId" v-loading="idCardFrontPicSuccessLoading">
|
||||||
|
<el-input v-model.trim="form.legalPersonInfo.legalPersonId" placeholder="请输入法定代表人身份证号"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="法定代表人身份证开始日期" prop="legalPersonInfo.legalIdPersonStartDate"
|
||||||
|
v-loading="idCardBackPicSuccessLoading">
|
||||||
|
<el-date-picker v-model="form.legalPersonInfo.legalIdPersonStartDate" type="date" placeholder="选择日期"
|
||||||
|
value-format="YYYY-MM-DD" style="width: 300px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="法定代表人身份证结束日期" prop="legalPersonInfo.legalPersonIdEndDate"
|
||||||
|
v-loading="idCardBackPicSuccessLoading">
|
||||||
|
<div class="center">
|
||||||
|
<el-date-picker v-model="form.legalPersonInfo.legalPersonIdEndDate" type="date" placeholder="选择日期"
|
||||||
|
value-format="YYYY-MM-DD" style="width: 300px;" />
|
||||||
|
<el-checkbox
|
||||||
|
@change="e => e ? form.legalPersonInfo.legalPersonIdEndDate = longTime : form.legalPersonInfo.legalPersonIdEndDate = ''">长期有效</el-checkbox>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="法定代表人手机号" prop="legalPersonInfo.legalPersonPhone">
|
||||||
|
<el-input v-model.trim="form.legalPersonInfo.legalPersonPhone" placeholder="请输入法定代表人手机号"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="法定代表人电子邮箱" prop="legalPersonInfo.legalPersonEmail">
|
||||||
|
<el-input v-model.trim="form.legalPersonInfo.legalPersonEmail" placeholder="请输入法定代表人电子邮箱"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="法定代表人性别" prop="legalPersonInfo.legalGender">
|
||||||
|
<el-radio-group v-model="form.legalPersonInfo.legalGender">
|
||||||
|
<el-radio label="男" :value="'0'"></el-radio>
|
||||||
|
<el-radio label="女" :value="'1'"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="法定代表人联系地址" prop="legalPersonInfo.legalAddress">
|
||||||
|
<el-input v-model.trim="form.legalPersonInfo.legalAddress" placeholder="请输入法定代表人联系地址"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<div class="title_row">
|
||||||
|
<div class="t">
|
||||||
|
<el-text size="large" type="primary">营业执照信息</el-text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-form-item label="营业执照全称" prop="businessLicenceInfo.licenceName">
|
||||||
|
<el-input v-model.trim="form.businessLicenceInfo.licenceName" placeholder="请输入营业执照全称"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="营业执照注册号" prop="businessLicenceInfo.licenceNo" v-loading="licensePicSuccessLoading">
|
||||||
|
<el-input v-model.trim="form.businessLicenceInfo.licenceNo" placeholder="请输入营业执照注册号"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="营业执照有效期开始日期" prop="businessLicenceInfo.licenceStartDate">
|
||||||
|
<el-date-picker v-model="form.businessLicenceInfo.licenceStartDate" type="date" placeholder="选择日期"
|
||||||
|
value-format="YYYY-MM-DD" style="width: 300px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="营业执照有效期结束日期" prop="businessLicenceInfo.licenceEndDate">
|
||||||
|
<div class="center">
|
||||||
|
<el-date-picker v-model="form.businessLicenceInfo.licenceEndDate" type="date" placeholder="选择日期"
|
||||||
|
value-format="YYYY-MM-DD" style="width: 300px;" />
|
||||||
|
<el-checkbox
|
||||||
|
@change="e => e ? form.businessLicenceInfo.licenceEndDate = longTime : form.businessLicenceInfo.licenceEndDate = ''">长期有效</el-checkbox>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="注册地址" prop="businessLicenceInfo.registeredAddress">
|
||||||
|
<el-input v-model.trim="form.businessLicenceInfo.registeredAddress" placeholder="请输入注册地址"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="营业执照照片" prop="businessLicenceInfo.licensePic.url">
|
||||||
|
<div class="column">
|
||||||
|
<single-image-upload :maxFileSize="2" v-model="form.businessLicenceInfo.licensePic.url"
|
||||||
|
@on-success="licensePicSuccess" />
|
||||||
|
<div class="tips">(上传图片自动识别 营业执照编号)</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<div class="title_row">
|
||||||
|
<div class="t">
|
||||||
|
<el-text size="large" type="primary">门店信息</el-text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-form-item label="商户归属省市区" prop="storeInfo.mercProvCode">
|
||||||
|
<selectAddress v-model:provCode="form.storeInfo.mercProvCode" v-model:cityCode="form.storeInfo.mercCityCode"
|
||||||
|
v-model:areaCode="form.storeInfo.mercAreaCode" v-model:prov="form.storeInfo.mercProv"
|
||||||
|
v-model:city="form.storeInfo.mercCity" v-model:area="form.storeInfo.mercArea" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="营业地址" prop="storeInfo.businessAddress">
|
||||||
|
<el-input v-model.trim="form.storeInfo.businessAddress" placeholder="请输入营业地址"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="经营场所内设照片" prop="storeInfo.insidePic.url">
|
||||||
|
<single-image-upload :maxFileSize="2" v-model="form.storeInfo.insidePic.url" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="门头照" prop="storeInfo.doorPic.url">
|
||||||
|
<single-image-upload :maxFileSize="2" v-model="form.storeInfo.doorPic.url" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="收银台照" prop="storeInfo.cashierDeskPic.url">
|
||||||
|
<single-image-upload :maxFileSize="2" v-model="form.storeInfo.cashierDeskPic.url" />
|
||||||
|
</el-form-item>
|
||||||
|
<div class="title_row">
|
||||||
|
<div class="t">
|
||||||
|
<el-text size="large" type="primary">结算信息</el-text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-form-item label="结算类型" prop="settlementInfo.settlementType">
|
||||||
|
<el-radio-group v-model="form.settlementInfo.settlementType">
|
||||||
|
<el-radio label="非法人结算" value="0" disabled></el-radio>
|
||||||
|
<el-radio label="法人结算" value="1"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="结算卡类型" prop="settlementInfo.settlementCardType">
|
||||||
|
<el-radio-group v-model="form.settlementInfo.settlementCardType">
|
||||||
|
<el-radio label="对私借记卡" :value="'11'"></el-radio>
|
||||||
|
<el-radio label="对公借记卡" :value="'21'"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="结算卡号" prop="settlementInfo.settlementCardNo">
|
||||||
|
<el-input v-model.trim="form.settlementInfo.settlementCardNo" placeholder="请输入结算卡号"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="开户名称" prop="settlementInfo.settlementName" v-loading="bankCardFrontPicSuccessLoading">
|
||||||
|
<el-input v-model.trim="form.settlementInfo.settlementName" placeholder="请输入开户名称"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="结算银行预留手机号" prop="settlementInfo.bankMobile">
|
||||||
|
<el-input v-model.trim="form.settlementInfo.bankMobile" placeholder="请输入结算银行预留手机号"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="开户行省市区" prop="settlementInfo.openAccProvinceId">
|
||||||
|
<selectAddress v-model:wxProvinceCode="wxProvinceCode"
|
||||||
|
v-model:provCode="form.settlementInfo.openAccProvinceId"
|
||||||
|
v-model:cityCode="form.settlementInfo.openAccCityId" v-model:areaCode="form.settlementInfo.openAccAreaId"
|
||||||
|
v-model:prov="form.settlementInfo.openAccProvince" v-model:city="form.settlementInfo.openAccCity"
|
||||||
|
v-model:area="form.settlementInfo.openAccArea" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="开户行" prop="settlementInfo.bankInstId">
|
||||||
|
<selectBank :province="form.settlementInfo.openAccProvince" :city="form.settlementInfo.openAccCity"
|
||||||
|
:city-code="wxProvinceCode" v-model:bankInstId="form.settlementInfo.bankInstId"
|
||||||
|
v-model:bankName="form.settlementInfo.bankName"
|
||||||
|
v-model:bank-branch-code="form.settlementInfo.bankBranchCode"
|
||||||
|
v-model:bank-branch-name="form.settlementInfo.bankBranchName" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="银行卡正面" prop="settlementInfo.bankCardFrontPic.url">
|
||||||
|
<div class="column">
|
||||||
|
<SingleImageUpload :maxFileSize="2" v-model="form.settlementInfo.bankCardFrontPic.url"
|
||||||
|
@on-success="bankCardFrontPicSuccess" />
|
||||||
|
<div class="tips">(上传图片自动识别 银行卡号)</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="银行卡反面" prop="settlementInfo.bankCardBackPic.url">
|
||||||
|
<SingleImageUpload :maxFileSize="2" v-model="form.settlementInfo.bankCardBackPic.url" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="开户许可证" prop="settlementInfo.openAccountLicencePic.url">
|
||||||
|
<SingleImageUpload :maxFileSize="2" v-model="form.settlementInfo.openAccountLicencePic.url" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<div class="btn_wrap" :style="{ width: `${containerDomInfo.width}px`, left: `${containerDomInfo.left}px` }"
|
||||||
|
v-if="formType != 'check'">
|
||||||
|
<div class="btn_content">
|
||||||
|
<div class="btn">
|
||||||
|
<el-button type="primary" size="large" style="width: 100%;" :loading="loading"
|
||||||
|
@click="submitForm">提交</el-button>
|
||||||
|
</div>
|
||||||
|
<div class="btn">
|
||||||
|
<el-button style="width: 100%;" size="large" @click="router.back()">取消</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, onMounted, onUnmounted } from "vue";
|
||||||
|
import selectAddress from "./components/selectAddress.vue";
|
||||||
|
import selectBank from "./components/selectBank.vue";
|
||||||
|
import selectCategory from "./components/selectCategory.vue";
|
||||||
|
import SingleImageUpload from "@/components/Upload/SingleImageUpload.vue";
|
||||||
|
import { entryManagerPost, getInfoByImg, entryManagerDetail } from '@/api/common'
|
||||||
|
import _ from 'lodash'
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { isValidMobile } from "@/utils";
|
||||||
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const containerRef = ref<any>(null)
|
||||||
|
|
||||||
|
const containerDomInfo = ref({
|
||||||
|
left: 0,
|
||||||
|
width: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
const longTime = ref('2099-12-31')
|
||||||
|
|
||||||
|
const wxProvinceCode = ref('')
|
||||||
|
|
||||||
|
// 获取进件详情
|
||||||
|
async function getDetailAjax(shopId: string) {
|
||||||
|
try {
|
||||||
|
const res: any = await entryManagerDetail({
|
||||||
|
shopId: shopId
|
||||||
|
})
|
||||||
|
if (res && res.shopId) {
|
||||||
|
form.value = res
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取containerDomInfo信息
|
||||||
|
function getContainerDomInfo() {
|
||||||
|
containerDomInfo.value = containerRef.value?.getBoundingClientRect() ?? {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const debouncedCheckWidth = _.debounce(getContainerDomInfo, 100)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getContainerDomInfo()
|
||||||
|
window.addEventListener('resize', debouncedCheckWidth)
|
||||||
|
|
||||||
|
const type = route.query.type
|
||||||
|
const shopId: string = String(route.query.shopId ?? '')
|
||||||
|
const licenceNo: string = String(route.query.licenceNo ?? '')
|
||||||
|
|
||||||
|
if (shopId) {
|
||||||
|
getDetailAjax(shopId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (licenceNo && type && type == 'editor') {
|
||||||
|
formType.value = 'editor'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type && type == 'check') {
|
||||||
|
formType.value = 'check'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener('resize', debouncedCheckWidth)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 表单操作类型 add添加 editor编辑 check查看
|
||||||
|
const formType = ref('add')
|
||||||
|
const formRef = ref<any>(null);
|
||||||
|
const form = ref({
|
||||||
|
shopId: route.query.shopId,
|
||||||
|
merchantCode: '',
|
||||||
|
// 【必填】商户基础信息
|
||||||
|
merchantBaseInfo: {
|
||||||
|
userType: '0', // 0: 个体商户;1: 企业商户;3: 小微商户 暂不支持
|
||||||
|
shortName: '', // 商户简称--企业、个体必填
|
||||||
|
mccCode: '', // 行业类别码--必填
|
||||||
|
alipayAccount: '', // 【必填】支付宝账号
|
||||||
|
contactPersonType: 'LEGAL', // 联系人类型 LEGAL: 经营者/法定代表人 SUPER: 经办人 默认LEGAL
|
||||||
|
contactName: '', // 联系人姓名
|
||||||
|
certType: '0', // 证件类型 目前只支持身份证 传值:0
|
||||||
|
contactPersonId: '', // 联系人身份证号
|
||||||
|
contactPersonIdStartDate: '', // 联系人证件有效期开始日期
|
||||||
|
contactPersonIdEndDate: '', // 联系人证件有效期结束日期
|
||||||
|
// 联系人身份证反面照片
|
||||||
|
contactIdCardBackPic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
// 联系人身份证正面照片
|
||||||
|
contactIdCardFrontPic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
contactPhone: '', // 联系人手机号
|
||||||
|
contactAddr: '', // 联系人地址
|
||||||
|
contactEmail: '', // 联系人电子邮箱
|
||||||
|
companyChildType: '1', // 企业类型,1:普通企业,2:事业单位,3:政府机关,4:社会组织 默认值:1
|
||||||
|
},
|
||||||
|
// 【必填】法人信息
|
||||||
|
legalPersonInfo: {
|
||||||
|
legalPersonName: '', // 法定代表人姓名
|
||||||
|
legalPersonId: '', // 法定代表人身份证号
|
||||||
|
legalIdPersonStartDate: '', // 法定代表人证件有效期开始日期
|
||||||
|
legalPersonIdEndDate: '', // 法定代表人证件有效期结束日期
|
||||||
|
legalPersonPhone: '', // 法定代表人手机号
|
||||||
|
legalPersonEmail: '', // 法定代表人电子邮箱
|
||||||
|
legalGender: '', // 法人性别(0男 1女)
|
||||||
|
legalAddress: '', // 法人联系地址
|
||||||
|
// 身份证手持 图片
|
||||||
|
idCardHandPic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
// 身份证正面 图片
|
||||||
|
idCardFrontPic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
// 身份证反面 图片
|
||||||
|
idCardBackPic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 【必填】营业执照信息
|
||||||
|
businessLicenceInfo: {
|
||||||
|
licenceName: '', // 营业执照全称--非小微必填
|
||||||
|
licenceNo: '', // 营业执照注册号--非小微必填
|
||||||
|
licenceStartDate: '', // 营业执照有效期开始日期--非小微必填
|
||||||
|
licenceEndDate: '', // 营业执照有效期结束日期--非小微必填
|
||||||
|
registeredAddress: '', // 注册地址--非小微必填
|
||||||
|
licensePic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 【必填】门店信息
|
||||||
|
storeInfo: {
|
||||||
|
mercProvCode: '', // 【必填】商户归属省Code
|
||||||
|
mercCityCode: '', // 【必填】商户归属市Code
|
||||||
|
mercAreaCode: '', // 【必填】商户归属区Code
|
||||||
|
mercProv: '', // 商户归属省
|
||||||
|
mercCity: '', // 商户归属市
|
||||||
|
mercArea: '', // 商户归属区
|
||||||
|
businessAddress: '', // 【必填】 营业地址
|
||||||
|
// 经营场所内设照片
|
||||||
|
insidePic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
// 门头照
|
||||||
|
doorPic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
// 收银台照
|
||||||
|
cashierDeskPic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 【必填】结算信息
|
||||||
|
settlementInfo: {
|
||||||
|
settlementType: '1', // 结算类型 0:非法人结算, 1:法人结算
|
||||||
|
noLegalName: '', // 非法人姓名
|
||||||
|
noLegalId: '', // 非法人身份证号
|
||||||
|
settlementCardType: '', // 结算卡类型 必填 11 对私借记卡(结算卡正面照、结算卡反面照图片必传) 21 对公借记卡(只须结算卡正面照片)
|
||||||
|
settlementCardNo: '', // 结算卡号
|
||||||
|
settlementName: '', // 开户名称
|
||||||
|
bankMobile: '', // 结算银行预留手机号
|
||||||
|
openAccProvinceId: '', // 开户行省ID
|
||||||
|
openAccCityId: '', // 开户行市ID
|
||||||
|
openAccAreaId: '', // 开户行区ID
|
||||||
|
openAccProvince: '', // 开户行省
|
||||||
|
openAccCity: '', // 开户行市
|
||||||
|
openAccArea: '', // 开户行区
|
||||||
|
bankName: '', // 开户行别名名称 bankAlias
|
||||||
|
bankInstId: '', // 开户行缩写 bankCode
|
||||||
|
bankType: '', // 开户行编号 bankAliasCode
|
||||||
|
bankBranchName: '', // 支行开户行行别名称 branchName
|
||||||
|
bankBranchCode: '', // 支行开户行编号 bankCode
|
||||||
|
// 银行卡正面
|
||||||
|
bankCardFrontPic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
// 银行卡反面
|
||||||
|
bankCardBackPic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
// 开户许可证
|
||||||
|
openAccountLicencePic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
// 非法人手持结算授权书
|
||||||
|
noLegalHandSettleAuthPic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
// 非法人结算授权书
|
||||||
|
noLegalSettleAuthPic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
// 非法人身份证正面
|
||||||
|
noLegalIdCardFrontPic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
// 非法人身份证反面
|
||||||
|
noLegalIdCardBackPic: {
|
||||||
|
url: '',
|
||||||
|
wechatId: '', // 微信图片ID
|
||||||
|
alipayId: '', // 支付宝图片ID
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const rules = reactive({
|
||||||
|
'merchantBaseInfo.userType': [{ required: true, message: '请选择商户类型', trigger: 'change' }],
|
||||||
|
'merchantBaseInfo.shortName': [{ required: true, message: '请输入商户简称', trigger: 'blur' }],
|
||||||
|
'merchantBaseInfo.mccCode': [{ required: true, message: '请输入行业类别码', trigger: 'change' }],
|
||||||
|
'merchantBaseInfo.alipayAccount': [{ required: true, message: '请输入支付宝账号', trigger: 'blur' }],
|
||||||
|
'merchantBaseInfo.contactPersonId': [{ required: true, message: '请输入联系人身份证号', trigger: 'blur' }],
|
||||||
|
'merchantBaseInfo.contactPersonIdStartDate': [{ required: true, message: '请选择联系人证件有效期开始日期', trigger: 'change' }],
|
||||||
|
'merchantBaseInfo.contactPersonIdEndDate': [{ required: true, message: '请选择联系人证件有效期结束日期', trigger: 'change' }],
|
||||||
|
'merchantBaseInfo.contactIdCardFrontPic.url': [{ required: true, message: '请上传联系人身份证正面照片', trigger: 'blur' }],
|
||||||
|
'merchantBaseInfo.contactIdCardBackPic.url': [{ required: true, message: '请上传联系人身份证反面照片', trigger: 'blur' }],
|
||||||
|
'merchantBaseInfo.contactPhone': [
|
||||||
|
{ required: true, message: '请输入联系人手机号', trigger: 'blur' },
|
||||||
|
{
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!isValidMobile(value)) {
|
||||||
|
callback(new Error('请输入正确的手机号'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'merchantBaseInfo.contactAddr': [{ required: true, message: '请输入联系人地址', trigger: 'blur' }],
|
||||||
|
'merchantBaseInfo.contactEmail': [{ required: true, message: '请输入联系人电子邮箱', trigger: 'blur' }],
|
||||||
|
'legalPersonInfo.idCardHandPic.url': [{ required: true, message: '请上传身份证手持图片', trigger: 'blur' }],
|
||||||
|
'legalPersonInfo.idCardFrontPic.url': [{ required: true, message: '请上传身份证正面图片', trigger: 'blur' }],
|
||||||
|
'legalPersonInfo.idCardBackPic.url': [{ required: true, message: '请上传身份证反面图片', trigger: 'blur' }],
|
||||||
|
'legalPersonInfo.legalPersonName': [{ required: true, message: '请输入法定代表人姓名', trigger: 'blur' }],
|
||||||
|
'legalPersonInfo.legalPersonId': [{ required: true, message: '请输入法定代表人身份证号', trigger: 'blur' }],
|
||||||
|
'legalPersonInfo.legalIdPersonStartDate': [{ required: true, message: '请输入法定代表人身份证开始日期', trigger: 'blur' }],
|
||||||
|
'legalPersonInfo.legalPersonIdEndDate': [{ required: true, message: '请输入法定代表人身份证结束日期', trigger: 'blur' }],
|
||||||
|
'legalPersonInfo.legalPersonPhone': [
|
||||||
|
{ required: true, message: '请输入法定代表人手机号', trigger: 'blur' },
|
||||||
|
{
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!isValidMobile(value)) {
|
||||||
|
callback(new Error('请输入正确的手机号'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'legalPersonInfo.legalPersonEmail': [{ required: true, message: '请输入法定代表人电子邮箱', trigger: 'blur' }],
|
||||||
|
'legalPersonInfo.legalGender': [{ required: true, message: '请选择法定代表人性别', trigger: 'change' }],
|
||||||
|
'legalPersonInfo.legalAddress': [{ required: true, message: '请输入法定代表人联系地址', trigger: 'blur' }],
|
||||||
|
// 营业执照信息
|
||||||
|
'businessLicenceInfo.licenceName': [{ required: true, message: '请输入营业执照全称', trigger: 'blur' }],
|
||||||
|
'businessLicenceInfo.licenceNo': [{ required: true, message: '请输入营业执照注册号', trigger: 'blur' }],
|
||||||
|
'businessLicenceInfo.licenceStartDate': [{ required: true, message: '请输入营业执照有效期开始日期', trigger: 'blur' }],
|
||||||
|
'businessLicenceInfo.licenceEndDate': [{ required: true, message: '请输入营业执照有效期结束日期', trigger: 'blur' }],
|
||||||
|
'businessLicenceInfo.registeredAddress': [{ required: true, message: '请输入注册地址', trigger: 'blur' }],
|
||||||
|
'businessLicenceInfo.licensePic.url': [{ required: true, message: '请上传营业执照照片', trigger: 'blur' }],
|
||||||
|
// 门店信息
|
||||||
|
'storeInfo.mercProvCode': [{ required: true, message: '请选择商户归属省市区', trigger: 'change' }],
|
||||||
|
'storeInfo.mercCityCode': [{ required: true, message: '请选择商户归属市', trigger: 'change' }],
|
||||||
|
'storeInfo.mercAreaCode': [{ required: true, message: '请选择商户归属区', trigger: 'change' }],
|
||||||
|
'storeInfo.businessAddress': [{ required: true, message: '请输入营业地址', trigger: 'blur' }],
|
||||||
|
'storeInfo.insidePic.url': [{ required: true, message: '请上传经营场所内设照片', trigger: 'blur' }],
|
||||||
|
'storeInfo.doorPic.url': [{ required: true, message: '请上传门头照', trigger: 'blur' }],
|
||||||
|
'storeInfo.cashierDeskPic.url': [{ required: true, message: '请上传收银台照', trigger: 'blur' }],
|
||||||
|
// 结算信息
|
||||||
|
'settlementInfo.settlementType': [{ required: true, message: '请选择结算类型', trigger: 'change' }],
|
||||||
|
'settlementInfo.settlementCardType': [{ required: true, message: '请选择结算卡类型', trigger: 'change' }],
|
||||||
|
'settlementInfo.settlementCardNo': [{ required: true, message: '请输入结算卡号', trigger: 'blur' }],
|
||||||
|
'settlementInfo.settlementName': [{ required: true, message: '请输入开户名称', trigger: 'blur' }],
|
||||||
|
'settlementInfo.bankMobile': [
|
||||||
|
{ required: true, message: '请输入结算银行预留手机号', trigger: 'blur' },
|
||||||
|
{
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!isValidMobile(value)) {
|
||||||
|
callback(new Error('请输入正确的手机号'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'settlementInfo.openAccProvinceId': [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (form.value.settlementInfo.openAccProvinceId == '' || form.value.settlementInfo.openAccCityId == '' || form.value.settlementInfo.openAccAreaId == '') {
|
||||||
|
callback(new Error('请选择开户行省市区'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'settlementInfo.bankInstId': [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (form.value.settlementInfo.bankInstId == '') {
|
||||||
|
callback(new Error('请选择开户行以及支行'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'settlementInfo.bankCardFrontPic.url': [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请上传银行卡正面图片',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'settlementInfo.bankCardBackPic.url': [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请上传银行卡反面图片',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'settlementInfo.openAccountLicencePic.url': [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请上传开户许可证图片',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 联系人身份证正面照片
|
||||||
|
const contactIdCardFrontPicUploadLoading = ref(false)
|
||||||
|
async function contactIdCardFrontPicUpload(url: string) {
|
||||||
|
try {
|
||||||
|
form.value.merchantBaseInfo.contactIdCardBackPic.alipayId = ''
|
||||||
|
form.value.merchantBaseInfo.contactIdCardBackPic.wechatId = ''
|
||||||
|
|
||||||
|
contactIdCardFrontPicUploadLoading.value = true
|
||||||
|
const res: any = await getInfoByImg({
|
||||||
|
url: url,
|
||||||
|
type: 'IdCard'
|
||||||
|
})
|
||||||
|
|
||||||
|
let date = res.subImages[0].kvInfo.data.validPeriod.split('-')
|
||||||
|
form.value.merchantBaseInfo.contactPersonIdStartDate = dayjs(date[0]).format('YYYY-MM-DD')
|
||||||
|
form.value.merchantBaseInfo.contactPersonIdEndDate = dayjs(date[1]).format('YYYY-MM-DD')
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
contactIdCardFrontPicUploadLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 联系人身份证反面照片
|
||||||
|
const contactIdCardBackPicUploadLoading = ref(false)
|
||||||
|
async function contactIdCardBackPicUpload(url: any) {
|
||||||
|
try {
|
||||||
|
form.value.merchantBaseInfo.contactIdCardFrontPic.alipayId = ''
|
||||||
|
form.value.merchantBaseInfo.contactIdCardFrontPic.wechatId = ''
|
||||||
|
|
||||||
|
contactIdCardBackPicUploadLoading.value = true
|
||||||
|
const res: any = await getInfoByImg({
|
||||||
|
url: url,
|
||||||
|
type: 'IdCard'
|
||||||
|
})
|
||||||
|
form.value.merchantBaseInfo.contactPersonId = res.subImages[0].kvInfo.data.idNumber
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
contactIdCardBackPicUploadLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 法人信息 身份证正面图片
|
||||||
|
const idCardFrontPicSuccessLoading = ref(false)
|
||||||
|
async function idCardFrontPicSuccess(url: string) {
|
||||||
|
try {
|
||||||
|
form.value.legalPersonInfo.idCardBackPic.alipayId = ''
|
||||||
|
form.value.legalPersonInfo.idCardBackPic.wechatId = ''
|
||||||
|
|
||||||
|
idCardFrontPicSuccessLoading.value = true
|
||||||
|
const res: any = await getInfoByImg({
|
||||||
|
url: url,
|
||||||
|
type: 'IdCard'
|
||||||
|
})
|
||||||
|
|
||||||
|
let date = res.subImages[0].kvInfo.data.validPeriod.split('-')
|
||||||
|
form.value.legalPersonInfo.legalIdPersonStartDate = dayjs(date[0]).format('YYYY-MM-DD')
|
||||||
|
form.value.legalPersonInfo.legalPersonIdEndDate = dayjs(date[1]).format('YYYY-MM-DD')
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
idCardFrontPicSuccessLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 法人信息 身份证反图片
|
||||||
|
const idCardBackPicSuccessLoading = ref(false)
|
||||||
|
async function idCardBackPicSuccess(url: string) {
|
||||||
|
try {
|
||||||
|
form.value.legalPersonInfo.idCardFrontPic.alipayId = ''
|
||||||
|
form.value.legalPersonInfo.idCardFrontPic.wechatId = ''
|
||||||
|
|
||||||
|
idCardBackPicSuccessLoading.value = true
|
||||||
|
const res: any = await getInfoByImg({
|
||||||
|
url: url,
|
||||||
|
type: 'IdCard'
|
||||||
|
})
|
||||||
|
|
||||||
|
form.value.legalPersonInfo.legalPersonName = res.subImages[0].kvInfo.data.name
|
||||||
|
form.value.legalPersonInfo.legalPersonId = res.subImages[0].kvInfo.data.idNumber
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
idCardBackPicSuccessLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 营业执照信息 营业执照照片
|
||||||
|
const licensePicSuccessLoading = ref(false)
|
||||||
|
async function licensePicSuccess(url: string) {
|
||||||
|
try {
|
||||||
|
form.value.businessLicenceInfo.licensePic.alipayId = ''
|
||||||
|
form.value.businessLicenceInfo.licensePic.wechatId = ''
|
||||||
|
|
||||||
|
licensePicSuccessLoading.value = true
|
||||||
|
const res: any = await getInfoByImg({
|
||||||
|
url: url,
|
||||||
|
type: 'BusinessLicense'
|
||||||
|
})
|
||||||
|
let data = res.subImages[0].kvInfo.data
|
||||||
|
// console.log('营业执照照片', data);
|
||||||
|
form.value.businessLicenceInfo.licenceName = data.companyName
|
||||||
|
form.value.businessLicenceInfo.licenceNo = data.creditCode
|
||||||
|
// form.value.businessLicenceInfo.licenceStartDate = data.companyName
|
||||||
|
// form.value.businessLicenceInfo.licenceEndDate = data.companyName
|
||||||
|
form.value.businessLicenceInfo.registeredAddress = data.businessAddress
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
licensePicSuccessLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 结算信息 银行卡正面
|
||||||
|
const bankCardFrontPicSuccessLoading = ref(false)
|
||||||
|
async function bankCardFrontPicSuccess(url: string) {
|
||||||
|
try {
|
||||||
|
form.value.settlementInfo.bankCardFrontPic.alipayId = ''
|
||||||
|
form.value.settlementInfo.bankCardFrontPic.wechatId = ''
|
||||||
|
|
||||||
|
bankCardFrontPicSuccessLoading.value = true
|
||||||
|
const res: any = await getInfoByImg({
|
||||||
|
url: url,
|
||||||
|
type: 'BankCard'
|
||||||
|
})
|
||||||
|
let data = res.subImages[0].kvInfo.data
|
||||||
|
// console.log('银行卡正面', data);
|
||||||
|
form.value.settlementInfo.settlementCardNo = data.cardNumber
|
||||||
|
form.value.settlementInfo.bankName = data.bankName
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
bankCardFrontPicSuccessLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
function submitForm() {
|
||||||
|
console.log('提交的表单数据:', form.value);
|
||||||
|
console.log('formRef', formRef.value);
|
||||||
|
formRef.value.validate(async (valid: boolean) => {
|
||||||
|
console.log('valid===', valid);
|
||||||
|
if (valid) {
|
||||||
|
console.log('表单验证通过,可以提交');
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
await entryManagerPost(form.value)
|
||||||
|
ElNotification({
|
||||||
|
title: '注意',
|
||||||
|
message: '提交成功',
|
||||||
|
type: 'success'
|
||||||
|
})
|
||||||
|
router.back()
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
} else {
|
||||||
|
console.log('表单验证失败,请检查输入项');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.gyq_container {
|
||||||
|
padding: 14px;
|
||||||
|
|
||||||
|
.gyq_content {
|
||||||
|
padding: 14px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding-bottom: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
&.mt14 {
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
--bg: #ffeed8;
|
||||||
|
font-size: 12px;
|
||||||
|
background-color: var(--bg);
|
||||||
|
color: #c57000;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin-top: 15px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
background-color: var(--bg);
|
||||||
|
border: 1px solid var(--bg);
|
||||||
|
border-radius: 4px;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
top: -7px;
|
||||||
|
left: 40px;
|
||||||
|
transform-origin: center;
|
||||||
|
translate: -50% 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title_row {
|
||||||
|
padding: 14px 50px;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: "";
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 1px solid #ececec;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 50%;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 0 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn_wrap {
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 10;
|
||||||
|
bottom: 10px;
|
||||||
|
padding-bottom: 24px;
|
||||||
|
|
||||||
|
.btn_content {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 14px;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
165
src/views/applyments/components/selectAddress.vue
Normal file
165
src/views/applyments/components/selectAddress.vue
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
<template>
|
||||||
|
<div class="center">
|
||||||
|
<el-select placeholder="请选择省" style="width: 100px" v-model="provCode" @change="provChange">
|
||||||
|
<el-option
|
||||||
|
v-for="item in provList"
|
||||||
|
:key="item.regionId"
|
||||||
|
:label="item.regionName"
|
||||||
|
:value="item.regionId"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-select
|
||||||
|
placeholder="请选择市"
|
||||||
|
style="width: 100px"
|
||||||
|
:disabled="!provCode"
|
||||||
|
v-model="cityCode"
|
||||||
|
@change="cityChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in cityList"
|
||||||
|
:key="item.regionId"
|
||||||
|
:label="item.regionName"
|
||||||
|
:value="item.regionId"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<el-select
|
||||||
|
placeholder="请选择区"
|
||||||
|
style="width: 100px"
|
||||||
|
:disabled="!cityCode"
|
||||||
|
v-model="areaCode"
|
||||||
|
@change="areaChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in areaList"
|
||||||
|
:key="item.regionId"
|
||||||
|
:label="item.regionName"
|
||||||
|
:value="item.regionId"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from "vue";
|
||||||
|
import { getRegion } from "@/api/common";
|
||||||
|
|
||||||
|
const provList = ref<any[]>([]);
|
||||||
|
const cityList = ref<any[]>([]);
|
||||||
|
const areaList = ref<any[]>([]);
|
||||||
|
|
||||||
|
const provCode = defineModel("provCode", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听省份code变化
|
||||||
|
watch(
|
||||||
|
provCode,
|
||||||
|
async (n, o) => {
|
||||||
|
await getRegionAjax();
|
||||||
|
if (n && n !== undefined) {
|
||||||
|
provChange(n, true);
|
||||||
|
|
||||||
|
// 监听市区code变化
|
||||||
|
watch(
|
||||||
|
cityCode,
|
||||||
|
async (n, o) => {
|
||||||
|
if (n !== undefined && n) {
|
||||||
|
cityChange(n, true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true, // 可选:初始化立即执行,验证是否监听到初始值
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true, // 可选:初始化立即执行,验证是否监听到初始值
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const cityCode = defineModel("cityCode", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const areaCode = defineModel("areaCode", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const prov = defineModel("prov", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const city = defineModel("city", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const area = defineModel("area", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const wxProvinceCode = defineModel("wxProvinceCode", {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 省份变化 e code isEcho是否回显
|
||||||
|
function provChange(e: string, isEcho: boolean = false) {
|
||||||
|
if (!isEcho) {
|
||||||
|
cityCode.value = "";
|
||||||
|
areaCode.value = "";
|
||||||
|
cityList.value = [];
|
||||||
|
areaList.value = [];
|
||||||
|
}
|
||||||
|
const provObj = provList.value.find((item) => item.regionId == e);
|
||||||
|
prov.value = provObj ? provObj.regionName : "";
|
||||||
|
if (provObj && provObj.children) {
|
||||||
|
cityList.value = provObj.children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 市区变化
|
||||||
|
function cityChange(e: string, isEcho: boolean = false) {
|
||||||
|
if (!isEcho) {
|
||||||
|
areaCode.value = "";
|
||||||
|
areaList.value = [];
|
||||||
|
}
|
||||||
|
const cityObj = cityList.value.find((item) => item.regionId == e);
|
||||||
|
|
||||||
|
city.value = cityObj ? cityObj.regionName : "";
|
||||||
|
if (cityObj && cityObj.children) {
|
||||||
|
areaList.value = cityObj.children;
|
||||||
|
wxProvinceCode.value = cityObj.wxProvinceCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 区变化
|
||||||
|
function areaChange(e: string) {
|
||||||
|
const areaObj = areaList.value.find((item) => item.regionId == e);
|
||||||
|
area.value = areaObj ? areaObj.regionName : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取省市区数据
|
||||||
|
async function getRegionAjax() {
|
||||||
|
try {
|
||||||
|
const res = await getRegion();
|
||||||
|
provList.value = res;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取省市区数据失败:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.center {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
145
src/views/applyments/components/selectBank.vue
Normal file
145
src/views/applyments/components/selectBank.vue
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
<template>
|
||||||
|
<div class="select_bank">
|
||||||
|
<!-- 银行 -->
|
||||||
|
<el-select v-model="bankInstId" placeholder="请选择银行,可搜索" style="width: 200px;" filterable remote
|
||||||
|
:remote-method="remoteGetBank" :loading="loading" remote-show-suffix @change="bankChange" :disabled="!province">
|
||||||
|
<el-option v-for="item in bankList" :key="item.bankAliasCode" :label="item.bankAlias" :value="item.bankCode" />
|
||||||
|
</el-select>
|
||||||
|
<!-- 支行 -->
|
||||||
|
<el-select v-model="bankBranchCode" placeholder="请选择支行" style="width: 200px;" :disabled="!bankInstId"
|
||||||
|
@change="bankBranchChange">
|
||||||
|
<el-option v-for="item in bankBranchList" :key="item.bank_branch_id" :label="item.bank_branch_name"
|
||||||
|
:value="item.bank_branch_id"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, watch } from "vue";
|
||||||
|
import { getBankInfo, getBankBranchList } from "@/api/common";
|
||||||
|
|
||||||
|
const loading = ref(false)
|
||||||
|
const bankNameValue = ref('')
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
province: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
city: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
cityCode: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => props.cityCode, async (newValue, oldValue) => {
|
||||||
|
try {
|
||||||
|
// console.log('watch.props.cityCode===', `newValue=${newValue},oldValue=${oldValue}`);
|
||||||
|
await getBankInfoAjax()
|
||||||
|
if (newValue && newValue !== undefined) {
|
||||||
|
// 监听银行code变化
|
||||||
|
watch(bankInstId, (n, o) => {
|
||||||
|
if (n !== undefined && n) {
|
||||||
|
bankChange(n)
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
immediate: true // 可选:初始化立即执行,验证是否监听到初始值
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const bankList = ref<Array<{ id: string; bankAlias: string, bankCode: string, bankAliasCode: string, accountBank: string }>>([]);
|
||||||
|
|
||||||
|
const bankInstId = defineModel('bankInstId', {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const bankName = defineModel('bankName', {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
|
||||||
|
// 选择银行
|
||||||
|
function bankChange(e: any) {
|
||||||
|
let obj = bankList.value.find(item => item.bankCode == e)
|
||||||
|
if (obj && obj.id) {
|
||||||
|
bankName.value = obj.accountBank
|
||||||
|
bankInstId.value = obj.bankCode
|
||||||
|
getBankBranchListAjax(obj.bankAliasCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支行开户行编号 bankCode
|
||||||
|
const bankBranchCode = defineModel('bankBranchCode', {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
|
||||||
|
// 支行开户行行别名称 branchName
|
||||||
|
const bankBranchName = defineModel('bankBranchName', {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
})
|
||||||
|
|
||||||
|
// 选择支行
|
||||||
|
function bankBranchChange(e: string) {
|
||||||
|
let obj = bankBranchList.value.find(item => item.bank_branch_id == e)
|
||||||
|
if (obj && obj.bank_branch_id) {
|
||||||
|
bankBranchName.value = obj.bank_branch_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 支行列表
|
||||||
|
const bankBranchList = ref<Array<{ bank_branch_id: string; bank_branch_name: string }>>([]);
|
||||||
|
async function getBankBranchListAjax(bankAliasCode: string) {
|
||||||
|
try {
|
||||||
|
const res: any = await getBankBranchList({
|
||||||
|
bankAliceCode: bankAliasCode,
|
||||||
|
cityCode: props.cityCode
|
||||||
|
})
|
||||||
|
bankBranchList.value = res.data
|
||||||
|
} catch (error) {
|
||||||
|
console.log('', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 远程搜索
|
||||||
|
function remoteGetBank(query: string) {
|
||||||
|
if (query) {
|
||||||
|
bankNameValue.value = query
|
||||||
|
getBankInfoAjax()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取银行列表
|
||||||
|
async function getBankInfoAjax() {
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
const res: any = await getBankInfo({
|
||||||
|
page: 1,
|
||||||
|
size: 100,
|
||||||
|
bankName: bankNameValue.value
|
||||||
|
});
|
||||||
|
bankList.value = res.records || [];
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.select_bank {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
43
src/views/applyments/components/selectCategory.vue
Normal file
43
src/views/applyments/components/selectCategory.vue
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<template>
|
||||||
|
<el-cascader v-model="modelValue" placeholder="请选择类目" filterable :options="options" :props="props"
|
||||||
|
style="width: 300px;"></el-cascader>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { getCategory } from '@/api/common'
|
||||||
|
|
||||||
|
const modelValue = defineModel({
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const options = ref([])
|
||||||
|
|
||||||
|
const props = ref({
|
||||||
|
children: 'child',
|
||||||
|
emitPath: false
|
||||||
|
})
|
||||||
|
|
||||||
|
// 获取类目
|
||||||
|
async function getCategoryAjax() {
|
||||||
|
try {
|
||||||
|
const res = await getCategory()
|
||||||
|
res.map(item => {
|
||||||
|
item.label = item.firstCategory
|
||||||
|
item.child.map(val => {
|
||||||
|
val.label = `${val.secondCategory}`
|
||||||
|
val.value = `${val.firstCategoryCode}_${val.secondCategoryCode}`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
options.value = res
|
||||||
|
console.log('options.value', options.value);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getCategoryAjax()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
162
src/views/applyments/components/selectShopsDialog.vue
Normal file
162
src/views/applyments/components/selectShopsDialog.vue
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog title="请选择用户" width="1000px" v-model="visible">
|
||||||
|
<div class="content">
|
||||||
|
<el-form :model="queryForm" inline>
|
||||||
|
<!-- <el-form-item>
|
||||||
|
<el-input v-model="queryForm.no" placeholder="请输入商户号" />
|
||||||
|
</el-form-item> -->
|
||||||
|
<el-form-item>
|
||||||
|
<el-input v-model="queryForm.shopName" placeholder="请输入商户名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" :loading="tableData.loading" @click="searchHandle">查询</el-button>
|
||||||
|
<el-button icon="Refresh" :loading="tableData.loading" @click="resetHandle">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-table :data="tableData.list" v-loading="tableData.loading" stripe border
|
||||||
|
style="width: 100%; margin-top: 20px;">
|
||||||
|
<el-table-column label="商户名称" prop="shopName"></el-table-column>
|
||||||
|
<el-table-column label="联系人姓名" prop="contactName"></el-table-column>
|
||||||
|
<el-table-column label="联系人电话" prop="phone"></el-table-column>
|
||||||
|
<el-table-column label="店铺类型" prop="shopType" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag :type="typeFilter(scope.row.shopType).type">{{ typeFilter(scope.row.shopType).label }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button type="primary" @click="selectHandle(scope.row)">选择</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="row mt14">
|
||||||
|
<el-pagination v-model:current-page="tableData.page" v-model:page-size="tableData.size"
|
||||||
|
:page-sizes="[10, 30, 50, 100]" background layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="tableData.total" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="">确定</el-button>
|
||||||
|
</div>
|
||||||
|
</template> -->
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, onMounted } from "vue";
|
||||||
|
import ShopApi from "@/api/account/shop";
|
||||||
|
|
||||||
|
// 店铺类型过滤器
|
||||||
|
type TagType = 'primary' | 'success' | 'danger' | 'info' | 'warning';
|
||||||
|
function typeFilter(shopType: string): { value: string; label: string; type: TagType } {
|
||||||
|
const typs: Array<{ value: string; label: string; type: TagType }> = [
|
||||||
|
{
|
||||||
|
value: 'only',
|
||||||
|
label: '单店',
|
||||||
|
type: 'primary'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'chain',
|
||||||
|
label: '连锁',
|
||||||
|
type: 'success'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'join',
|
||||||
|
label: '加盟',
|
||||||
|
type: 'danger'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const obj = typs.find(item => item.value === shopType);
|
||||||
|
return obj ? obj : { value: shopType, label: shopType, type: 'info' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
|
||||||
|
const queryForm = ref({
|
||||||
|
shopName: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// 分页大小发生变化
|
||||||
|
function handleSizeChange(e: number) {
|
||||||
|
tableData.size = e;
|
||||||
|
getTableData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页发生变化
|
||||||
|
function handleCurrentChange(e: number) {
|
||||||
|
tableData.page = e;
|
||||||
|
getTableData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
function searchHandle() {
|
||||||
|
tableData.page = 1;
|
||||||
|
getTableData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
function resetHandle() {
|
||||||
|
queryForm.value.shopName = "";
|
||||||
|
tableData.page = 1;
|
||||||
|
getTableData();
|
||||||
|
}
|
||||||
|
|
||||||
|
const tableData = reactive({
|
||||||
|
loading: false,
|
||||||
|
page: 1,
|
||||||
|
size: 10,
|
||||||
|
total: 0,
|
||||||
|
list: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取店铺列表
|
||||||
|
async function getTableData() {
|
||||||
|
try {
|
||||||
|
tableData.loading = true;
|
||||||
|
const res: any = await ShopApi.getList({
|
||||||
|
page: tableData.page,
|
||||||
|
size: tableData.size,
|
||||||
|
shopName: queryForm.value.shopName,
|
||||||
|
});
|
||||||
|
tableData.list = res.records;
|
||||||
|
tableData.total = res.totalRow;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
} finally {
|
||||||
|
tableData.loading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
(e: 'success', row: any): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
function selectHandle(row: any) {
|
||||||
|
console.log("选择商户:", row);
|
||||||
|
emits('success', row);
|
||||||
|
visible.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function show() {
|
||||||
|
visible.value = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
show,
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getTableData();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.row {
|
||||||
|
&.mt14 {
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
63
src/views/applyments/components/singCodeDialog.vue
Normal file
63
src/views/applyments/components/singCodeDialog.vue
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog title="签约码" width="350px" v-model="visible">
|
||||||
|
<div class="wrap">
|
||||||
|
<el-image :src="srcUrl" style="width: 200px;height: 200px;"></el-image>
|
||||||
|
<el-text>请前往{{ type == 1 ? '支付宝' : '微信' }}进行扫码</el-text>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import QRCode from 'qrcode'
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
|
||||||
|
const srcUrl = ref('')
|
||||||
|
const type = ref(1)
|
||||||
|
|
||||||
|
// 手动生成二维码
|
||||||
|
async function generateQrcode(text) {
|
||||||
|
try {
|
||||||
|
// 生成 Base64 格式的二维码图片
|
||||||
|
const base64 = await QRCode.toDataURL(text, {
|
||||||
|
width: 200,
|
||||||
|
margin: 1,
|
||||||
|
color: {
|
||||||
|
dark: '#000',
|
||||||
|
light: '#fff'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
url.value = base64
|
||||||
|
} catch (err) {
|
||||||
|
console.error('生成二维码失败:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示二维码弹窗
|
||||||
|
function show(url, t) {
|
||||||
|
// console.log(url);
|
||||||
|
visible.value = true
|
||||||
|
type.value = t
|
||||||
|
if (t == 2) {
|
||||||
|
srcUrl.value = url
|
||||||
|
} else {
|
||||||
|
generateQrcode(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
show
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.wrap {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 14px;
|
||||||
|
padding-bottom: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
312
src/views/applyments/index.vue
Normal file
312
src/views/applyments/index.vue
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
<!-- 进件管理 -->
|
||||||
|
<template>
|
||||||
|
<div class="gyq_container">
|
||||||
|
<div class="gyq_content">
|
||||||
|
<div class="row">
|
||||||
|
<el-form :model="queryForm" inline>
|
||||||
|
<el-form-item label="商户类型">
|
||||||
|
<el-select v-model="queryForm.userType" style="width: 200px;">
|
||||||
|
<el-option v-for="item in userTypeList" :key="item.value" :label="item.label"
|
||||||
|
:value="item.value"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="店铺名称">
|
||||||
|
<el-input style="width: 200px;" v-model="queryForm.shopName" placeholder="请输入店铺名称"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="进件状态">
|
||||||
|
<el-select v-model="queryForm.status" style="width: 200px;">
|
||||||
|
<el-option v-for="item in statusList" :key="item.value" :label="item.label"
|
||||||
|
:value="item.value"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="支付宝账号">
|
||||||
|
<el-input style="width: 200px;" v-model="queryForm.alipayAccount" placeholder="请输入支付宝账号"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" :loading="tableData.loading" @click="queryHandle">查询</el-button>
|
||||||
|
<el-button icon="Refresh" :loading="tableData.loading" @click="resetHandle">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<el-button type="primary" icon="Plus" @click="selectShopsDialogRef?.show()">发起进件</el-button>
|
||||||
|
</div>
|
||||||
|
<div class="row mt14">
|
||||||
|
<el-table :data="tableData.list" v-loading="tableData.loading" stripe border>
|
||||||
|
<el-table-column label="商户号" prop="merchantCode" width="200"></el-table-column>
|
||||||
|
<el-table-column label="商户简称" prop="shortName" width="150"></el-table-column>
|
||||||
|
<el-table-column label="商户类型" prop="userType" width="120">
|
||||||
|
<template v-slot="scope">
|
||||||
|
{{ userTypeListFilter(scope.row.userType).label }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="绑定店铺名称" prop="shopName" width="200"></el-table-column>
|
||||||
|
<el-table-column label="支付宝进件状态" prop="alipayStatus" min-width="200">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<div class="column">
|
||||||
|
<div>
|
||||||
|
<el-tag :type="statusListFilter(scope.row.alipayStatus).type" disable-transitions>{{
|
||||||
|
statusListFilter(scope.row.alipayStatus).label }}</el-tag>
|
||||||
|
</div>
|
||||||
|
<div class="error_text" v-if="scope.row.alipayStatus == 'REJECTED'">
|
||||||
|
{{ scope.row.alipayErrorMsg }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-link type="primary" v-if="scope.row.alipayStatus == 'SIGN '"
|
||||||
|
@click="singCodeDialogRef?.show(scope.row.alipaySignUrl, 1)">查看签约码</el-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="微信进件状态" prop="wechatStatus" min-width="200">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<div class="column">
|
||||||
|
<div>
|
||||||
|
<el-tag :type="statusListFilter(scope.row.wechatStatus).type" disable-transitions>{{
|
||||||
|
statusListFilter(scope.row.wechatStatus).label }}</el-tag>
|
||||||
|
</div>
|
||||||
|
<div class="error_text" v-if="scope.row.wechatStatus == 'REJECTED'">
|
||||||
|
{{ scope.row.wechatErrorMsg }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-link type="primary" v-if="scope.row.wechatStatus == 'SIGN'"
|
||||||
|
@click="singCodeDialogRef?.show(scope.row.wechatSignUrl, 2)">查看签约码</el-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="更新时间" prop="updateTime" width="200"></el-table-column>
|
||||||
|
<el-table-column label="创建时间" prop="createTime" width="200"></el-table-column>
|
||||||
|
<el-table-column label="操作" fixed="right" width="160">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<el-button link type="primary"
|
||||||
|
v-if="scope.row.wechatStatus == 'INIT' || scope.row.wechatStatus == 'AUDIT' || scope.row.wechatStatus == 'SIGN' || scope.row.alipayStatus == 'INIT' || scope.row.alipayStatus == 'AUDIT' || scope.row.alipayStatus == 'SIGN'"
|
||||||
|
@click="checkStatusHandle(scope.row)">查询</el-button>
|
||||||
|
<el-button link type="primary" @click="toDetail(scope.row, 'check')">详情</el-button>
|
||||||
|
<el-button link type="primary" @click="toDetail(scope.row, 'editor')"
|
||||||
|
v-if="scope.row.alipayStatus == 'REJECTED' || scope.row.wechatStatus == 'REJECTED'">修改</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<div class="row mt14">
|
||||||
|
<el-pagination v-model:current-page="tableData.page" v-model:page-size="tableData.size"
|
||||||
|
:page-sizes="[10, 30, 50, 100]" background layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="tableData.total" @size-change="handleSizeChange" @current-change="handleCurrentChange" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 选择商户 -->
|
||||||
|
<selectShopsDialog ref="selectShopsDialogRef" @success="selectSuccessHandle" />
|
||||||
|
<!-- 显示签约码 -->
|
||||||
|
<singCodeDialog ref="singCodeDialogRef" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted } from "vue";
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import selectShopsDialog from "./components/selectShopsDialog.vue";
|
||||||
|
import singCodeDialog from "./components/singCodeDialog.vue";
|
||||||
|
import { entryManagerList, queryEntry } from '@/api/common'
|
||||||
|
|
||||||
|
const singCodeDialogRef = ref(null)
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const selectShopsDialogRef = ref(null);
|
||||||
|
|
||||||
|
// 选择商户成功回调
|
||||||
|
function selectSuccessHandle(shop) {
|
||||||
|
console.log('选择的商户:', shop);
|
||||||
|
router.push({ name: 'applyment_in', query: { shopId: shop.id } });
|
||||||
|
}
|
||||||
|
|
||||||
|
const userTypeList = ref([
|
||||||
|
{
|
||||||
|
value: '0',
|
||||||
|
label: '个体商户'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '1',
|
||||||
|
label: '企业商户'
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
function userTypeListFilter(userType) {
|
||||||
|
let obj = userTypeList.value.find(item => item.value == userType)
|
||||||
|
if (obj) {
|
||||||
|
return obj
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
label: userType,
|
||||||
|
value: userType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const statusList = ref([
|
||||||
|
{
|
||||||
|
value: 'WAIT',
|
||||||
|
label: '待提交',
|
||||||
|
type: 'info'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'INIT',
|
||||||
|
label: '待处理',
|
||||||
|
type: 'info'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'AUDIT',
|
||||||
|
label: '待审核',
|
||||||
|
type: 'warning'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'SIGN',
|
||||||
|
label: '待签约',
|
||||||
|
type: 'primary'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'FINISH',
|
||||||
|
label: '已完成',
|
||||||
|
type: 'success'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'REJECTED',
|
||||||
|
label: '失败',
|
||||||
|
type: 'danger'
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
function statusListFilter(status) {
|
||||||
|
let obj = statusList.value.find(item => item.value == status)
|
||||||
|
if (obj) {
|
||||||
|
return obj
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
label: status,
|
||||||
|
value: status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryForm = ref({
|
||||||
|
userType: '',
|
||||||
|
shopName: '',
|
||||||
|
status: '',
|
||||||
|
alipayAccount: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
function queryHandle() {
|
||||||
|
tableData.page = 1
|
||||||
|
getTableData()
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetHandle() {
|
||||||
|
queryForm.value.userType = ''
|
||||||
|
queryForm.value.shopName = ''
|
||||||
|
queryForm.value.status = ''
|
||||||
|
queryForm.value.alipayAccount = ''
|
||||||
|
queryHandle()
|
||||||
|
}
|
||||||
|
|
||||||
|
const tableData = reactive({
|
||||||
|
loading: false,
|
||||||
|
page: 1,
|
||||||
|
size: 10,
|
||||||
|
total: 0,
|
||||||
|
list: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
// 分页大小发生变化
|
||||||
|
function handleSizeChange(e) {
|
||||||
|
tableData.size = e;
|
||||||
|
getTableData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页发生变化
|
||||||
|
function handleCurrentChange(e) {
|
||||||
|
tableData.page = e;
|
||||||
|
getTableData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询状态
|
||||||
|
async function checkStatusHandle(row) {
|
||||||
|
try {
|
||||||
|
tableData.loading = true
|
||||||
|
const businessLicenceInfo = JSON.parse(row.businessLicenceInfo)
|
||||||
|
await queryEntry({
|
||||||
|
shopId: row.shopId,
|
||||||
|
licenceNo: businessLicenceInfo.licenceNo
|
||||||
|
})
|
||||||
|
getTableData()
|
||||||
|
} catch (error) {
|
||||||
|
tableData.loading = false
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取表格数据
|
||||||
|
async function getTableData() {
|
||||||
|
try {
|
||||||
|
tableData.loading = true
|
||||||
|
const res = await entryManagerList({
|
||||||
|
page: tableData.page,
|
||||||
|
size: tableData.size,
|
||||||
|
...queryForm.value
|
||||||
|
})
|
||||||
|
tableData.list = res.records
|
||||||
|
tableData.total = res.totalRow
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
tableData.loading = false;
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转编辑页面
|
||||||
|
function toDetail(row, type) {
|
||||||
|
const businessLicenceInfo = JSON.parse(row.businessLicenceInfo)
|
||||||
|
router.push({
|
||||||
|
name: 'applyment_in',
|
||||||
|
query: {
|
||||||
|
shopId: row.shopId,
|
||||||
|
licenceNo: businessLicenceInfo.licenceNo,
|
||||||
|
type: type
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getTableData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.gyq_container {
|
||||||
|
padding: 14px;
|
||||||
|
|
||||||
|
.gyq_content {
|
||||||
|
padding: 14px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
&.mt14 {
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error_text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--el-color-danger);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
71
src/views/applyments/select_shop.vue
Normal file
71
src/views/applyments/select_shop.vue
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<!-- 选择商户以及进件渠道 -->
|
||||||
|
<template>
|
||||||
|
<div class="gyq_container">
|
||||||
|
<div class="gyq_content">
|
||||||
|
<div class="row">
|
||||||
|
<el-form :model="queryForm" inline>
|
||||||
|
<el-form-item label="请选择用户">
|
||||||
|
<el-input placeholder="用户号/名称/手机号" readonly @click="selectShopsDialogRef?.show()"
|
||||||
|
v-model="queryForm.shopName">
|
||||||
|
<template #suffix>
|
||||||
|
<div class="center">
|
||||||
|
<el-icon v-if="queryForm.shopName" @click.stop="queryForm.shopName = ''">
|
||||||
|
<CircleCloseFilled />
|
||||||
|
</el-icon>
|
||||||
|
<el-icon @click="selectShopsDialogRef?.show()" style="cursor: pointer;">
|
||||||
|
<Search />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Plus">新增用户</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<selectShopsDialog ref="selectShopsDialogRef" @success="selectShopSuccess" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive } from "vue";
|
||||||
|
import selectShopsDialog from "./components/selectShopsDialog.vue";
|
||||||
|
|
||||||
|
const selectShopsDialogRef = ref<InstanceType<typeof selectShopsDialog> | null>(null);
|
||||||
|
|
||||||
|
const queryForm = ref({
|
||||||
|
shopName: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
// 选择商户成功回调
|
||||||
|
function selectShopSuccess(shop: any) {
|
||||||
|
console.log('选择的商户:', shop);
|
||||||
|
queryForm.value.shopName = shop.shopName;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.gyq_container {
|
||||||
|
padding: 14px;
|
||||||
|
|
||||||
|
.gyq_content {
|
||||||
|
padding: 14px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
&.mt14 {
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
699
src/views/data/finance.vue
Normal file
699
src/views/data/finance.vue
Normal file
@@ -0,0 +1,699 @@
|
|||||||
|
<template>
|
||||||
|
<div class="gyq_container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="between">
|
||||||
|
<el-form :model="queryForm" inline>
|
||||||
|
<el-form-item>
|
||||||
|
<el-date-picker v-model="queryForm.queryDate" type="date" placeholder="选择日期" format="YYYY-MM-DD"
|
||||||
|
value-format="YYYY-MM-DD" :disabled-date="disabledFutureDate" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" :loading="loading" @click="handleQuery">查询</el-button>
|
||||||
|
<el-button @click="handleReset" icon="Refresh" :loading="loading">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<el-form inline>
|
||||||
|
<el-form-item>
|
||||||
|
<el-select v-model="queryForm.platform" placeholder="选择平台" clearable style="width: 150px;">
|
||||||
|
<el-option v-for="item in platformList" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button @click="handleExport" icon="Download">导出</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" v-loading="loading">
|
||||||
|
<div class="warp" style="width: 400px;">
|
||||||
|
<div class="card">
|
||||||
|
<div class="header_title">营业额</div>
|
||||||
|
<div class="num" style="color: var(--el-color-primary);">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.turnover.turnover || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="intro">营业额</div>
|
||||||
|
<div class="pay_wrap">
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.turnover.wechat || 0) }}
|
||||||
|
</div>
|
||||||
|
<span class="t">微信支付金额</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.turnover.alipay || 0) }}
|
||||||
|
</div>
|
||||||
|
<span class="t">支付宝支付金额</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.turnover.selfScan || 0) }}
|
||||||
|
</div>
|
||||||
|
<span class="t">二维码收款</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.turnover.barScan || 0) }}
|
||||||
|
</div>
|
||||||
|
<span class="t">扫码收款</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.turnover.cash || 0) }}
|
||||||
|
</div>
|
||||||
|
<span class="t">现金收款</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.turnover.recharge || 0) }}
|
||||||
|
</div>
|
||||||
|
<span class="t">充值</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.turnover.owed || 0) }}
|
||||||
|
</div>
|
||||||
|
<span class="t">挂账</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.turnover.balance || 0) }}
|
||||||
|
</div>
|
||||||
|
<span class="t">余额支付</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="order_info">
|
||||||
|
<div class="order_title">
|
||||||
|
<span class="dot"></span>
|
||||||
|
<span class="t">订单</span>
|
||||||
|
</div>
|
||||||
|
<div class="order_lits">
|
||||||
|
<div class="item">
|
||||||
|
<span class="t">订单金额</span>
|
||||||
|
<span class="n">{{ tableData.order.orderAmount || 0 }}</span>
|
||||||
|
</div>
|
||||||
|
<span class="line">|</span>
|
||||||
|
<div class="item">
|
||||||
|
<span class="t">订单总数</span>
|
||||||
|
<span class="n">{{ tableData.order.orderCount || 0 }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="header_title">数据统计</div>
|
||||||
|
<div class="pay_wrap">
|
||||||
|
<div class="item">
|
||||||
|
<span class="n">{{ tableData.sts.customerCount || 0 }}</span>
|
||||||
|
<span class="t">就餐人数</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<span class="n">{{ tableData.sts.orderCount || 0 }}</span>
|
||||||
|
<span class="t">订单数</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<span class="n">{{ tableData.sts.tableCount || 0 }}</span>
|
||||||
|
<span class="t">桌台数</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.sts.avgPayAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="t">客单价
|
||||||
|
<el-tooltip class="box-item" effect="dark" content="实付金额(包含现金支付 包含会员支付 包含挂账)/就餐人数没有具体人数时,默认一桌按照1人计算"
|
||||||
|
placement="top">
|
||||||
|
<el-icon color="#666">
|
||||||
|
<QuestionFilled />
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<span class="n">{{ tableData.sts.turnoverRate || 0 }}%</span>
|
||||||
|
<div class="t">翻台率
|
||||||
|
<el-tooltip class="box-item" effect="dark" content="(订单数-桌台数)/桌台数*100%" placement="top">
|
||||||
|
<el-icon color="#666">
|
||||||
|
<QuestionFilled />
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.sts.profitAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="t">毛利润
|
||||||
|
<el-tooltip class="box-item" effect="dark" content="(订单实付金额-商品成本)" placement="top">
|
||||||
|
<el-icon color="#666">
|
||||||
|
<QuestionFilled />
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.sts.productCostAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<span class="t">商品成本</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<span class="n">{{ tableData.sts.profitRate || 0 }}%</span>
|
||||||
|
<div class="t">毛利率
|
||||||
|
<el-tooltip class="box-item" effect="dark" content="(订单实付金额-商品成本)/订单实付金额*100%" placement="top">
|
||||||
|
<el-icon color="#666">
|
||||||
|
<QuestionFilled />
|
||||||
|
</el-icon>
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="item">
|
||||||
|
<span class="n">{{ tableData.sts.netProfitAmount || 0 }}%</span>
|
||||||
|
<span class="t">净利率</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.sts.netProfitRate || 0) }}
|
||||||
|
</div>
|
||||||
|
<span class="t">净利润</span>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card" style="flex: 1;">
|
||||||
|
<div class="header_title">商家经营数据</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="card" style="flex: 1;">
|
||||||
|
<div class="num" style="color: var(--el-color-success);">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.discount.discountAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="intro">优惠金额</div>
|
||||||
|
<div class="item_list">
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
{{ tableData.discount.discountCount || 0 }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
优惠笔数
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.discount.newConsumerDiscount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
新客立减
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.discount.freeCashAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
霸王餐
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.discount.fullMinusAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
满减活动
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.discount.couponAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
优惠券
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.discount.memberDiscount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
会员折扣
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.discount.pointsDiscountAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
积分抵扣金额
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.discount.orderDiscount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
订单改价
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card" style="flex: 1;">
|
||||||
|
<div class="num" style="color: var(--el-color-danger);">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.refund.refundAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="intro">退款金额</div>
|
||||||
|
<div class="item_list">
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.refund.onlineRefundAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
线上退款金额
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.refund.cashRefundAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
现金退款金额
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.refund.memberRefundAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
余额退款金额
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.refund.onlineRechargeRefundAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
线上充值退款金额
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.refund.cashRechargeRefundAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
现金充值退款金额
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.refund.creditRefundAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
挂账退款金额
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card" style="flex: 1;">
|
||||||
|
<div class="num" style="color: var(--el-color-warning);">
|
||||||
|
<span class="i">¥</span>
|
||||||
|
{{ multiplyAndFormat(tableData.order.orderAmount || 0) }}
|
||||||
|
</div>
|
||||||
|
<div class="intro">订单金额</div>
|
||||||
|
<div class="item_list">
|
||||||
|
<div class="item">
|
||||||
|
<div class="n">
|
||||||
|
{{ tableData.order.orderCount || 0 }}
|
||||||
|
</div>
|
||||||
|
<div class="label">
|
||||||
|
订单总数
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
import OrderApi from "@/api/order/order";
|
||||||
|
import { downloadFile, multiplyAndFormat } from '@/utils'
|
||||||
|
|
||||||
|
const queryForm = ref({
|
||||||
|
queryDate: dayjs().format('YYYY-MM-DD'), // 查询日期 yyyy-MM-dd
|
||||||
|
platform: 'czg',
|
||||||
|
shopId: localStorage.getItem('shopId') || '',
|
||||||
|
mainShopId: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const platformList = ref([
|
||||||
|
{ value: 'czg', label: '银收客' },
|
||||||
|
{ value: 'MTuan', label: '美团' },
|
||||||
|
{ value: 'CMeMe', label: '菜么么' },
|
||||||
|
{ value: 'KRuYun', label: '客如云' },
|
||||||
|
])
|
||||||
|
|
||||||
|
// 禁用今天以后的日期
|
||||||
|
const disabledFutureDate = (time) => {
|
||||||
|
return dayjs(time).isAfter(dayjs().startOf('day'))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询
|
||||||
|
function handleQuery() {
|
||||||
|
getData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
function handleReset() {
|
||||||
|
queryForm.value.queryDate = dayjs().format('YYYY-MM-DD')
|
||||||
|
queryForm.value.platform = 'czg'
|
||||||
|
getData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出
|
||||||
|
async function handleExport() {
|
||||||
|
try {
|
||||||
|
if (!queryForm.value.platform) {
|
||||||
|
ElMessage.error('请选择导出平台')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const res = await OrderApi.financeExport(queryForm.value)
|
||||||
|
downloadFile(res, '财务报表', 'xlsx')
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
const tableData = ref({
|
||||||
|
turnover: {},
|
||||||
|
order: {},
|
||||||
|
discount: {},
|
||||||
|
refund: {},
|
||||||
|
sts: {}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 查询财务报表
|
||||||
|
async function getData() {
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
const res = await OrderApi.financeSts(queryForm.value)
|
||||||
|
tableData.value = res
|
||||||
|
console.log('tableData.value', tableData.value);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = false
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.gyq_container {
|
||||||
|
padding: 14px;
|
||||||
|
|
||||||
|
.gyq_content {
|
||||||
|
padding: 14px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.between {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
gap: 14px;
|
||||||
|
|
||||||
|
&.mt14 {
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.warp {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border-radius: 12px;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
.header_title {
|
||||||
|
font-size: 16px;
|
||||||
|
color: 333;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-top: 20px;
|
||||||
|
padding: 14px;
|
||||||
|
display: flex;
|
||||||
|
gap: 14px;
|
||||||
|
|
||||||
|
.item_list {
|
||||||
|
margin-top: 14px;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
height: 50px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 14px;
|
||||||
|
|
||||||
|
&:nth-child(odd) {
|
||||||
|
background-color: #F3F7FA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.n {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.i {
|
||||||
|
font-size: 10px;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.num {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.i {
|
||||||
|
font-size: 12px;
|
||||||
|
position: relative;
|
||||||
|
top: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pay_wrap {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
grid-column-gap: 0px;
|
||||||
|
grid-row-gap: 14px;
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
padding: 14px;
|
||||||
|
margin-top: 14px;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
.item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.n {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.i {
|
||||||
|
font-size: 12px;
|
||||||
|
position: relative;
|
||||||
|
top: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.t {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.order_info {
|
||||||
|
border-top: 1px solid #ececec;
|
||||||
|
padding-top: 14px;
|
||||||
|
|
||||||
|
.order_title {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.dot {
|
||||||
|
--size: 12px;
|
||||||
|
width: var(--size);
|
||||||
|
height: var(--size);
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: var(--el-color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.t {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.order_lits {
|
||||||
|
display: flex;
|
||||||
|
gap: 14px;
|
||||||
|
margin-top: 4px;
|
||||||
|
|
||||||
|
.line {
|
||||||
|
color: #ececec;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 14px;
|
||||||
|
|
||||||
|
.t {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.n {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.waterfall {
|
||||||
|
/* 核心属性1:定义瀑布流列数(关键) */
|
||||||
|
column-count: 3;
|
||||||
|
/* 核心属性2:列之间的间距(替代margin,避免卡片间距错乱) */
|
||||||
|
column-gap: 14px;
|
||||||
|
/* 可选:防止卡片内容被列分割(关键!避免卡片跨列断裂) */
|
||||||
|
break-inside: avoid;
|
||||||
|
|
||||||
|
.waterfall-card {
|
||||||
|
/* 必须:适配多列布局,避免卡片宽度溢出 */
|
||||||
|
width: 100%;
|
||||||
|
/* 卡片间距:仅需设置底部外边距(上下间距),左右间距由column-gap控制 */
|
||||||
|
margin-bottom: 14px;
|
||||||
|
padding: 24px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
/* 配合break-inside: avoid,强化卡片不可分割 */
|
||||||
|
page-break-inside: avoid;
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
display: flex;
|
||||||
|
gap: 14px;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
|
||||||
|
.dot {
|
||||||
|
--size: 10px;
|
||||||
|
width: var(--size);
|
||||||
|
height: var(--size);
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.t {
|
||||||
|
font-size: 24px;
|
||||||
|
color: #000;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
padding-left: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
margin-top: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
padding-left: 24px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -52,6 +52,7 @@
|
|||||||
<span>营业</span>
|
<span>营业</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="u-flex" style="flex-wrap: wrap">
|
<div class="u-flex" style="flex-wrap: wrap">
|
||||||
|
<importData :type="9" style="margin-right: 14px;" @close="importDataClose" />
|
||||||
<el-select v-if="isHeadShop == 1 && loginType == 0" v-model="shopId" placeholder="选择分店"
|
<el-select v-if="isHeadShop == 1 && loginType == 0" v-model="shopId" placeholder="选择分店"
|
||||||
style="width: 200px; margin-right: 10px;" @change="shopChange">
|
style="width: 200px; margin-right: 10px;" @change="shopChange">
|
||||||
<el-option v-for="item in branchList" :key="item.shopId" :label="item.shopName" :value="item.shopId" />
|
<el-option v-for="item in branchList" :key="item.shopId" :label="item.shopName" :value="item.shopId" />
|
||||||
@@ -101,7 +102,14 @@
|
|||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<img class="icon" src="@/assets/images/data/scan.png" />
|
<img class="icon" src="@/assets/images/data/scan.png" />
|
||||||
<span>主扫收款</span>
|
<span>二维码收款</span>
|
||||||
|
</div>
|
||||||
|
<span class="num">{{ trade.mainScanPayAmount || 0 }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<div class="left">
|
||||||
|
<img class="icon" src="@/assets/images/data/scan.png" />
|
||||||
|
<span>扫码收款</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="num">{{ trade.backScanPayAmount || 0 }}</span>
|
<span class="num">{{ trade.backScanPayAmount || 0 }}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -180,7 +188,7 @@
|
|||||||
<div class="gropress l" :style="{
|
<div class="gropress l" :style="{
|
||||||
width: `${trade.rechargeAmount
|
width: `${trade.rechargeAmount
|
||||||
? (trade.rechargeAmount /
|
? (trade.rechargeAmount /
|
||||||
(trade.memberPayAmount + trade.rechargeRefundAmount * 1)) *
|
(trade.rechargeAmount * 1 + trade.rechargeRefundAmount * 1)) *
|
||||||
100
|
100
|
||||||
: 0
|
: 0
|
||||||
}%`,
|
}%`,
|
||||||
@@ -188,7 +196,7 @@
|
|||||||
<div class="gropress r" :style="{
|
<div class="gropress r" :style="{
|
||||||
width: `${trade.rechargeRefundAmount
|
width: `${trade.rechargeRefundAmount
|
||||||
? (trade.rechargeRefundAmount /
|
? (trade.rechargeRefundAmount /
|
||||||
(trade.memberPayAmount + trade.rechargeRefundAmount * 1)) *
|
(trade.rechargeAmount * 1 + trade.rechargeRefundAmount * 1)) *
|
||||||
100
|
100
|
||||||
: 0
|
: 0
|
||||||
}%`,
|
}%`,
|
||||||
@@ -495,6 +503,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import importData from "@/components/importData/index.vue";
|
||||||
import dataSummaryApi from "@/api/order/data-summary";
|
import dataSummaryApi from "@/api/order/data-summary";
|
||||||
import ShopApi from "@/api/account/shop";
|
import ShopApi from "@/api/account/shop";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
@@ -504,6 +513,7 @@ import { formatDateRange } from './utils/index.js'
|
|||||||
import { multiplyAndFormat } from '@/utils/index.js'
|
import { multiplyAndFormat } from '@/utils/index.js'
|
||||||
export default {
|
export default {
|
||||||
name: "home",
|
name: "home",
|
||||||
|
components: { importData },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
multiplyAndFormat,
|
multiplyAndFormat,
|
||||||
@@ -704,6 +714,15 @@ export default {
|
|||||||
// this.initCardUserChart();
|
// this.initCardUserChart();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
importDataClose() {
|
||||||
|
// this.summaryGet();
|
||||||
|
this.dateAmount();
|
||||||
|
this.dateProduct();
|
||||||
|
// this.summaryDateGet();
|
||||||
|
this.timeChange(this.timeValue);
|
||||||
|
this.profitRateBarChart()
|
||||||
|
this.costLineChart()
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 获取分店列表
|
* 获取分店列表
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
<span v-if="!downloadLoading">导出Excel</span>
|
<span v-if="!downloadLoading">导出Excel</span>
|
||||||
<span v-else>下载中...</span>
|
<span v-else>下载中...</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<importData :type="7" @close="getTableData" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
@@ -56,7 +57,7 @@
|
|||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="m">¥{{ payCount.totalAmount || 0 }}</div>
|
<div class="m">¥{{ multiplyAndFormat(payCount.totalAmount || 0) }}</div>
|
||||||
<div class="t">总金额</div>
|
<div class="t">总金额</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -67,7 +68,7 @@
|
|||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="m">¥{{ payCount.refundAmount || 0 }}</div>
|
<div class="m">¥{{ multiplyAndFormat(payCount.refundAmount || 0) }}</div>
|
||||||
<div class="t">退款金额</div>
|
<div class="t">退款金额</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -100,7 +101,7 @@
|
|||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="m">{{ payCount.totalAmount - payCount.refundAmount || 0 }}</div>
|
<div class="m">{{ multiplyAndFormat((payCount.totalAmount - payCount.refundAmount) || 0) }}</div>
|
||||||
<div class="t">实际销售额总和</div>
|
<div class="t">实际销售额总和</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -111,7 +112,7 @@
|
|||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="m">{{ payCount.saleCount - payCount.refundCount || 0 }}</div>
|
<div class="m">{{ multiplyAndFormat((payCount.saleCount - payCount.refundCount) || 0) }}</div>
|
||||||
<div class="t">实际销量总和</div>
|
<div class="t">实际销量总和</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -152,10 +153,10 @@
|
|||||||
<template v-slot="scope">¥{{ scope.row.refund }}</template>
|
<template v-slot="scope">¥{{ scope.row.refund }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="实际销量" prop="refundCount">
|
<el-table-column label="实际销量" prop="refundCount">
|
||||||
<template v-slot="scope"> {{ scope.row.saleCount - scope.row.refundCount }} </template>
|
<template v-slot="scope"> {{ multiplyAndFormat(scope.row.saleCount - scope.row.refundCount) }} </template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="实际销售额" prop="refundCount">
|
<el-table-column label="实际销售额" prop="refundCount">
|
||||||
<template v-slot="scope"> ¥{{ scope.row.saleAmount - scope.row.refundAmount }} </template>
|
<template v-slot="scope"> ¥{{ multiplyAndFormat(scope.row.saleAmount - scope.row.refundAmount) }} </template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<el-table :data="tableData.data" v-loading="tableData.loading" v-if="orderType == 2">
|
<el-table :data="tableData.data" v-loading="tableData.loading" v-if="orderType == 2">
|
||||||
@@ -165,17 +166,17 @@
|
|||||||
<el-table-column label="商品名称" prop="productName"></el-table-column>
|
<el-table-column label="商品名称" prop="productName"></el-table-column>
|
||||||
<el-table-column label="销量" prop="saleCount" sortable></el-table-column>
|
<el-table-column label="销量" prop="saleCount" sortable></el-table-column>
|
||||||
<el-table-column label="销售金额" prop="saleAmount" sortable>
|
<el-table-column label="销售金额" prop="saleAmount" sortable>
|
||||||
<template v-slot="scope">¥{{ scope.row.saleAmount }}</template>
|
<template v-slot="scope">¥{{ multiplyAndFormat(scope.row.saleAmount) }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="退单量" prop="refundCount" sortable></el-table-column>
|
<el-table-column label="退单量" prop="refundCount" sortable></el-table-column>
|
||||||
<el-table-column label="退款金额" prop="refundAmount" sortable>
|
<el-table-column label="退款金额" prop="refundAmount" sortable>
|
||||||
<template v-slot="scope">¥{{ scope.row.refundAmount }}</template>
|
<template v-slot="scope">¥{{ multiplyAndFormat(scope.row.refundAmount) }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="实际销量" prop="refundCount" sortable>
|
<el-table-column label="实际销量" prop="refundCount" sortable>
|
||||||
<template v-slot="scope"> {{ scope.row.saleCount - scope.row.refundCount }} </template>
|
<template v-slot="scope"> {{ multiplyAndFormat(scope.row.saleCount - scope.row.refundCount) }} </template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="实际销售额" prop="refundCount" sortable>
|
<el-table-column label="实际销售额" prop="refundCount" sortable>
|
||||||
<template v-slot="scope"> ¥{{ scope.row.saleAmount - scope.row.refundAmount }} </template>
|
<template v-slot="scope"> ¥{{ multiplyAndFormat(scope.row.saleAmount - scope.row.refundAmount) }} </template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
@@ -189,16 +190,19 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import importData from "@/components/importData/index.vue";
|
||||||
import saleSummaryApi from "@/api/order/sale-summary";
|
import saleSummaryApi from "@/api/order/sale-summary";
|
||||||
import categoryApi from "@/api/product/productclassification";
|
import categoryApi from "@/api/product/productclassification";
|
||||||
import ShopApi from "@/api/account/shop";
|
import ShopApi from "@/api/account/shop";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { downloadFile } from "@/utils/index";
|
import { downloadFile, multiplyAndFormat } from "@/utils/index";
|
||||||
import { formatDateRange } from './utils/index.js'
|
import { formatDateRange } from './utils/index.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: { importData },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
multiplyAndFormat,
|
||||||
timeValue: "today",
|
timeValue: "today",
|
||||||
resetQuery: null,
|
resetQuery: null,
|
||||||
orderType: "2",
|
orderType: "2",
|
||||||
@@ -314,7 +318,8 @@ export default {
|
|||||||
endDate: this.query.createdAt[1],
|
endDate: this.query.createdAt[1],
|
||||||
categoryId: this.query.prodCategoryId,
|
categoryId: this.query.prodCategoryId,
|
||||||
productName: this.query.productName,
|
productName: this.query.productName,
|
||||||
shopId: this.shopId
|
shopId: this.shopId,
|
||||||
|
rangeType: this.timeValue,
|
||||||
});
|
});
|
||||||
downloadFile(file, "数据", "xlsx");
|
downloadFile(file, "数据", "xlsx");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -27,13 +27,14 @@
|
|||||||
<el-option v-for="item in branchList" :key="item.shopId" :label="item.shopName" :value="item.shopId" />
|
<el-option v-for="item in branchList" :key="item.shopId" :label="item.shopName" :value="item.shopId" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div style="display: flex;">
|
||||||
<el-button type="primary" @click="getTableData">查询</el-button>
|
<el-button type="primary" @click="getTableData">查询</el-button>
|
||||||
<el-button @click="resetHandle">重置</el-button>
|
<el-button @click="resetHandle">重置</el-button>
|
||||||
<el-button icon="download" v-loading="downloadLoading" @click="downloadHandle">
|
<el-button icon="download" v-loading="downloadLoading" @click="downloadHandle">
|
||||||
<span v-if="!downloadLoading">导出Excel</span>
|
<span v-if="!downloadLoading">导出Excel</span>
|
||||||
<span v-else>下载中...</span>
|
<span v-else>下载中...</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<importData :type="8" @close="getTableData" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -90,16 +91,17 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table> -->
|
</el-table> -->
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="head-container">
|
<div class="head-container">
|
||||||
<el-pagination :total="tableData.total" :current-page="tableData.page + 1" :page-size="tableData.size"
|
<el-pagination :total="tableData.total" :current-page="tableData.page" :page-size="tableData.size"
|
||||||
@current-change="paginationChange" @size-change="sizeChange"
|
@current-change="paginationChange" @size-change="sizeChange"
|
||||||
layout="total, sizes, prev, pager, next, jumper"></el-pagination>
|
layout="total, sizes, prev, pager, next, jumper"></el-pagination>
|
||||||
</div> -->
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
import importData from "@/components/importData/index.vue";
|
||||||
import tableSummaryApi from "@/api/order/table-summary";
|
import tableSummaryApi from "@/api/order/table-summary";
|
||||||
import ShopApi from "@/api/account/shop";
|
import ShopApi from "@/api/account/shop";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
@@ -107,6 +109,7 @@ import { downloadFile } from "@/utils/index";
|
|||||||
import { formatDateRange } from './utils/index.js'
|
import { formatDateRange } from './utils/index.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: { importData },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
timeValue: "today",
|
timeValue: "today",
|
||||||
@@ -187,7 +190,8 @@ export default {
|
|||||||
const file = await tableSummaryApi.export({
|
const file = await tableSummaryApi.export({
|
||||||
beginDate: this.query.createdAt[0],
|
beginDate: this.query.createdAt[0],
|
||||||
endDate: this.query.createdAt[1],
|
endDate: this.query.createdAt[1],
|
||||||
shopId: this.shopId
|
shopId: this.shopId,
|
||||||
|
rangeType: this.timeValue,
|
||||||
});
|
});
|
||||||
downloadFile(file, "数据", "xlsx");
|
downloadFile(file, "数据", "xlsx");
|
||||||
this.downloadLoading = false;
|
this.downloadLoading = false;
|
||||||
@@ -198,13 +202,14 @@ export default {
|
|||||||
},
|
},
|
||||||
// 重置查询
|
// 重置查询
|
||||||
resetHandle() {
|
resetHandle() {
|
||||||
this.timeValue = "";
|
this.timeValue = "today";
|
||||||
this.query = { ...this.resetQuery };
|
this.query = { ...this.resetQuery };
|
||||||
this.page = 1;
|
this.page = 1;
|
||||||
this.getTableData();
|
this.getTableData();
|
||||||
},
|
},
|
||||||
// 分页大小改变
|
// 分页大小改变
|
||||||
sizeChange(e) {
|
sizeChange(e) {
|
||||||
|
this.tableData.page = 1
|
||||||
this.tableData.size = e;
|
this.tableData.size = e;
|
||||||
this.getTableData();
|
this.getTableData();
|
||||||
},
|
},
|
||||||
@@ -224,8 +229,11 @@ export default {
|
|||||||
// page: this.tableData.page,
|
// page: this.tableData.page,
|
||||||
// size: this.tableData.size,
|
// size: this.tableData.size,
|
||||||
rangeType: this.timeValue,
|
rangeType: this.timeValue,
|
||||||
|
// rangeType: 'custom',
|
||||||
beginDate: this.query.createdAt[0],
|
beginDate: this.query.createdAt[0],
|
||||||
endDate: this.query.createdAt[1],
|
endDate: this.query.createdAt[1],
|
||||||
|
// beginDate: '2026-01-26',
|
||||||
|
// endDate: '2026-01-26',
|
||||||
shopId: this.shopId
|
shopId: this.shopId
|
||||||
});
|
});
|
||||||
this.tableData.loading = false;
|
this.tableData.loading = false;
|
||||||
|
|||||||
@@ -70,12 +70,11 @@ const env = process.env.NODE_ENV
|
|||||||
// DEV-START
|
// DEV-START
|
||||||
const accountList = reactive([
|
const accountList = reactive([
|
||||||
{ username: "admin", type: 'primary', label: 'admin' },
|
{ username: "admin", type: 'primary', label: 'admin' },
|
||||||
{ username: "19191703856", type: 'warning', label: '喜气洋洋' },
|
{ username: "18049104914", type: 'warning', label: '东风的店铺' },
|
||||||
{ username: "19107220837", type: 'danger', label: '快乐时光店铺' },
|
{ username: "19107220837", type: 'danger', label: '快乐时光店铺' },
|
||||||
{ username: "18199991111", type: 'success', label: '草莓加盟主店可直接管理' },
|
// { username: "18199991111", type: 'success', label: '草莓加盟主店可直接管理' },
|
||||||
{ username: "18821670757", type: 'primary', label: '强盛集团' },
|
{ username: "18821670757", type: 'success', label: '高歌的小店' },
|
||||||
{ username: "19107220837", type: 'warning', label: '万维时光' },
|
{ username: "191123456", type: 'primary', label: '酸橘子' },
|
||||||
{ username: "19112345678", type: 'success', label: '酸橘子·云贵小馆' },
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 快捷模拟登录
|
// 快捷模拟登录
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, nextTick } from 'vue'
|
import { ref, onMounted, nextTick, watch } from 'vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
// {label: '设置',value: 1}
|
// {label: '设置',value: 1}
|
||||||
@@ -29,10 +29,8 @@ const modelValue = defineModel('modelValue', {
|
|||||||
required: true
|
required: true
|
||||||
})
|
})
|
||||||
|
|
||||||
// 改变索引
|
// 更新active_wrap位置
|
||||||
function changeHandle(index) {
|
function updateActivePosition(index) {
|
||||||
modelValue.value = index
|
|
||||||
|
|
||||||
let left = 0
|
let left = 0
|
||||||
itemsWidth.value.forEach((val, i) => {
|
itemsWidth.value.forEach((val, i) => {
|
||||||
if (i < index) {
|
if (i < index) {
|
||||||
@@ -40,7 +38,12 @@ function changeHandle(index) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
leftValue.value = left + gap.value * index
|
leftValue.value = left + gap.value * index
|
||||||
|
}
|
||||||
|
|
||||||
|
// 改变索引
|
||||||
|
function changeHandle(index) {
|
||||||
|
modelValue.value = index
|
||||||
|
updateActivePosition(index)
|
||||||
emits('change', index)
|
emits('change', index)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,10 +60,14 @@ onMounted(() => {
|
|||||||
console.log('itemRefs===', itemRefs.value);
|
console.log('itemRefs===', itemRefs.value);
|
||||||
console.log('itemsWidth===', itemsWidth.value);
|
console.log('itemsWidth===', itemsWidth.value);
|
||||||
|
|
||||||
|
updateActivePosition(modelValue.value)
|
||||||
changeHandle(modelValue.value)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 监听modelValue变化,更新位置
|
||||||
|
watch(modelValue, (newVal) => {
|
||||||
|
updateActivePosition(newVal)
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -32,10 +32,10 @@ export const newMenus = [
|
|||||||
intro: '协助商家拉来新客户,拓展客户群体',
|
intro: '协助商家拉来新客户,拓展客户群体',
|
||||||
childrenList: [
|
childrenList: [
|
||||||
{
|
{
|
||||||
name: "分销",
|
name: "全民股东",
|
||||||
icon: "zhcz",
|
icon: "zhcz",
|
||||||
pathName: "distribution_page",
|
pathName: "distribution_page",
|
||||||
intro: "用户成为业务员,可促进消费"
|
intro: "用户成为股东,可促进消费"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "套餐推广",
|
name: "套餐推广",
|
||||||
@@ -55,6 +55,12 @@ export const newMenus = [
|
|||||||
pathName: "group_booking",
|
pathName: "group_booking",
|
||||||
intro: "拼团"
|
intro: "拼团"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "分享配置",
|
||||||
|
icon: "fxpz",
|
||||||
|
pathName: "share_setting",
|
||||||
|
intro: "商家可配置用户分享后可获得的奖励"
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -128,7 +128,8 @@ function submitHandle() {
|
|||||||
// 过滤条件
|
// 过滤条件
|
||||||
function isDistribtion(str) {
|
function isDistribtion(str) {
|
||||||
let s = str.split('_')
|
let s = str.split('_')
|
||||||
return s[1]
|
let shopId = s[0]
|
||||||
|
return s[1] && shopId == localStorage.getItem('shopId') ? 1 : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectUser = ref([])
|
const selectUser = ref([])
|
||||||
|
|||||||
@@ -0,0 +1,290 @@
|
|||||||
|
<template>
|
||||||
|
<div class="form_content">
|
||||||
|
<div class="left">
|
||||||
|
<div class="new_preview">
|
||||||
|
<div class="header">{{ shopInfo.shopName }}</div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="title">{{ form.title }}</div>
|
||||||
|
<div class="img_wrap">
|
||||||
|
<div class="img">
|
||||||
|
<el-image :src="form.groupUrl" style="width: 100%;height: 100%;border-radius: 4px;"></el-image>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="intro">
|
||||||
|
{{ form.content }}
|
||||||
|
</div>
|
||||||
|
<div class="foot">
|
||||||
|
{{ defaultNote }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form">
|
||||||
|
<el-form ref="formRef" :model="form" :rules="rules" label-position="right" label-width="120px">
|
||||||
|
<el-form-item label="群二维码" prop="groupUrl">
|
||||||
|
<single-image-upload style="width: 120px; height: 120px" v-model="form.groupUrl"></single-image-upload>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="模块标题" prop="title">
|
||||||
|
<el-input :placeholder="defaultTitle" :maxlength="15" v-model.trim="form.title"
|
||||||
|
style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="模块内容">
|
||||||
|
<el-input type="textarea" :rows="4" :maxlength="20" show-word-limit placeholder="请输入内容"
|
||||||
|
v-model.trim="form.content" style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="模块提示语">
|
||||||
|
<div class="tips">{{ defaultNote }}</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="启用状态">
|
||||||
|
<el-switch v-model="form.isEnable" :active-value="1" :inactive-value="0"></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" :loading="loading" @click="submitHandle">保存</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
|
import { ElNotification } from 'element-plus'
|
||||||
|
import { disGroupGet, disGroupPost } from '@/api/coupon/index'
|
||||||
|
|
||||||
|
const defaultTitle = ref('扫码进群,优惠多多')
|
||||||
|
const defaultNote = ref('如果长按不能识别,可截图或保存二维码图片至相册,通过微信扫码入群')
|
||||||
|
const defaultContent = ref('长按识别上方企微好友码,添加【福利官】')
|
||||||
|
const shopInfo = ref('')
|
||||||
|
|
||||||
|
const form = ref({
|
||||||
|
id: '',
|
||||||
|
groupUrl: '',
|
||||||
|
title: defaultTitle.value,
|
||||||
|
content: defaultContent.value,
|
||||||
|
isEnable: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = reactive({
|
||||||
|
groupUrl: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请上传群二维码',
|
||||||
|
triiger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
title: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入模块标题',
|
||||||
|
triiger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入内容',
|
||||||
|
triiger: 'change'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 开始提交
|
||||||
|
const formRef = ref(null)
|
||||||
|
const emits = defineEmits(["success"]);
|
||||||
|
const loading = ref(false);
|
||||||
|
function submitHandle() {
|
||||||
|
formRef.value.validate(async (valid) => {
|
||||||
|
try {
|
||||||
|
if (valid) {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
let data = { ...form.value }
|
||||||
|
|
||||||
|
if (data.title == '') {
|
||||||
|
data.title = defaultTitle.value
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.content == '') {
|
||||||
|
data.content = defaultContent.value
|
||||||
|
}
|
||||||
|
|
||||||
|
await disGroupPost(data);
|
||||||
|
ElNotification({
|
||||||
|
title: '注意',
|
||||||
|
message: '保存成功',
|
||||||
|
type: 'success'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取配置信息
|
||||||
|
async function drainageConfigGetAjax() {
|
||||||
|
try {
|
||||||
|
const res = await disGroupGet()
|
||||||
|
form.value = res
|
||||||
|
if (form.value.title == '') {
|
||||||
|
form.value.title = defaultTitle.value
|
||||||
|
}
|
||||||
|
if (form.value.content == '') {
|
||||||
|
form.value.content = defaultContent.value
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
shopInfo.value = JSON.parse(localStorage.getItem('userInfo'))
|
||||||
|
drainageConfigGetAjax()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.form_content {
|
||||||
|
padding: 14px 0 0;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.left {
|
||||||
|
width: 374px;
|
||||||
|
height: 720px;
|
||||||
|
position: relative;
|
||||||
|
background: url('https://cashier-oss.oss-cn-beijing.aliyuncs.com/upload/3/7da616a1c56a409dbdea8bf2f41cf14b.png') no-repeat center center / 100% 100%;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview {
|
||||||
|
width: 350px;
|
||||||
|
height: 130px;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 6px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 14px;
|
||||||
|
|
||||||
|
.info {
|
||||||
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 5px 0;
|
||||||
|
|
||||||
|
.top {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btm {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.img_wrap {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.new_preview {
|
||||||
|
--bg: #3F3B37;
|
||||||
|
--color: #F6DFC4;
|
||||||
|
--borderColor: #f6dfc45b;
|
||||||
|
width: 90%;
|
||||||
|
background-color: var(--bg);
|
||||||
|
border-radius: 4px;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 16px;
|
||||||
|
color: var(--color);
|
||||||
|
height: 50px;
|
||||||
|
border-bottom: 1px dashed var(--borderColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding-bottom: 14px;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color);
|
||||||
|
height: 50px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img_wrap {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.img {
|
||||||
|
--size: 220px;
|
||||||
|
width: var(--size);
|
||||||
|
height: var(--size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro {
|
||||||
|
height: 40px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--color);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.foot {
|
||||||
|
height: 40px;
|
||||||
|
color: var(--borderColor);
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 14px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -135,8 +135,8 @@
|
|||||||
<span class="required">*</span>分成比例
|
<span class="required">*</span>分成比例
|
||||||
</div>
|
</div>
|
||||||
<div class="ipt">
|
<div class="ipt">
|
||||||
<el-input v-model="item.levelOneCommission" placeholder="请输入" :maxlength="5"
|
<el-input v-model="item.commission" placeholder="请输入" :maxlength="5" style="width: 200px;"
|
||||||
style="width: 200px;" @input="e => item.levelOneCommission = filterNumberInput(e)">
|
@input="e => item.commission = filterNumberInput(e)">
|
||||||
<template #append>%</template>
|
<template #append>%</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</div>
|
</div>
|
||||||
@@ -204,7 +204,7 @@ const levelConfigListObj = ref({
|
|||||||
name: '', // 名称
|
name: '', // 名称
|
||||||
inviteCount: '', // 有效人数
|
inviteCount: '', // 有效人数
|
||||||
costAmount: '', // 消费金额
|
costAmount: '', // 消费金额
|
||||||
levelOneCommission: '', // 一级分销比例
|
commission: '', // 一级分销比例
|
||||||
levelTwoCommission: '', // 二级分销比例
|
levelTwoCommission: '', // 二级分销比例
|
||||||
})
|
})
|
||||||
const form = ref({
|
const form = ref({
|
||||||
@@ -281,7 +281,7 @@ const rules = ref({
|
|||||||
callback(new Error(tips))
|
callback(new Error(tips))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (item.levelOneCommission === '' || item.levelOneCommission == 0) {
|
if (item.commission === '' || item.commission == 0) {
|
||||||
tips = `请输入${index + 1}级的分成比例`
|
tips = `请输入${index + 1}级的分成比例`
|
||||||
callback(new Error(tips))
|
callback(new Error(tips))
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="gyq_container">
|
<div class="gyq_container">
|
||||||
<div class="gyq_content">
|
<div class="gyq_content">
|
||||||
<HeaderCard name="分销" intro="用户成为业务员,可促进消费" icon="xffx" showSwitch v-model:isOpen="form.isEnable">
|
<HeaderCard name="全民股东" intro="用户成为股东,可促进消费" icon="xffx" showSwitch v-model:isOpen="form.isEnable">
|
||||||
</HeaderCard>
|
</HeaderCard>
|
||||||
<div class="tips">
|
<div class="tips">
|
||||||
<el-alert title="请记得前往《分销明细》充值余额,余额不足时用户收益将无法正常入账" type="primary" show-icon :closable="false" />
|
<el-alert title="请记得前往《分销明细》充值余额,余额不足时用户收益将无法正常入账" type="primary" show-icon :closable="false" />
|
||||||
@@ -18,6 +18,8 @@
|
|||||||
<activation_record key="activationRecord" v-if="tabActiveIndex == 2" />
|
<activation_record key="activationRecord" v-if="tabActiveIndex == 2" />
|
||||||
<!-- 分销明细 -->
|
<!-- 分销明细 -->
|
||||||
<distribution_details key="distributionDetails" v-if="tabActiveIndex == 3" />
|
<distribution_details key="distributionDetails" v-if="tabActiveIndex == 3" />
|
||||||
|
<!-- 股东管理群 -->
|
||||||
|
<groupSetting name="groupSetting" key="groupSetting" v-if="tabActiveIndex == 4" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -30,6 +32,7 @@ import setting from "./components/setting.vue";
|
|||||||
import distributor from "./components/distributor.vue";
|
import distributor from "./components/distributor.vue";
|
||||||
import activation_record from "./components/activation_record.vue";
|
import activation_record from "./components/activation_record.vue";
|
||||||
import distribution_details from "./components/distribution_details.vue";
|
import distribution_details from "./components/distribution_details.vue";
|
||||||
|
import groupSetting from "./components/groupSetting.vue";
|
||||||
import { ref, onMounted, watch } from 'vue'
|
import { ref, onMounted, watch } from 'vue'
|
||||||
import { distributionGet, distributionPut } from '@/api/coupon'
|
import { distributionGet, distributionPut } from '@/api/coupon'
|
||||||
|
|
||||||
@@ -53,6 +56,10 @@ const tabList = ref([
|
|||||||
label: '分销明细',
|
label: '分销明细',
|
||||||
value: 3
|
value: 3
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: '股东管理群',
|
||||||
|
value: 3
|
||||||
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const form = ref({
|
const form = ref({
|
||||||
|
|||||||
@@ -0,0 +1,179 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog :title="form.id ? '编辑' : '添加'" width="800px" v-model="visible" @closed="resetForm">
|
||||||
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" label-position="left">
|
||||||
|
<el-form-item label="名称" prop="name">
|
||||||
|
<el-input v-model="form.name" placeholder="请输入轮播图名称" :maxlength="20" style="width: 300px;"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="轮播图片" prop="imageUrl">
|
||||||
|
<div class="column">
|
||||||
|
<div class="center">
|
||||||
|
<SingleImageUpload v-model="form.imageUrl" />
|
||||||
|
</div>
|
||||||
|
<div class="tips" style="margin-bottom: 8px;">建议尺寸:750x300像素,支持jpg、png、gif格式,大小不超过2MB</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="是否可分享" prop="isShareable">
|
||||||
|
<div class="column">
|
||||||
|
<div>
|
||||||
|
<el-radio-group v-model="form.isShareable">
|
||||||
|
<el-radio label="开启" :value="1"></el-radio>
|
||||||
|
<el-radio label="关闭" :value="0"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
<div class="tips">开启时,用户端会显示单独的分享按钮</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="跳转页面" prop="jumpPageId">
|
||||||
|
<linkCard :includes-names="includesNames" v-model="form.jumpPageId" v-model:extendParam="form.extendParam" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="排序值" prop="sort">
|
||||||
|
<el-input v-model="form.sort" @input="e => form.sort = filterNumberInput(e, 1)" style="width: 300px;"
|
||||||
|
placeholder="排序值越大越靠前"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="是否启用">
|
||||||
|
<el-radio-group v-model="form.isEnabled">
|
||||||
|
<el-radio label="启用" :value="1"></el-radio>
|
||||||
|
<el-radio label="禁用" :value="0"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="visible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="submitForm" :loading="loading">确 定</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import _ from 'lodash';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { filterNumberInput } from '@/utils';
|
||||||
|
import SingleImageUpload from '@/components/Upload/SingleImageUpload.vue';
|
||||||
|
import linkCard from './linkCard.vue';
|
||||||
|
import { shareCarouselPost } from '@/api/coupon/index.js';
|
||||||
|
|
||||||
|
const visible = ref(false);
|
||||||
|
const loading = ref(false);
|
||||||
|
const formObj = ref({
|
||||||
|
id: '', // 轮播图ID,编辑时传递
|
||||||
|
name: '', // 轮播图名称(20字内)
|
||||||
|
imageUrl: '', // 轮播图片地址
|
||||||
|
isShareable: 1, // 是否可分享 1=开启 0=关闭
|
||||||
|
jumpPageId: '', // 跳转页面 tb_mini_app_pages的 id
|
||||||
|
extendParam: '', // 扩展参数
|
||||||
|
sort: '', // 排序值,数值越大越靠前
|
||||||
|
isEnabled: 1, // 是否启用 1=启用 0=禁用
|
||||||
|
});
|
||||||
|
const form = ref(_.cloneDeep(formObj.value));
|
||||||
|
function resetForm() {
|
||||||
|
form.value = _.cloneDeep(formObj.value);
|
||||||
|
}
|
||||||
|
const formRef = ref(null);
|
||||||
|
const rules = {
|
||||||
|
name: [
|
||||||
|
{ required: true, message: '请输入轮播图名称', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
imageUrl: [
|
||||||
|
{ required: true, message: '请上传轮播图片', trigger: 'change' }
|
||||||
|
],
|
||||||
|
jumpPageId: [
|
||||||
|
{
|
||||||
|
validator: (rule, value, callback) => {
|
||||||
|
if (form.value.jumpPageId && _.includes(includesNames.value.map(item => item.id), form.value.jumpPageId)) {
|
||||||
|
if (!form.value.extendParam) {
|
||||||
|
callback(new Error('请选择具体菜品'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
sort: [
|
||||||
|
{ required: true, message: '请输入排序值', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const includesNames = ref([
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
name: '套餐推广商品详情页'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '6',
|
||||||
|
name: '商品拼团详情页'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '10',
|
||||||
|
name: '点餐商品详情弹窗页'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '12',
|
||||||
|
name: '积分商品详情页面'
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
function submitForm() {
|
||||||
|
console.log(form.value);
|
||||||
|
|
||||||
|
formRef.value.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
shareCarouselPostAjax();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const emits = defineEmits(['success']);
|
||||||
|
|
||||||
|
// 轮播图配置:新增/修改
|
||||||
|
async function shareCarouselPostAjax() {
|
||||||
|
try {
|
||||||
|
loading.value = true;
|
||||||
|
await shareCarouselPost(form.value);
|
||||||
|
ElNotification({
|
||||||
|
title: '成功',
|
||||||
|
message: '保存成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
emits('success');
|
||||||
|
visible.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function show(obj) {
|
||||||
|
visible.value = true;
|
||||||
|
if (obj && obj.id) {
|
||||||
|
form.value = _.cloneDeep(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
show
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.center {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="row">
|
||||||
|
<el-form :model="queryForm" inline>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Plus" @click="AddBannerRef.show()">添加</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-select v-model="queryForm.isShareable" style="width: 150px;">
|
||||||
|
<el-option label="全部" :value="''" />
|
||||||
|
<el-option label="开启" :value="1" />
|
||||||
|
<el-option label="关闭" :value="0" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-select v-model="queryForm.isEnabled" style="width: 150px;">
|
||||||
|
<el-option label="全部" :value="''" />
|
||||||
|
<el-option label="启用" :value="1" />
|
||||||
|
<el-option label="禁用" :value="0" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-input v-model="queryForm.name" placeholder="请输入名称搜索" style="width: 200px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" :loading="tableData.loading" @click="queryHandle">搜索</el-button>
|
||||||
|
<el-button icon="Refresh" :loading="tableData.loading" @click="resetHandle">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<el-table :data="tableData.list" border stripe v-loading="tableData.loading">
|
||||||
|
<el-table-column label="ID" prop="id"></el-table-column>
|
||||||
|
<el-table-column label="名称" prop="name"></el-table-column>
|
||||||
|
<el-table-column label="图片" prop="imageUrl">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<el-image :src="scope.row.imageUrl" style="width: 50px;height: 50px;"></el-image>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<!-- <el-table-column label="分享" prop="isShareable">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span v-if="scope.row.isShareable == 1">开启</span>
|
||||||
|
<span v-else>关闭</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column> -->
|
||||||
|
<el-table-column label="启用状态" prop="isEnabled">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<el-tag v-if="scope.row.isEnabled == 1" type="primary" disable-transitions>已启用</el-tag>
|
||||||
|
<el-tag v-if="scope.row.isEnabled == 0" type="info" disable-transitions>已禁用</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="排序值" prop="sort"></el-table-column>
|
||||||
|
<el-table-column label="创建时间" prop="createTime" width="200"></el-table-column>
|
||||||
|
<el-table-column label="操作" width="150">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<el-button link type="primary" @click="AddBannerRef.show(scope.row)">编辑</el-button>
|
||||||
|
<el-popconfirm title="确认要删除吗?" @confirm="deleteHandle(scope.row)">
|
||||||
|
<template #reference>
|
||||||
|
<el-button type="danger" link>删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-popconfirm>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<AddBanner @success="queryHandle" ref="AddBannerRef" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import AddBanner from './add_banner.vue';
|
||||||
|
import { shareCarouselGet, shareCarouselDel } from '@/api/coupon/index.js';
|
||||||
|
|
||||||
|
const AddBannerRef = ref(null);
|
||||||
|
|
||||||
|
const queryForm = ref({
|
||||||
|
name: '',
|
||||||
|
isShareable: '', // 是否可分享 1=开启 0=关闭
|
||||||
|
isEnabled: '', // 是否启用 1=启用 0=禁用
|
||||||
|
})
|
||||||
|
|
||||||
|
const tableData = ref({
|
||||||
|
loading: false,
|
||||||
|
list: []
|
||||||
|
})
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
function queryHandle() {
|
||||||
|
getTableData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
function resetHandle() {
|
||||||
|
queryForm.value = {
|
||||||
|
name: '',
|
||||||
|
isShareable: '',
|
||||||
|
isEnabled: '',
|
||||||
|
};
|
||||||
|
queryHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 轮播图配置
|
||||||
|
async function getTableData() {
|
||||||
|
try {
|
||||||
|
tableData.value.loading = true;
|
||||||
|
const res = await shareCarouselGet(queryForm.value);
|
||||||
|
tableData.value.list = res;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
tableData.value.loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除轮播图配置
|
||||||
|
async function deleteHandle(row) {
|
||||||
|
try {
|
||||||
|
await shareCarouselDel(row.id);
|
||||||
|
getTableData();
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getTableData();
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.row {
|
||||||
|
&.mt14 {
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
213
src/views/marketing_center/share_setting/components/linkCard.vue
Normal file
213
src/views/marketing_center/share_setting/components/linkCard.vue
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-select v-model="jumpPageId" style="width: 300px;" placeholder="请选择跳转页面" @change="jumpPageIdChange">
|
||||||
|
<el-option v-for="item in miniPageList" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||||
|
</el-select>
|
||||||
|
<div class="tips">选填,轮播图点击后跳转的目标页面</div>
|
||||||
|
<el-select v-model="goodsId" style="width: 300px;" placeholder="请选择具体菜品,可搜索" clearable filterable remote
|
||||||
|
:remote-method="remoteMethod" :loading="loading" v-if="jumpPageId && isIncludeFlag" @change="goodsIdChange">
|
||||||
|
<el-option v-for="item in goodsList" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import _ from 'lodash';
|
||||||
|
import { ref, onMounted, watch } from 'vue';
|
||||||
|
import { pointsGoodsPage } from '@/api/points/index.js'
|
||||||
|
import API from '@/views/application/list/advertisement/indexconfig/api';
|
||||||
|
import { packageGet, getGbWarePage } from '@/api/market/ware'
|
||||||
|
import productApi from '@/api/product';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
includesNames: {
|
||||||
|
type: Array,
|
||||||
|
default: () => ([])
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const jumpPageId = defineModel({
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const jumpPageName = ref('');
|
||||||
|
const isIncludeFlag = ref(false);
|
||||||
|
|
||||||
|
function checkIsInclude() {
|
||||||
|
// 增加边界判断:避免includesNames为空或item.id不存在导致的错误
|
||||||
|
if (!jumpPageId.value || !Array.isArray(props.includesNames) || props.includesNames.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 提取id数组并判断包含关系
|
||||||
|
const idList = props.includesNames.map(item => item?.id); // 可选链避免item.id不存在
|
||||||
|
return _.includes(idList, jumpPageId.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(jumpPageId, async (newVal, oldVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
await nextTick()
|
||||||
|
watchJumpPageIdChange(newVal)
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
immediate: true, // 可选:首次加载时立即执行一次(根据需求决定)
|
||||||
|
deep: false // 无需深度监听,因为值是String/Number
|
||||||
|
})
|
||||||
|
|
||||||
|
const miniPageList = ref([]);
|
||||||
|
|
||||||
|
// 获取小程序跳转页面列表
|
||||||
|
async function getList() {
|
||||||
|
try {
|
||||||
|
const res = await API.miniAppPagesPage({ page: 1, size: 999 });
|
||||||
|
miniPageList.value = res.records;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function jumpPageIdChange(value) {
|
||||||
|
goodsId.value = '';
|
||||||
|
extendParam.value = ''
|
||||||
|
jumpPageName.value = miniPageList.value.find(item => item.id == value)?.name || '';
|
||||||
|
// 清空具体菜品选择
|
||||||
|
if (checkIsInclude()) {
|
||||||
|
isIncludeFlag.value = true;
|
||||||
|
getGoodsList()
|
||||||
|
} else {
|
||||||
|
isIncludeFlag.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// watch监听jumpPageId变化
|
||||||
|
async function watchJumpPageIdChange(value) {
|
||||||
|
if (miniPageList.value.length === 0) {
|
||||||
|
await getList()
|
||||||
|
}
|
||||||
|
// 清空具体菜品选择
|
||||||
|
if (checkIsInclude()) {
|
||||||
|
jumpPageName.value = miniPageList.value.find(item => item.id == value)?.name || '';
|
||||||
|
isIncludeFlag.value = true;
|
||||||
|
getGoodsList()
|
||||||
|
} else {
|
||||||
|
isIncludeFlag.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
const goodsList = ref([]); // 具体菜品列表
|
||||||
|
const goodsId = defineModel('goodsId', {
|
||||||
|
type: [String, Number],
|
||||||
|
default: ''
|
||||||
|
});
|
||||||
|
const extendParam = defineModel('extendParam', {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听extendParam的变化,解析并赋值给goodsId
|
||||||
|
watch(extendParam, async (newExtendParam, oldExtendParam) => {
|
||||||
|
// console.log('extendParam变化:', newExtendParam);
|
||||||
|
|
||||||
|
// 1. 空值判断:如果extendParam为空,重置goodsId
|
||||||
|
if (!newExtendParam) {
|
||||||
|
goodsId.value = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 解析字符串:匹配goodsId=xxx的格式
|
||||||
|
// 正则表达式说明:匹配goodsId=后接任意字符(非空),直到字符串结束或遇到&等分隔符
|
||||||
|
const reg = /goodsId=([^&]+)/;
|
||||||
|
const matchResult = newExtendParam.match(reg);
|
||||||
|
|
||||||
|
// 3. 提取值并赋值:匹配成功则赋值,否则重置
|
||||||
|
if (matchResult && matchResult[1]) {
|
||||||
|
let extractedGoodsId = matchResult[1];
|
||||||
|
|
||||||
|
// 尝试将 id 转为数字(如果看起来像数字)以保持与后端 id 类型一致
|
||||||
|
const numeric = Number(extractedGoodsId);
|
||||||
|
const parsedId = !Number.isNaN(numeric) ? numeric : extractedGoodsId;
|
||||||
|
|
||||||
|
// 确保 options 已加载,这样 el-select 能根据 value 匹配到对应的 label
|
||||||
|
try {
|
||||||
|
await getGoodsList();
|
||||||
|
} catch (e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一使用字符串类型的 id 以保证与 options 中的 value 匹配
|
||||||
|
goodsId.value = String(parsedId);
|
||||||
|
} else {
|
||||||
|
goodsId.value = ''; // 匹配失败时清空
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
immediate: true, // 初始加载时立即执行一次解析
|
||||||
|
deep: false // 字符串是基本类型,无需深度监听
|
||||||
|
});
|
||||||
|
|
||||||
|
// 具体菜品选择变化
|
||||||
|
function goodsIdChange(value) {
|
||||||
|
// 设置扩展参数,处理清空情况以避免出现 'undefined'
|
||||||
|
if (value === null || typeof value === 'undefined' || value === '') {
|
||||||
|
extendParam.value = '';
|
||||||
|
goodsId.value = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
extendParam.value = `goodsId=${value}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function remoteMethod(value) {
|
||||||
|
getGoodsList(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取商品咧白哦
|
||||||
|
async function getGoodsList(value = '') {
|
||||||
|
try {
|
||||||
|
// 获取套餐列表
|
||||||
|
loading.value = true;
|
||||||
|
let list = [];
|
||||||
|
if (jumpPageName.value == '套餐推广商品详情页') {
|
||||||
|
const res = await packageGet({ page: 1, size: 999, packageName: value });
|
||||||
|
list = res.records.map(item => ({
|
||||||
|
id: String(item.id),
|
||||||
|
name: item.packageName
|
||||||
|
}));
|
||||||
|
} else if (jumpPageName.value == '商品拼团详情页') {
|
||||||
|
const res = await getGbWarePage({ page: 1, size: 999, wareName: value });
|
||||||
|
list = res.records.map(item => ({
|
||||||
|
id: String(item.id),
|
||||||
|
name: item.wareName
|
||||||
|
}));
|
||||||
|
} else if (jumpPageName.value == '点餐商品详情弹窗页') {
|
||||||
|
const res = await productApi.getPage({ name: value });
|
||||||
|
list = res.records.map(item => ({
|
||||||
|
id: String(item.id),
|
||||||
|
name: item.name
|
||||||
|
}));
|
||||||
|
} else if (jumpPageName.value == '积分商品详情页面') {
|
||||||
|
const res = await pointsGoodsPage({ page: 1, size: 999 });
|
||||||
|
list = res.records.map(item => ({
|
||||||
|
id: String(item.id),
|
||||||
|
name: item.goodsName
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
goodsList.value = list;
|
||||||
|
loading.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.tips {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
135
src/views/marketing_center/share_setting/components/setting.vue
Normal file
135
src/views/marketing_center/share_setting/components/setting.vue
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
<template>
|
||||||
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="160px" label-position="left">
|
||||||
|
<el-form-item label="功能开启">
|
||||||
|
<el-switch v-model="form.isEnabled" :active-value="1" :inactive-value="0" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="可获得奖励的分享" prop="rewardSharePages">
|
||||||
|
<el-checkbox-group v-model="form.rewardSharePages">
|
||||||
|
<el-checkbox :label="item.label" :value="item.value" v-for="item in typesList" :key="item.value"></el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-form-item>
|
||||||
|
<div class="header">分享人可获得奖励</div>
|
||||||
|
<el-form-item label="选择优惠券" prop="sharerCouponId">
|
||||||
|
<SelectCoupon v-model="form.sharerCouponId" v-model:name="form.sharerCouponName" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="单次获得优惠券数量" prop="sharerCouponNum">
|
||||||
|
<el-input v-model="form.sharerCouponNum" placeholder="请输入数量"
|
||||||
|
@input="e => form.sharerCouponNum = filterNumberInput(e, 1)" style="width: 300px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="可获得奖励次数">
|
||||||
|
<el-radio-group v-model="form.rewardTimesType">
|
||||||
|
<el-radio label="仅1次" :value="1"></el-radio>
|
||||||
|
<el-radio label="每次分享成功" :value="2"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<div class="header">被分享人可获得奖励</div>
|
||||||
|
<el-form-item label="选择优惠券">
|
||||||
|
<SelectCoupon v-model="form.sharedUserCouponId" v-model:name="form.sharedUserCouponName" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="单次获得优惠券数量">
|
||||||
|
<el-input v-model="form.sharedUserCouponNum" placeholder="请输入数量"
|
||||||
|
@input="e => form.sharedUserCouponNum = filterNumberInput(e, 1)" style="width: 300px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="被分享人弹窗">
|
||||||
|
<el-radio-group v-model="form.isSharedUserPopup">
|
||||||
|
<el-radio label="是" :value="1"></el-radio>
|
||||||
|
<el-radio label="否" :value="0"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="submitForm">保存</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import _ from 'lodash'
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import typesList from '../data.js'
|
||||||
|
import SelectCoupon from '@/components/selectCoupon/index.vue'
|
||||||
|
import { filterNumberInput } from '@/utils/index.js'
|
||||||
|
import { shareBasePost, shareBaseGet } from '@/api/coupon/index.js'
|
||||||
|
|
||||||
|
const formRef = ref(null)
|
||||||
|
const form = ref({
|
||||||
|
isEnabled: 0,
|
||||||
|
rewardSharePages: [], // 可获得奖励的分享页面,用逗号分隔 typesList
|
||||||
|
sharerCouponId: '', // 分享人可获得的优惠券ID
|
||||||
|
sharerCouponName: '', // 分享人可获得的优惠券名称
|
||||||
|
sharerCouponNum: '', // 分享人可获得的优惠券数量
|
||||||
|
rewardTimesType: 1, // 可获得奖励次数 1=仅1次 2=每次分享成功
|
||||||
|
sharedUserCouponId: '', // 被分享人可获得的优惠券ID
|
||||||
|
sharedUserCouponName: '', // 被分享人可获得的优惠券名称
|
||||||
|
sharedUserCouponNum: '', // 被分享人可获得的优惠券数量
|
||||||
|
isSharedUserPopup: 1, // 被分享人获得奖励时是否弹窗 1=是 0=否
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
rewardSharePages: [
|
||||||
|
{ required: true, message: '请选择可获得奖励的分享', trigger: 'change' }
|
||||||
|
],
|
||||||
|
sharerCouponId: [
|
||||||
|
{ required: true, message: '请选择优惠券', trigger: 'change' }
|
||||||
|
],
|
||||||
|
sharerCouponNum: [
|
||||||
|
{ required: true, message: '请输入单次获得优惠券数量', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitForm() {
|
||||||
|
console.log(form.value);
|
||||||
|
formRef.value.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
console.log('提交表单', form.value)
|
||||||
|
shareBasePostAjax()
|
||||||
|
} else {
|
||||||
|
console.log('表单验证失败')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分享奖励基础:新增/修改
|
||||||
|
async function shareBasePostAjax() {
|
||||||
|
try {
|
||||||
|
const data = _.cloneDeep(form.value);
|
||||||
|
data.rewardSharePages = data.rewardSharePages.join(',');
|
||||||
|
await shareBasePost(data);
|
||||||
|
ElNotification({
|
||||||
|
title: '成功',
|
||||||
|
message: '保存成功',
|
||||||
|
type: 'success',
|
||||||
|
duration: 2000
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分享奖励基础 查询
|
||||||
|
async function shareBaseGetAjax() {
|
||||||
|
try {
|
||||||
|
const res = await shareBaseGet();
|
||||||
|
if (res) {
|
||||||
|
form.value = { ...form.value, ...res };
|
||||||
|
form.value.rewardSharePages = res.rewardSharePages ? res.rewardSharePages.split(',') : [];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
// 初始化数据
|
||||||
|
shareBaseGetAjax();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.header {
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
38
src/views/marketing_center/share_setting/data.js
Normal file
38
src/views/marketing_center/share_setting/data.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
export default [
|
||||||
|
{
|
||||||
|
label: '店铺首页',
|
||||||
|
value: 'index'
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// label: '我的',
|
||||||
|
// value: 'dine'
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
label: '点餐页',
|
||||||
|
value: 'eat'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '点餐页-详情',
|
||||||
|
value: 'eat-detail'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '套餐推广-列表',
|
||||||
|
value: 'pp-list'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '套餐推广-详情',
|
||||||
|
value: 'pp-detail'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '商品拼团-列表',
|
||||||
|
value: 'gb-list'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '商品拼团-详情',
|
||||||
|
value: 'gb-detail'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '全民股东',
|
||||||
|
value: 'dis'
|
||||||
|
}
|
||||||
|
]
|
||||||
56
src/views/marketing_center/share_setting/index.vue
Normal file
56
src/views/marketing_center/share_setting/index.vue
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<template>
|
||||||
|
<div class="gyq_container">
|
||||||
|
<div class="gyq_content">
|
||||||
|
<HeaderCard name="分享配置" intro="商家可配置用户分享后可获得的奖励" icon="fxpz">
|
||||||
|
</HeaderCard>
|
||||||
|
<div class="row mt14">
|
||||||
|
<tabHeader v-model="tabActiveIndex" :list="tabList" />
|
||||||
|
</div>
|
||||||
|
<div class="row mt14">
|
||||||
|
<!-- 基础设置 -->
|
||||||
|
<setting key="setting" name="setting" v-if="tabActiveIndex == 0" />
|
||||||
|
<!-- 点餐页轮播图 -->
|
||||||
|
<bannerSetting key="bannerSetting" name="bannerSetting" v-if="tabActiveIndex == 1" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import HeaderCard from "../components/headerCard.vue";
|
||||||
|
import tabHeader from "../components/tabHeader.vue";
|
||||||
|
import setting from "./components/setting.vue";
|
||||||
|
import bannerSetting from "./components/banner_setting.vue";
|
||||||
|
|
||||||
|
const tabActiveIndex = ref(0)
|
||||||
|
|
||||||
|
const tabList = ref([
|
||||||
|
{
|
||||||
|
label: '基础设置',
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '点餐页轮播图',
|
||||||
|
value: 1
|
||||||
|
},
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.gyq_container {
|
||||||
|
padding: 14px;
|
||||||
|
|
||||||
|
.gyq_content {
|
||||||
|
padding: 14px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
&.mt14 {
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -233,7 +233,7 @@ import shopExtendApi from "@/api/account/shopExtend";
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tableActive: "",
|
tableActive: "index_bg",
|
||||||
tableData: [],
|
tableData: [],
|
||||||
selectItem: {},
|
selectItem: {},
|
||||||
imageUrl: "",
|
imageUrl: "",
|
||||||
@@ -248,7 +248,10 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
// 刷新列表数据
|
// 刷新列表数据
|
||||||
async doSubmit() {
|
async doSubmit() {
|
||||||
this.selectItem.value = JSON.stringify(this.imgList)
|
// console.log('this.selectItem.value', this.selectItem.value);
|
||||||
|
// return
|
||||||
|
|
||||||
|
// this.selectItem.value = JSON.stringify(this.imgList)
|
||||||
await shopExtendApi.edit({
|
await shopExtendApi.edit({
|
||||||
...this.selectItem,
|
...this.selectItem,
|
||||||
autokey: this.selectItem.autoKey,
|
autokey: this.selectItem.autoKey,
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-select v-model="query.payType" placeholder="支付类型">
|
<el-select v-model="query.payType" placeholder="支付类型">
|
||||||
<el-option label="微信支付" value="wechatPay" />
|
<el-option label="微信支付" value="WECHAT" />
|
||||||
<el-option label="支付宝支付" value="aliPay" />
|
<el-option label="支付宝支付" value="ALIPAY" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -135,11 +135,11 @@ export default {
|
|||||||
},
|
},
|
||||||
payTypes: [
|
payTypes: [
|
||||||
{
|
{
|
||||||
value: "wechatPay",
|
value: "WECHAT",
|
||||||
label: "微信支付"
|
label: "微信支付"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "aliPay",
|
value: "ALIPAY",
|
||||||
label: "支付宝支付"
|
label: "支付宝支付"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="t">订单类型</div>
|
<div class="t">订单类型</div>
|
||||||
<div class="b">
|
<div class="b">
|
||||||
{{ sendTypeFilter(detail.sendType) }}
|
{{ sendTypeFilter(detail.dineMode) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -46,12 +46,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="t">下单时间</div>
|
<div class="t">下单时间</div>
|
||||||
<div class="b">{{ timeFilter(detail.createdAt) }}</div>
|
<div class="b">{{ timeFilter(detail.createTime) }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<div class="t">支付时间</div>
|
<div class="t">支付时间</div>
|
||||||
<div class="b">
|
<div class="b">
|
||||||
{{ timeFilter(detail.createdAt) }}
|
{{ timeFilter(detail.paidTime) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -51,15 +51,15 @@ export default {
|
|||||||
label: "快递",
|
label: "快递",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "takeaway",
|
key: "take-away",
|
||||||
label: "外卖",
|
label: "外卖",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "takeself",
|
key: "take-out",
|
||||||
label: "自提",
|
label: "自提",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "table",
|
key: "dine-in",
|
||||||
label: "堂食",
|
label: "堂食",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export const statusOptions: statusOptions[] = [
|
|||||||
{ label: "订单完成", value: "done" },
|
{ label: "订单完成", value: "done" },
|
||||||
{ label: "申请退单", value: "refunding" },
|
{ label: "申请退单", value: "refunding" },
|
||||||
{ label: "退单", value: "refund" },
|
{ label: "退单", value: "refund" },
|
||||||
{ label: "部分退单", value: "part-refund" },
|
{ label: "部分退单", value: "part_refund" },
|
||||||
{ label: "取消订单", value: "cancelled" },
|
{ label: "取消订单", value: "cancelled" },
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -78,6 +78,7 @@ export const options: { [key in optionsType]: options[] } = {
|
|||||||
{ label: '支付宝小程序', value: 'ALI' },
|
{ label: '支付宝小程序', value: 'ALI' },
|
||||||
{ label: '收银机客户端', value: 'PC' },
|
{ label: '收银机客户端', value: 'PC' },
|
||||||
{ label: '收款码', value: 'H5' },
|
{ label: '收款码', value: 'H5' },
|
||||||
|
{ label: 'PAD点餐宝', value: 'PAD' },
|
||||||
],
|
],
|
||||||
sendType: [
|
sendType: [
|
||||||
{ label: '快递', value: 'post' },
|
{ label: '快递', value: 'post' },
|
||||||
|
|||||||
@@ -7,17 +7,9 @@
|
|||||||
@reset-click="handleResetClick" /> -->
|
@reset-click="handleResetClick" /> -->
|
||||||
|
|
||||||
<!-- 列表 -->
|
<!-- 列表 -->
|
||||||
<page-content
|
<page-content ref="contentRef" :content-config="contentConfig" @add-click="handleAddClick"
|
||||||
ref="contentRef"
|
@edit-click="handleEditClick" @export-click="handleExportClick" @search-click="handleSearchClick"
|
||||||
:content-config="contentConfig"
|
@toolbar-click="handleToolbarClick" @operat-click="handleOperatClick" @filter-change="handleFilterChange">
|
||||||
@add-click="handleAddClick"
|
|
||||||
@edit-click="handleEditClick"
|
|
||||||
@export-click="handleExportClick"
|
|
||||||
@search-click="handleSearchClick"
|
|
||||||
@toolbar-click="handleToolbarClick"
|
|
||||||
@operat-click="handleOperatClick"
|
|
||||||
@filter-change="handleFilterChange"
|
|
||||||
>
|
|
||||||
<template #status="scope">
|
<template #status="scope">
|
||||||
<el-tag :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
|
<el-tag :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
|
||||||
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
|
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
|
||||||
@@ -25,12 +17,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #slotNameimage="scope">
|
<template #slotNameimage="scope">
|
||||||
<el-image
|
<el-image v-if="scope.row.pic" :src="scope.row.pic" lazy style="width: 40px; height: 40px" />
|
||||||
v-if="scope.row.pic"
|
|
||||||
:src="scope.row.pic"
|
|
||||||
lazy
|
|
||||||
style="width: 40px; height: 40px"
|
|
||||||
/>
|
|
||||||
<div v-else>无</div>
|
<div v-else>无</div>
|
||||||
</template>
|
</template>
|
||||||
<template #gender="scope">
|
<template #gender="scope">
|
||||||
@@ -38,42 +25,26 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #mobile="scope">
|
<template #mobile="scope">
|
||||||
<el-text>{{ scope.row[scope.prop] }}</el-text>
|
<el-text>{{ scope.row[scope.prop] }}</el-text>
|
||||||
<copy-button
|
<copy-button v-if="scope.row[scope.prop]" :text="scope.row[scope.prop]" style="margin-left: 2px" />
|
||||||
v-if="scope.row[scope.prop]"
|
|
||||||
:text="scope.row[scope.prop]"
|
|
||||||
style="margin-left: 2px"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</page-content>
|
</page-content>
|
||||||
|
|
||||||
<!-- 新增 -->
|
<!-- 新增 -->
|
||||||
<page-modal
|
<page-modal ref="addModalRef" :modal-config="addModalConfig" @submit-click="handleSubmitClick">
|
||||||
ref="addModalRef"
|
|
||||||
:modal-config="addModalConfig"
|
|
||||||
@submit-click="handleSubmitClick"
|
|
||||||
>
|
|
||||||
<template #gender="scope">
|
<template #gender="scope">
|
||||||
<Dict v-model="scope.formData[scope.prop]" code="gender" />
|
<Dict v-model="scope.formData[scope.prop]" code="gender" />
|
||||||
</template>
|
</template>
|
||||||
</page-modal>
|
</page-modal>
|
||||||
|
|
||||||
<!-- 编辑 -->
|
<!-- 编辑 -->
|
||||||
<page-modal
|
<page-modal ref="editModalRef" :modal-config="editModalConfig" @submit-click="handleSubmitClick">
|
||||||
ref="editModalRef"
|
|
||||||
:modal-config="editModalConfig"
|
|
||||||
@submit-click="handleSubmitClick"
|
|
||||||
>
|
|
||||||
<template #gender="scope">
|
<template #gender="scope">
|
||||||
<Dict v-model="scope.formData[scope.prop]" code="gender" v-bind="scope.attrs" />
|
<Dict v-model="scope.formData[scope.prop]" code="gender" v-bind="scope.attrs" />
|
||||||
</template>
|
</template>
|
||||||
</page-modal>
|
</page-modal>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<page-content
|
<page-content ref="contentRef" :content-config="contentConfig2" @operat-click="handleOperatClick">
|
||||||
ref="contentRef"
|
|
||||||
:content-config="contentConfig2"
|
|
||||||
@operat-click="handleOperatClick"
|
|
||||||
>
|
|
||||||
<template #status="scope">
|
<template #status="scope">
|
||||||
<el-tag :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
|
<el-tag :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
|
||||||
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
|
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
|
||||||
@@ -95,7 +66,7 @@ import contentConfig from "./categoryconfig/content";
|
|||||||
import contentConfig2 from "./categoryconfig/content2";
|
import contentConfig2 from "./categoryconfig/content2";
|
||||||
import editModalConfig from "./categoryconfig/edit";
|
import editModalConfig from "./categoryconfig/edit";
|
||||||
import searchConfig from "./categoryconfig/search";
|
import searchConfig from "./categoryconfig/search";
|
||||||
import { isSyncStatus } from "@/utils/index";
|
import { isSyncStatus, downloadFile } from "@/utils/index";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
searchRef,
|
searchRef,
|
||||||
@@ -107,7 +78,7 @@ const {
|
|||||||
// handleAddClick,
|
// handleAddClick,
|
||||||
// handleEditClick,
|
// handleEditClick,
|
||||||
handleSubmitClick,
|
handleSubmitClick,
|
||||||
handleExportClick,
|
// handleExportClick,
|
||||||
handleSearchClick,
|
handleSearchClick,
|
||||||
handleFilterChange,
|
handleFilterChange,
|
||||||
} = usePage();
|
} = usePage();
|
||||||
@@ -123,6 +94,18 @@ if (isSyncStatus()) {
|
|||||||
contentConfig.cols[contentConfig.cols.length - 1].operat[0].hidden = false
|
contentConfig.cols[contentConfig.cols.length - 1].operat[0].hidden = false
|
||||||
contentConfig.cols[contentConfig.cols.length - 1].operat[1].hidden = false
|
contentConfig.cols[contentConfig.cols.length - 1].operat[1].hidden = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 导出
|
||||||
|
async function handleExportClick() {
|
||||||
|
try {
|
||||||
|
const filterParams = searchRef.value?.getQueryParams();
|
||||||
|
const file = await UserAPI.exportCategories(filterParams);
|
||||||
|
downloadFile(file, "商品分类列表", "xlsx");
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 新增
|
// 新增
|
||||||
async function handleAddClick() {
|
async function handleAddClick() {
|
||||||
addModalRef.value?.setModalVisible();
|
addModalRef.value?.setModalVisible();
|
||||||
|
|||||||
@@ -52,6 +52,13 @@ const contentConfig: IContentConfig<UserPageQuery> = {
|
|||||||
name: "add",
|
name: "add",
|
||||||
auth: "import",
|
auth: "import",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: "Download",
|
||||||
|
text: "导出",
|
||||||
|
type: "",
|
||||||
|
name: "export",
|
||||||
|
auth: "import",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
cols: [
|
cols: [
|
||||||
// { type: "selection", width: 50, align: "center" },
|
// { type: "selection", width: 50, align: "center" },
|
||||||
@@ -76,7 +83,7 @@ const contentConfig: IContentConfig<UserPageQuery> = {
|
|||||||
fixed: "right",
|
fixed: "right",
|
||||||
width: 280,
|
width: 280,
|
||||||
templet: "tool",
|
templet: "tool",
|
||||||
operat: [{ text: "编辑", icon: 'edit', name: "edit"}, { text: "删除", icon: 'delete', type: 'danger', name: "delete"}],
|
operat: [{ text: "编辑", icon: 'edit', name: "edit" }, { text: "删除", icon: 'delete', type: 'danger', name: "delete" }],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,6 +15,9 @@
|
|||||||
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
|
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template> -->
|
</template> -->
|
||||||
|
<template #custom>
|
||||||
|
<importData :type="3" @close="newHandleQueryClick" />
|
||||||
|
</template>
|
||||||
<template #type="scope">
|
<template #type="scope">
|
||||||
{{ typeFilter(scope.row[scope.prop]) }}
|
{{ typeFilter(scope.row[scope.prop]) }}
|
||||||
</template>
|
</template>
|
||||||
@@ -170,11 +173,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import importData from "@/components/importData/index.vue";
|
||||||
import UserAPI from "@/api/product/index";
|
import UserAPI from "@/api/product/index";
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import type { IObject, IOperatData } from "@/components/CURD/types";
|
import type { IObject, IOperatData } from "@/components/CURD/types";
|
||||||
import usePage from "@/components/CURD/usePage";
|
import usePage from "@/components/CURD/usePage";
|
||||||
import { isSyncStatus } from "@/utils/index";
|
import { isSyncStatus, downloadFile } from "@/utils/index";
|
||||||
import addModalConfig from "./indexconfig/add";
|
import addModalConfig from "./indexconfig/add";
|
||||||
import contentConfig from "./indexconfig/content";
|
import contentConfig from "./indexconfig/content";
|
||||||
import MultiImageUpload from "@/components/Upload/MultiImageUpload.vue";
|
import MultiImageUpload from "@/components/Upload/MultiImageUpload.vue";
|
||||||
@@ -183,7 +187,8 @@ import editModalConfig from "./indexconfig/edit";
|
|||||||
import searchConfig from "./indexconfig/search";
|
import searchConfig from "./indexconfig/search";
|
||||||
import MyDialog from "@/components/mycomponents/myDialog.vue";
|
import MyDialog from "@/components/mycomponents/myDialog.vue";
|
||||||
import Statistics from "./indexconfig/statistics.vue";
|
import Statistics from "./indexconfig/statistics.vue";
|
||||||
import { min } from "lodash";
|
|
||||||
|
const importDataRef = ref(null);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
searchRef,
|
searchRef,
|
||||||
@@ -194,7 +199,7 @@ const {
|
|||||||
handleResetClick,
|
handleResetClick,
|
||||||
// handleEditClick,
|
// handleEditClick,
|
||||||
handleSubmitClick,
|
handleSubmitClick,
|
||||||
handleExportClick,
|
// handleExportClick,
|
||||||
handleSearchClick,
|
handleSearchClick,
|
||||||
handleFilterChange,
|
handleFilterChange,
|
||||||
} = usePage();
|
} = usePage();
|
||||||
@@ -242,13 +247,17 @@ if (isSyncStatus()) {
|
|||||||
contentConfig.cols[contentConfig.cols.length - 1].operat[2].hidden = false;
|
contentConfig.cols[contentConfig.cols.length - 1].operat[2].hidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
console.log(route.query);
|
console.log(route.query);
|
||||||
if (route.query.id) {
|
if (route.query.id) {
|
||||||
contentRef.value?.fetchPageData({ id: route.query.id });
|
contentRef.value?.fetchPageData({ id: route.query.id });
|
||||||
}
|
}
|
||||||
// 获取耗材列表
|
// 获取耗材列表
|
||||||
gethaocaiList();
|
gethaocaiList();
|
||||||
|
|
||||||
|
const res = await UserAPI.getPage()
|
||||||
|
form.warnLine = res.warnLine || ''
|
||||||
|
// console.log('contentRef.value===', res);
|
||||||
});
|
});
|
||||||
|
|
||||||
function newHandleQueryClick(e: IObject | undefined) {
|
function newHandleQueryClick(e: IObject | undefined) {
|
||||||
@@ -299,6 +308,22 @@ function getTongji(params: IObject | undefined) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 显示批量导入
|
||||||
|
function handleUploadClick() {
|
||||||
|
importDataRef.value.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出商品
|
||||||
|
async function handleExportClick() {
|
||||||
|
try {
|
||||||
|
const filterParams = searchRef.value?.getQueryParams();
|
||||||
|
const file = await UserAPI.exportProducts(filterParams);
|
||||||
|
downloadFile(file, "商品列表", "xlsx");
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 新增
|
// 新增
|
||||||
async function handleAddClick() {
|
async function handleAddClick() {
|
||||||
router.push({ name: "addgoods" });
|
router.push({ name: "addgoods" });
|
||||||
@@ -372,6 +397,9 @@ async function handleToolbarClick(name: string) {
|
|||||||
let res = await UserAPI.sync();
|
let res = await UserAPI.sync();
|
||||||
ElMessage.success("操作成功,数据正在后台同步中...");
|
ElMessage.success("操作成功,数据正在后台同步中...");
|
||||||
}
|
}
|
||||||
|
if (name === "upload") {
|
||||||
|
importDataRef.value.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async function confirm() {
|
async function confirm() {
|
||||||
let res = await UserAPI.stockWarning(form.warnLine);
|
let res = await UserAPI.stockWarning(form.warnLine);
|
||||||
|
|||||||
@@ -75,11 +75,17 @@ const contentConfig: IContentConfig<UserPageQuery> = {
|
|||||||
{
|
{
|
||||||
icon: "edit",
|
icon: "edit",
|
||||||
text: "库存预警",
|
text: "库存预警",
|
||||||
type: "info",
|
type: "danger",
|
||||||
name: "custom1",
|
name: "custom1",
|
||||||
auth: "import",
|
auth: "import",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: "Download",
|
||||||
|
text: "导出",
|
||||||
|
type: "",
|
||||||
|
name: "export",
|
||||||
|
auth: "import",
|
||||||
|
}
|
||||||
],
|
],
|
||||||
cols: [
|
cols: [
|
||||||
// { type: "selection", width: 50, align: "center" },
|
// { type: "selection", width: 50, align: "center" },
|
||||||
@@ -127,7 +133,7 @@ const contentConfig: IContentConfig<UserPageQuery> = {
|
|||||||
fixed: "right",
|
fixed: "right",
|
||||||
width: 280,
|
width: 280,
|
||||||
templet: "tool",
|
templet: "tool",
|
||||||
operat: [{ text: "报损", name: ''}, { text: "编辑", icon: 'edit', name: "edit"}, { text: "删除", icon: 'delete', type: 'danger', name: "delete"}],
|
operat: [{ text: "报损", name: '' }, { text: "编辑", icon: 'edit', name: "edit" }, { text: "删除", icon: 'delete', type: 'danger', name: "delete" }],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ import contentConfig from "./unitconfig/content";
|
|||||||
import contentConfig2 from "./unitconfig/content2";
|
import contentConfig2 from "./unitconfig/content2";
|
||||||
import editModalConfig from "./unitconfig/edit";
|
import editModalConfig from "./unitconfig/edit";
|
||||||
import searchConfig from "./unitconfig/search";
|
import searchConfig from "./unitconfig/search";
|
||||||
import { isSyncStatus } from "@/utils/index";
|
import { isSyncStatus, downloadFile } from "@/utils/index";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
searchRef,
|
searchRef,
|
||||||
@@ -73,7 +73,7 @@ const {
|
|||||||
// handleAddClick,
|
// handleAddClick,
|
||||||
// handleEditClick,
|
// handleEditClick,
|
||||||
handleSubmitClick,
|
handleSubmitClick,
|
||||||
handleExportClick,
|
// handleExportClick,
|
||||||
handleSearchClick,
|
handleSearchClick,
|
||||||
handleFilterChange,
|
handleFilterChange,
|
||||||
} = usePage();
|
} = usePage();
|
||||||
@@ -88,6 +88,17 @@ if (isSyncStatus()) {
|
|||||||
contentConfig.cols[contentConfig.cols.length - 1].operat[1].hidden = false
|
contentConfig.cols[contentConfig.cols.length - 1].operat[1].hidden = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 导出商品单位
|
||||||
|
async function handleExportClick() {
|
||||||
|
try {
|
||||||
|
const filterParams = searchRef.value?.getQueryParams();
|
||||||
|
const file = await UserAPI.exportUnits(filterParams);
|
||||||
|
downloadFile(file, "商品单位列表", "xlsx");
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 新增
|
// 新增
|
||||||
async function handleAddClick() {
|
async function handleAddClick() {
|
||||||
addModalRef.value?.setModalVisible();
|
addModalRef.value?.setModalVisible();
|
||||||
|
|||||||
@@ -45,6 +45,13 @@ const contentConfig: IContentConfig<UserPageQuery> = {
|
|||||||
name: "add",
|
name: "add",
|
||||||
auth: "import",
|
auth: "import",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
icon: "Download",
|
||||||
|
text: "导出",
|
||||||
|
type: "",
|
||||||
|
name: "export",
|
||||||
|
auth: "import",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
cols: [
|
cols: [
|
||||||
// { type: "selection", width: 50, align: "center" },
|
// { type: "selection", width: 50, align: "center" },
|
||||||
@@ -56,7 +63,7 @@ const contentConfig: IContentConfig<UserPageQuery> = {
|
|||||||
fixed: "right",
|
fixed: "right",
|
||||||
width: 280,
|
width: 280,
|
||||||
templet: "tool",
|
templet: "tool",
|
||||||
operat: [{ text: "编辑", icon: 'edit', name: "edit"}, { text: "删除", icon: 'delete', type: 'danger', name: "delete"}],
|
operat: [{ text: "编辑", icon: 'edit', name: "edit" }, { text: "删除", icon: 'delete', type: 'danger', name: "delete" }],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -245,8 +245,8 @@ const tableData = reactive({
|
|||||||
// 支付方式类型
|
// 支付方式类型
|
||||||
function payTypeFilter(t) {
|
function payTypeFilter(t) {
|
||||||
const m = {
|
const m = {
|
||||||
wechatPay: '微信支付',
|
WECHAT: '微信支付',
|
||||||
aliPay: '支付宝支付'
|
ALIPAY: '支付宝支付'
|
||||||
}
|
}
|
||||||
return m[t]
|
return m[t]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,86 +1,191 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog :title="state.form.id ? '编辑店铺' : '添加店铺'" v-model="state.dialogVisible" @close="reset">
|
<div>
|
||||||
<div style="height: 50vh; overflow-y: auto">
|
<el-dialog
|
||||||
<el-form ref="refForm" :model="state.form" :rules="state.rules" label-width="120px" label-position="left">
|
:title="state.form.id ? '编辑店铺' : '添加店铺'"
|
||||||
<el-form-item label="店铺名称" prop="shopName">
|
v-model="state.dialogVisible"
|
||||||
<el-input v-model="state.form.shopName" placeholder="请输入门店名称"></el-input>
|
@close="reset"
|
||||||
</el-form-item>
|
>
|
||||||
<el-form-item label="店铺类型">
|
<div style="height: 50vh; overflow-y: auto">
|
||||||
<el-radio-group v-model="state.form.shopType" :disabled="state.isEdit || state.type == 'addBranch'">
|
<el-form
|
||||||
<el-radio-button value="only">单店</el-radio-button>
|
ref="refForm"
|
||||||
<el-radio-button value="chain">连锁店</el-radio-button>
|
:model="state.form"
|
||||||
<el-radio-button value="join">加盟店</el-radio-button>
|
:rules="state.rules"
|
||||||
</el-radio-group>
|
label-width="120px"
|
||||||
<div class="tips"><el-alert title="请谨慎修改" type="warning" size="7" effect="dark" show-icon :closable="false"/></div>
|
label-position="left"
|
||||||
|
>
|
||||||
</el-form-item>
|
<el-form-item label="店铺名称" prop="shopName">
|
||||||
<el-form-item label="是否为主店" prop="isHeadShop" v-if="state.form.shopType != 'only'">
|
<el-input v-model="state.form.shopName" placeholder="请输入门店名称"></el-input>
|
||||||
<el-radio-group v-model="state.form.isHeadShop" @change=" state.form.mainId = ''" :disabled="state.isEdit || state.type == 'addBranch'">
|
</el-form-item>
|
||||||
<el-radio :value="1">是</el-radio>
|
<el-form-item label="店铺类型">
|
||||||
<el-radio :value="0">否</el-radio>
|
<el-radio-group
|
||||||
</el-radio-group>
|
v-model="state.form.shopType"
|
||||||
</el-form-item>
|
:disabled="state.isEdit || state.type == 'addBranch'"
|
||||||
<el-form-item label="选择主店" prop="mainId" v-if="state.form.isHeadShop == '0'&&state.form.shopType != 'only'">
|
>
|
||||||
<!-- <el-form-item label="主店账号" prop="mainId" v-if="state.form.shopType != 'only'"> -->
|
<el-radio-button value="only">单店</el-radio-button>
|
||||||
<el-select v-model="state.form.mainId" placeholder="请选择主店铺" filterable reserve-keyword
|
<el-radio-button value="chain">连锁店</el-radio-button>
|
||||||
:remote-method="getTableData" :loading="state.shopListLoading" :disabled="state.isEdit || state.type == 'addBranch'">
|
<el-radio-button value="join">加盟店</el-radio-button>
|
||||||
<el-option v-for="item in state.shopList" :label="`${item.shopName}`" :value="item.id"
|
</el-radio-group>
|
||||||
:key="item.id"></el-option>
|
<div class="tips">
|
||||||
</el-select>
|
<el-alert
|
||||||
</el-form-item>
|
title="请谨慎修改"
|
||||||
<el-form-item label="连锁店扩展店名">
|
type="warning"
|
||||||
<el-input v-model="state.form.chainName" placeholder="请输入连锁店扩展店名"></el-input>
|
size="7"
|
||||||
</el-form-item>
|
effect="dark"
|
||||||
<el-form-item label="门店logo" prop="logo">
|
show-icon
|
||||||
<SingleImageUpload v-model="state.form.logo" />
|
:closable="false"
|
||||||
</el-form-item>
|
/>
|
||||||
<el-form-item label="门店照片">
|
</div>
|
||||||
<SingleImageUpload v-model="state.form.frontImg" />
|
</el-form-item>
|
||||||
</el-form-item>
|
<el-form-item label="是否为主店" prop="isHeadShop" v-if="state.form.shopType != 'only'">
|
||||||
<el-form-item label="经营模式">
|
<el-radio-group
|
||||||
<el-radio-group v-model="state.form.registerType">
|
v-model="state.form.isHeadShop"
|
||||||
<el-radio-button value="before">先付费</el-radio-button>
|
@change="state.form.mainId = ''"
|
||||||
<el-radio-button value="after">后付费</el-radio-button>
|
:disabled="state.isEdit || state.type == 'addBranch'"
|
||||||
</el-radio-group>
|
>
|
||||||
<div class="tips"><el-alert title="请谨慎修改" type="warning" size="7" effect="dark" show-icon :closable="false"/></div>
|
<el-radio :value="1">是</el-radio>
|
||||||
|
<el-radio :value="0">否</el-radio>
|
||||||
</el-form-item>
|
</el-radio-group>
|
||||||
<el-form-item label="管理方式" v-if="state.form.shopType != 'only'">
|
</el-form-item>
|
||||||
<el-radio-group v-model="state.form.tubeType">
|
<el-form-item
|
||||||
<el-radio-button :value="0">不可直接管理</el-radio-button>
|
label="选择主店"
|
||||||
<el-radio-button :value="1">直接管理</el-radio-button>
|
prop="mainId"
|
||||||
</el-radio-group>
|
v-if="state.form.isHeadShop == '0' && state.form.shopType != 'only'"
|
||||||
<div class="tips"><el-alert title="请谨慎修改" type="warning" size="7" effect="dark" show-icon :closable="false"/></div>
|
>
|
||||||
|
<!-- <el-form-item label="主店账号" prop="mainId" v-if="state.form.shopType != 'only'"> -->
|
||||||
</el-form-item>
|
<el-select
|
||||||
<el-form-item label="试用/正式">
|
v-model="state.form.mainId"
|
||||||
<el-radio-group v-model="state.form.profiles">
|
placeholder="请选择主店铺"
|
||||||
<el-radio-button value="probation">试用</el-radio-button>
|
filterable
|
||||||
<el-radio-button value="release">正式</el-radio-button>
|
reserve-keyword
|
||||||
</el-radio-group>
|
:remote-method="getTableData"
|
||||||
</el-form-item>
|
:loading="state.shopListLoading"
|
||||||
<el-form-item label="激活码">
|
:disabled="state.isEdit || state.type == 'addBranch'"
|
||||||
<el-input v-model="state.form.activateCode" placeholder="请输入激活码"></el-input>
|
>
|
||||||
<div class="tips">注:输入有效激活码表示添加的同时直接激活该店铺。</div>
|
<el-option
|
||||||
</el-form-item>
|
v-for="item in state.shopList"
|
||||||
<el-form-item label="登录账号" prop="accountName">
|
:label="`${item.shopName}`"
|
||||||
<el-input v-model="state.form.accountName" placeholder="请输入登录账号"></el-input>
|
:value="item.id"
|
||||||
</el-form-item>
|
:key="item.id"
|
||||||
<el-form-item label="登录密码" prop="password" v-if="!state.form.id">
|
></el-option>
|
||||||
<el-input type="password" show-password v-model="state.form.accountPwd" placeholder="请输入登录密码"></el-input>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="联系电话" prop="phone">
|
<el-form-item label="连锁店扩展店名">
|
||||||
<el-input v-model="state.form.phone" placeholder="请输入联系电话"></el-input>
|
<el-input v-model="state.form.chainName" placeholder="请输入连锁店扩展店名"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备数量">
|
<el-form-item label="门店logo" prop="logo">
|
||||||
<el-input-number v-model="state.form.supportDeviceNumber" controls-position="right" :min="1" :step="1"
|
<SingleImageUpload v-model="state.form.logo" />
|
||||||
step-strictly></el-input-number>
|
</el-form-item>
|
||||||
</el-form-item>
|
<el-form-item label="门店照片">
|
||||||
<!-- <el-form-item label="外卖起送金额">
|
<SingleImageUpload v-model="state.form.frontImg" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="经营模式">
|
||||||
|
<el-radio-group v-model="state.form.registerType">
|
||||||
|
<el-radio-button value="before">先付费</el-radio-button>
|
||||||
|
<el-radio-button value="after">后付费</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
<div class="tips">
|
||||||
|
<el-alert
|
||||||
|
title="请谨慎修改"
|
||||||
|
type="warning"
|
||||||
|
size="7"
|
||||||
|
effect="dark"
|
||||||
|
show-icon
|
||||||
|
:closable="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="管理方式" v-if="state.form.shopType != 'only'">
|
||||||
|
<el-radio-group v-model="state.form.tubeType">
|
||||||
|
<el-radio-button :value="0">不可直接管理</el-radio-button>
|
||||||
|
<el-radio-button :value="1">直接管理</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
<div class="tips">
|
||||||
|
<el-alert
|
||||||
|
title="请谨慎修改"
|
||||||
|
type="warning"
|
||||||
|
size="7"
|
||||||
|
effect="dark"
|
||||||
|
show-icon
|
||||||
|
:closable="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商户版本">
|
||||||
|
<el-radio-group v-model="state.form.profiles">
|
||||||
|
<el-radio-button value="probation">试用</el-radio-button>
|
||||||
|
<el-radio-button value="release">正式</el-radio-button>
|
||||||
|
</el-radio-group>
|
||||||
|
<div class="tips">
|
||||||
|
<el-alert
|
||||||
|
title="请谨慎修改"
|
||||||
|
type="warning"
|
||||||
|
size="7"
|
||||||
|
effect="dark"
|
||||||
|
show-icon
|
||||||
|
:closable="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="激活码">
|
||||||
|
<el-input v-model="state.form.activateCode" placeholder="请输入激活码"></el-input>
|
||||||
|
<div class="tips">注:输入有效激活码表示添加的同时直接激活该店铺。</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="登录账号" prop="accountName">
|
||||||
|
<el-input v-model="state.form.accountName" placeholder="请输入登录账号"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="登录密码" prop="password" v-if="!state.form.id">
|
||||||
|
<el-input
|
||||||
|
type="password"
|
||||||
|
show-password
|
||||||
|
v-model="state.form.accountPwd"
|
||||||
|
placeholder="请输入登录密码"
|
||||||
|
></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="联系电话" prop="phone">
|
||||||
|
<el-input v-model="state.form.phone" placeholder="请输入联系电话"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备数量">
|
||||||
|
<el-input-number
|
||||||
|
v-model="state.form.supportDeviceNumber"
|
||||||
|
controls-position="right"
|
||||||
|
:min="1"
|
||||||
|
:step="1"
|
||||||
|
step-strictly
|
||||||
|
></el-input-number>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- <el-form-item label="外卖起送金额">
|
||||||
<el-input-number v-model="form.takeaway_money" placeholder="0.00" controls-position="right"
|
<el-input-number v-model="form.takeaway_money" placeholder="0.00" controls-position="right"
|
||||||
:min="0"></el-input-number>
|
:min="0"></el-input-number>
|
||||||
</el-form-item> -->
|
</el-form-item> -->
|
||||||
<el-form-item label="店铺经度" prop="lat">
|
<el-form-item label="店铺地址" prop="districts">
|
||||||
|
<AddressSelect
|
||||||
|
v-model:prov="state.form.provinces"
|
||||||
|
v-model:city="state.form.cities"
|
||||||
|
v-model:area="state.form.districts"
|
||||||
|
></AddressSelect>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="经度" prop="lng">
|
||||||
|
<el-input v-model="state.form.lng" placeholder="经度"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="4">
|
||||||
|
<el-form-item label="纬度" prop="lat" label-width="auto">
|
||||||
|
<el-input v-model="state.form.lat" placeholder="纬度"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="4">
|
||||||
|
<el-button type="primary" plain icon="place" @click="latShow = true">
|
||||||
|
打开地图复制坐标
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <el-form-item label="店铺经度" prop="lat">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="9" v-if="state.form.provinces">
|
<el-col :span="9" v-if="state.form.provinces">
|
||||||
<el-input :value="`${state.form.provinces}-${state.form.cities}-${state.form.districts}`" disabled />
|
<el-input :value="`${state.form.provinces}-${state.form.cities}-${state.form.districts}`" disabled />
|
||||||
@@ -97,69 +202,105 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form-item>
|
</el-form-item> -->
|
||||||
<el-form-item label="店铺详细地址">
|
<el-form-item label="店铺详细地址">
|
||||||
<el-input type="textarea" v-model="state.form.address" placeholder="请输入门店详细地址"></el-input>
|
<el-input
|
||||||
</el-form-item>
|
type="textarea"
|
||||||
<el-form-item label="店铺简介">
|
v-model="state.form.address"
|
||||||
<el-input type="textarea" v-model="state.form.detail" placeholder="请输入店铺简介"></el-input>
|
placeholder="请输入门店详细地址"
|
||||||
</el-form-item>
|
></el-input>
|
||||||
<el-form-item label="状态">
|
</el-form-item>
|
||||||
<el-radio-group v-model="state.form.status">
|
<el-form-item label="店铺简介">
|
||||||
<el-radio :value="1">开启</el-radio>
|
<el-input
|
||||||
<el-radio :value="0">关闭</el-radio>
|
type="textarea"
|
||||||
</el-radio-group>
|
v-model="state.form.detail"
|
||||||
</el-form-item>
|
placeholder="请输入店铺简介"
|
||||||
</el-form>
|
></el-input>
|
||||||
</div>
|
</el-form-item>
|
||||||
<el-dialog title="选择地址" v-model="state.showLocation" :modal="false" :modal-append-to-body="false">
|
<el-form-item label="状态">
|
||||||
<div class="map_box">
|
<el-radio-group v-model="state.form.status">
|
||||||
<div class="map">
|
<el-radio :value="1">开启</el-radio>
|
||||||
<el-amap ref="map" :center="state.amapOptions.center" @init="mapInit">
|
<el-radio :value="0">关闭</el-radio>
|
||||||
<el-amap-marker :position="state.amapOptions.center"></el-amap-marker>
|
</el-radio-group>
|
||||||
</el-amap>
|
</el-form-item>
|
||||||
</div>
|
</el-form>
|
||||||
<div class="search_box">
|
|
||||||
<el-input v-model="state.searchOption.keyword" placeholder="请输入关键字" @focus="state.searchOption.focus = true"
|
|
||||||
@blur="autoCompleteSearchBlur" @input="autoCompleteSearch(state.searchOption.keyword)">
|
|
||||||
<template #append>
|
|
||||||
<el-button type="primary" @click="placeSearchSearch(state.searchOption.keyword)">
|
|
||||||
搜索
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
<div class="list" v-if="state.searchOption.focus && state.searchOption.show">
|
|
||||||
<div class="item" @click="autoCompleteListClick(item)" v-for="item in state.autoCompleteList"
|
|
||||||
:key="item.id">
|
|
||||||
{{ item.name }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="search_wrap">
|
|
||||||
<div class="item" v-for="item in state.locationSearchList" :key="item.id">
|
|
||||||
<div class="left">
|
|
||||||
<div class="name">{{ item.name }}-{{ item.address }}</div>
|
|
||||||
<div class="location">经纬度:{{ item.location.lng }},{{ item.location.lat }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="btn">
|
|
||||||
<el-button type="primary" @click="selectLocationHandle(item)">选择</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<el-dialog
|
||||||
|
title="选择地址"
|
||||||
|
v-model="state.showLocation"
|
||||||
|
:modal="false"
|
||||||
|
:modal-append-to-body="false"
|
||||||
|
>
|
||||||
|
<div class="map_box">
|
||||||
|
<div class="map">
|
||||||
|
<el-amap ref="map" :center="state.amapOptions.center" @init="mapInit">
|
||||||
|
<el-amap-marker :position="state.amapOptions.center"></el-amap-marker>
|
||||||
|
</el-amap>
|
||||||
|
</div>
|
||||||
|
<div class="search_box">
|
||||||
|
<el-input
|
||||||
|
v-model="state.searchOption.keyword"
|
||||||
|
placeholder="请输入关键字"
|
||||||
|
@focus="state.searchOption.focus = true"
|
||||||
|
@blur="autoCompleteSearchBlur"
|
||||||
|
@input="autoCompleteSearch(state.searchOption.keyword)"
|
||||||
|
>
|
||||||
|
<template #append>
|
||||||
|
<el-button type="primary" @click="placeSearchSearch(state.searchOption.keyword)">
|
||||||
|
搜索
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<div class="list" v-if="state.searchOption.focus && state.searchOption.show">
|
||||||
|
<div
|
||||||
|
class="item"
|
||||||
|
@click="autoCompleteListClick(item)"
|
||||||
|
v-for="item in state.autoCompleteList"
|
||||||
|
:key="item.id"
|
||||||
|
>
|
||||||
|
{{ item.name }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="search_wrap">
|
||||||
|
<div class="item" v-for="item in state.locationSearchList" :key="item.id">
|
||||||
|
<div class="left">
|
||||||
|
<div class="name">{{ item.name }}-{{ item.address }}</div>
|
||||||
|
<div class="location">经纬度:{{ item.location.lng }},{{ item.location.lat }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="btn">
|
||||||
|
<el-button type="primary" @click="selectLocationHandle(item)">选择</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="close">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submitHandle" :loading="state.formLoading">
|
||||||
|
<span v-if="!state.formLoading">保存</span>
|
||||||
|
<span v-else>保存中...</span>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<el-dialog title="坐标搜索" v-model="latShow" width="60vw">
|
||||||
<template #footer>
|
<iframe
|
||||||
<div class="dialog-footer">
|
style="width: 100%; height: 60vh"
|
||||||
<el-button @click="close">取消</el-button>
|
src="https://lbs.baidu.com/maptool/getpoint"
|
||||||
<el-button type="primary" @click="submitHandle" :loading="state.formLoading">
|
frameborder="0"
|
||||||
<span v-if="!state.formLoading">保存</span>
|
></iframe>
|
||||||
<span v-else>保存中...</span>
|
<template #footer>
|
||||||
</el-button>
|
<div class="dialog-footer">
|
||||||
</div>
|
<el-button @click="latShow = false">取消</el-button>
|
||||||
</template>
|
<el-button type="primary" @click="latConfirm">确认</el-button>
|
||||||
</el-dialog>
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -170,6 +311,8 @@ import { initMapLoad } from "@/utils/mapLoadUtil";
|
|||||||
import { ElNotification } from "element-plus";
|
import { ElNotification } from "element-plus";
|
||||||
// { geocode, ShopApi.getList }
|
// { geocode, ShopApi.getList }
|
||||||
import ShopApi from "@/api/account/shop";
|
import ShopApi from "@/api/account/shop";
|
||||||
|
|
||||||
|
const latShow = ref(false);
|
||||||
const validateLogo = (rule, value, callback) => {
|
const validateLogo = (rule, value, callback) => {
|
||||||
if (!state.form.logo) {
|
if (!state.form.logo) {
|
||||||
callback(new Error("请上传门店logo"));
|
callback(new Error("请上传门店logo"));
|
||||||
@@ -177,6 +320,28 @@ const validateLogo = (rule, value, callback) => {
|
|||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
async function latConfirm() {
|
||||||
|
//js获取当前剪贴板内容
|
||||||
|
try {
|
||||||
|
// 核心:异步读取剪贴板文本内容
|
||||||
|
const clipboardText = await navigator.clipboard.readText();
|
||||||
|
|
||||||
|
// 显示获取到的内容
|
||||||
|
console.log("剪贴板内容:", clipboardText);
|
||||||
|
if (clipboardText && clipboardText.indexOf(",") > 0) {
|
||||||
|
const latLng = clipboardText.split(",");
|
||||||
|
state.form.lat = latLng[1];
|
||||||
|
state.form.lng = latLng[0];
|
||||||
|
latShow.value = false;
|
||||||
|
} else [ElMessage.error("请搜索地址后复制经纬度")];
|
||||||
|
} catch (err) {
|
||||||
|
// 捕获异常(用户拒绝权限、浏览器不支持、非交互上下文等)
|
||||||
|
console.error("获取剪贴板失败:", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function openMap() {
|
||||||
|
window.open("https://lbs.baidu.com/maptool/getpoint");
|
||||||
|
}
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
uploadImg: uploadImg,
|
uploadImg: uploadImg,
|
||||||
@@ -213,7 +378,7 @@ const state = reactive({
|
|||||||
chainName: "",
|
chainName: "",
|
||||||
isHeadShop: 0,
|
isHeadShop: 0,
|
||||||
},
|
},
|
||||||
type: '',
|
type: "",
|
||||||
resetForm: "",
|
resetForm: "",
|
||||||
rules: {
|
rules: {
|
||||||
activateCode: [
|
activateCode: [
|
||||||
@@ -244,6 +409,20 @@ const state = reactive({
|
|||||||
trigger: "blur",
|
trigger: "blur",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
districts: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: "请选择店铺地址",
|
||||||
|
trigger: "change",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
lng: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: "请选择坐标",
|
||||||
|
trigger: "change",
|
||||||
|
},
|
||||||
|
],
|
||||||
lat: [
|
lat: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
@@ -311,7 +490,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 获取商家列表
|
// 获取商家列表
|
||||||
async function getTableData(query = "") {
|
async function getTableData(query = "") {
|
||||||
console.log(123)
|
console.log(123);
|
||||||
state.shopListLoading = true;
|
state.shopListLoading = true;
|
||||||
try {
|
try {
|
||||||
const res = await ShopApi.getList({
|
const res = await ShopApi.getList({
|
||||||
@@ -360,7 +539,7 @@ function submitHandle() {
|
|||||||
type: "success",
|
type: "success",
|
||||||
});
|
});
|
||||||
close();
|
close();
|
||||||
location.reload()
|
location.reload();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
state.formLoading = false;
|
state.formLoading = false;
|
||||||
console.log(error);
|
console.log(error);
|
||||||
@@ -376,7 +555,7 @@ function handleSuccess(response, file, fileList) {
|
|||||||
state.files = response.data;
|
state.files = response.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
function show(obj,type) {
|
function show(obj, type) {
|
||||||
getTableData();
|
getTableData();
|
||||||
state.dialogVisible = true;
|
state.dialogVisible = true;
|
||||||
if (obj && obj.id) {
|
if (obj && obj.id) {
|
||||||
@@ -386,13 +565,13 @@ function show(obj,type) {
|
|||||||
if (obj && obj.mainId) {
|
if (obj && obj.mainId) {
|
||||||
Object.assign(state.form, obj);
|
Object.assign(state.form, obj);
|
||||||
}
|
}
|
||||||
if( type ){
|
if (type) {
|
||||||
state.type = type
|
state.type = type;
|
||||||
}
|
}
|
||||||
console.log(state.form);
|
console.log(state.form);
|
||||||
console.log(state.type);
|
console.log(state.type);
|
||||||
if( state.form.shopType != 'only'){
|
if (state.form.shopType != "only") {
|
||||||
state.isEdit = true
|
state.isEdit = true;
|
||||||
}
|
}
|
||||||
for (let key in state.rules) {
|
for (let key in state.rules) {
|
||||||
if (key === "accountName") {
|
if (key === "accountName") {
|
||||||
@@ -409,12 +588,12 @@ function close() {
|
|||||||
state.dialogVisible = false;
|
state.dialogVisible = false;
|
||||||
state.form = { ...state.resetForm };
|
state.form = { ...state.resetForm };
|
||||||
state.type = "";
|
state.type = "";
|
||||||
state.isEdit = false
|
state.isEdit = false;
|
||||||
}
|
}
|
||||||
function reset() {
|
function reset() {
|
||||||
state.form = { ...state.resetForm };
|
state.form = { ...state.resetForm };
|
||||||
state.type = "";
|
state.type = "";
|
||||||
state.isEdit = false
|
state.isEdit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ElMap = undefined;
|
let ElMap = undefined;
|
||||||
@@ -551,7 +730,7 @@ defineExpose({
|
|||||||
.amap-sug-result {
|
.amap-sug-result {
|
||||||
z-index: 2000;
|
z-index: 2000;
|
||||||
}
|
}
|
||||||
.tips{
|
.tips {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,156 +1,110 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog v-model="dialogVisible" :show-close="false" @close="reset">
|
<div class="row mt14">
|
||||||
<el-tabs v-model="activeName">
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px" label-position="left">
|
||||||
<el-tab-pane label="聚合支付" name="pay">
|
<el-form-item label="店铺ID" prop="storeId">
|
||||||
<el-form ref="form" :model="form" label-width="120px" label-position="left">
|
<el-input v-model="form.storeId" placeholder="请输入店铺ID" :style="inputStyle"></el-input>
|
||||||
<el-form-item label="店铺id">
|
</el-form-item>
|
||||||
<el-input v-model="form.storeId" placeholder="请输入店铺id"></el-input>
|
<el-form-item label="商户名称" prop="merchantName">
|
||||||
</el-form-item>
|
<el-input v-model="form.merchantName" placeholder="请输入商户名称" :style="inputStyle"></el-input>
|
||||||
<el-form-item label="商户名称">
|
</el-form-item>
|
||||||
<el-input v-model="form.merchantName" placeholder="请输入支付系统商户名称"></el-input>
|
<el-form-item label="appId" prop="appId">
|
||||||
</el-form-item>
|
<el-input v-model="form.appId" placeholder="请输入appId" :style="inputStyle"></el-input>
|
||||||
<el-form-item label="商户应用id">
|
</el-form-item>
|
||||||
<el-input v-model="form.appId" placeholder="请输入商户应用id"></el-input>
|
<el-form-item label="appSecret" prop="appSecret">
|
||||||
</el-form-item>
|
<el-input type="textarea" :rows="4" v-model="form.appSecret" placeholder="请输入appSecret"
|
||||||
<el-form-item label="商户密钥">
|
:style="inputStyle"></el-input>
|
||||||
<el-input
|
</el-form-item>
|
||||||
type="textarea"
|
<el-form-item>
|
||||||
v-model="form.appSecret"
|
<el-button type="primary" @click="submitHandle" v-loading="loading">保存</el-button>
|
||||||
placeholder="请输入商户密钥"
|
</el-form-item>
|
||||||
></el-input>
|
</el-form>
|
||||||
</el-form-item>
|
</div>
|
||||||
<el-form-item label="支付密码">
|
|
||||||
<el-input v-model="form.payPassword" placeholder="请输入支付密码"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="微信appid">
|
|
||||||
<el-input
|
|
||||||
v-model="form.wechatSmallAppid"
|
|
||||||
placeholder="请输入微信小程序appid"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="支付宝appid">
|
|
||||||
<el-input
|
|
||||||
v-model="form.alipaySmallAppid"
|
|
||||||
placeholder="请输入支付宝小程序appid"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<!-- <el-form-item label="支付宝商户号">
|
|
||||||
<el-input v-model="form.alipayAppId" placeholder="请输入支付宝商户号"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="支付宝商户密钥">
|
|
||||||
<el-input v-model="form.alipayAppToken" placeholder="请输入支付宝商户密钥"></el-input>
|
|
||||||
</el-form-item> -->
|
|
||||||
|
|
||||||
<!-- <el-form-item label="状态">
|
|
||||||
<el-radio-group v-model="form.status">
|
|
||||||
<el-radio :value="1">启用</el-radio>
|
|
||||||
<el-radio :value="-1">禁用</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item> -->
|
|
||||||
</el-form>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
<template #footer>
|
|
||||||
<div class="dialog-footer">
|
|
||||||
<el-button @click="close">取消</el-button>
|
|
||||||
<el-button type="primary" @click="submitHandle" :loading="formLoading">
|
|
||||||
<span v-if="!formLoading">保存</span>
|
|
||||||
<span v-else>保存中...</span>
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
// import { tbMerchantThirdApply, tbMerchantThirdApplyPut } from "@/api/shop";
|
import { ref } from 'vue'
|
||||||
import ShopApi from "@/api/account/shop";
|
import { useRoute } from 'vue-router'
|
||||||
import shopMerchantApi from "@/api/account/shopMerchant";
|
import { shopMerchantPut } from '@/api/common'
|
||||||
import { ElNotification } from "element-plus";
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dialogVisible: false,
|
|
||||||
activeName: "pay",
|
|
||||||
formLoading: false,
|
|
||||||
form: {
|
|
||||||
appSecret: "",
|
|
||||||
id: "",
|
|
||||||
payPassword: "",
|
|
||||||
status: 1,
|
|
||||||
appId: "",
|
|
||||||
wechatSmallAppid: "",
|
|
||||||
storeId: "",
|
|
||||||
alipaySmallAppid: "",
|
|
||||||
alipayAppToken: "",
|
|
||||||
alipayAppId: "",
|
|
||||||
},
|
|
||||||
shopId: "",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 保存
|
|
||||||
async submitHandle() {
|
|
||||||
this.formLoading = true;
|
|
||||||
try {
|
|
||||||
await shopMerchantApi.edit(this.shopId, this.form);
|
|
||||||
this.$emit("success");
|
|
||||||
this.formLoading = false;
|
|
||||||
ElNotification({
|
|
||||||
title: "成功",
|
|
||||||
message: `修改成功`,
|
|
||||||
type: "success",
|
|
||||||
});
|
|
||||||
this.close();
|
|
||||||
} catch (error) {
|
|
||||||
this.formLoading = false;
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
close() {
|
|
||||||
this.dialogVisible = false;
|
|
||||||
},
|
|
||||||
reset() {
|
|
||||||
this.form.appSecret = "";
|
|
||||||
this.form.id = "";
|
|
||||||
this.form.payPassword = "";
|
|
||||||
this.form.status = 1;
|
|
||||||
this.form.appId = "";
|
|
||||||
this.shopId = "";
|
|
||||||
},
|
|
||||||
// 详情(配置三方支付)
|
|
||||||
async getDetail(id) {
|
|
||||||
console.log(id);
|
|
||||||
this.shopId = id;
|
|
||||||
try {
|
|
||||||
const res = await shopMerchantApi.get(id);
|
|
||||||
this.form.appSecret = res.appSecret || "";
|
|
||||||
this.form.payPassword = res.payPassword || "";
|
|
||||||
this.form.status = res.status || "";
|
|
||||||
this.form.appId = res.appId || "";
|
|
||||||
this.form.wechatSmallAppid = res.wechatSmallAppid || "";
|
|
||||||
this.form.alipaySmallAppid = res.alipaySmallAppid || "";
|
|
||||||
this.form.merchantName = res.merchantName || "";
|
|
||||||
//this.form.alipayAppToken = res.alipayAppToken
|
|
||||||
//this.form.alipayAppId = res.alipayAppId
|
|
||||||
this.form.storeId = res.storeId || "";
|
|
||||||
this.dialogVisible = true;
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
show(obj) {
|
|
||||||
if (obj && obj.id) {
|
|
||||||
this.form.id = obj.id;
|
|
||||||
this.getDetail(obj.id);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
const inputStyle = {
|
||||||
:deep(.el-dialog__header) {
|
width: '500px'
|
||||||
padding: 0;
|
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
const props = defineProps({
|
||||||
|
detail: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
const form = defineModel({
|
||||||
|
storeId: '',
|
||||||
|
merchantName: '',
|
||||||
|
appId: '',
|
||||||
|
appSecret: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = ref({
|
||||||
|
storeId: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入店铺ID',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
merchantName: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入店铺名称',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
appId: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入appId',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
appSecret: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入appSecret',
|
||||||
|
trigger: 'blur'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 验证表单
|
||||||
|
function submitHandle() {
|
||||||
|
formRef.value.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
shopMerchantPostAjax()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新聚合支付
|
||||||
|
const loading = ref(false)
|
||||||
|
async function shopMerchantPostAjax() {
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
const res = await shopMerchantPut({
|
||||||
|
shopId: route.query.shopId,
|
||||||
|
polyMerchantDTO: form.value
|
||||||
|
})
|
||||||
|
ElNotification({
|
||||||
|
title: '注意',
|
||||||
|
message: '更新成功',
|
||||||
|
type: 'success'
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.log('shopMerchantPostAjax=', error);
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
340
src/views/shop/list/components/payStatusCard.vue
Normal file
340
src/views/shop/list/components/payStatusCard.vue
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
<template>
|
||||||
|
<div class="row mt14">
|
||||||
|
<el-form label-width="150" label-position="left" v-loading="loading">
|
||||||
|
<el-form-item label="信息来源" v-if="isHeadShop != 1">
|
||||||
|
<el-radio-group :model-value="typeValue" @change="typeValueChange">
|
||||||
|
<el-radio label="进件信息" :value="route.query.shopId"></el-radio>
|
||||||
|
<el-radio label="复用主店信息" :value="route.query.mainId" v-if="mainInfo && mainInfo.shopId"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<template v-if="!form.shopId">
|
||||||
|
<el-form-item label-width="0">
|
||||||
|
<el-text>您还未申请进件</el-text>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label-width="0">
|
||||||
|
<el-button type="primary" @click="toApplyment">去申请</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<el-form-item label="商户号">
|
||||||
|
<el-text>{{ form.merchantCode }}</el-text>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="商户类型">
|
||||||
|
<el-text>{{ userTypeListFilter(form.userType).label }}</el-text>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="支付宝进件状态">
|
||||||
|
<div class="column">
|
||||||
|
<div>
|
||||||
|
<el-text :type="statusListFilter(form.alipayStatus).type">
|
||||||
|
{{ statusListFilter(form.alipayStatus).label }}
|
||||||
|
</el-text>
|
||||||
|
</div>
|
||||||
|
<div class="center" v-if="form.alipayStatus == 'SIGN'">
|
||||||
|
<el-text>待签约</el-text>
|
||||||
|
<el-link type="primary" @click="singCodeDialogRef?.show(form.alipaySignUrl, 1)">查看签约码</el-link>
|
||||||
|
</div>
|
||||||
|
<div class="error_text" v-if="form.alipayStatus == 'REJECTED'">
|
||||||
|
失败原因:{{ form.alipayErrorMsg }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="微信进件状态">
|
||||||
|
<div class="column">
|
||||||
|
<div>
|
||||||
|
<el-text :type="statusListFilter(form.wechatStatus).type">
|
||||||
|
{{ statusListFilter(form.wechatStatus).label }}
|
||||||
|
</el-text>
|
||||||
|
</div>
|
||||||
|
<div class="center" v-if="form.wechatStatus == 'SIGN'">
|
||||||
|
<el-text>待签约</el-text>
|
||||||
|
<el-link type="primary" @click="singCodeDialogRef?.show(form.wechatSignUrl, 2)">查看签约码</el-link>
|
||||||
|
</div>
|
||||||
|
<div class="error_text" v-if="form.wechatStatus == 'REJECTED'">
|
||||||
|
失败原因:{{ form.wechatErrorMsg }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="最后提交时间">
|
||||||
|
<el-text>{{ form.updateTime }}</el-text>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="创建时间">
|
||||||
|
<el-text>{{ form.createTime }}</el-text>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item v-if="typeValue == shopId">
|
||||||
|
<el-button link type="primary"
|
||||||
|
v-if="form.wechatStatus == 'INIT' || form.wechatStatus == 'AUDIT' || form.wechatStatus == 'SIGN' || form.alipayStatus == 'INIT' || form.alipayStatus == 'AUDIT' || form.alipayStatus == 'SIGN'"
|
||||||
|
@click="checkStatusHandle()">查询</el-button>
|
||||||
|
<el-button type="primary" @click="toDetail('check')">查看详情</el-button>
|
||||||
|
<el-button type="primary" @click="toDetail('editor')"
|
||||||
|
v-if="form.alipayStatus == 'REJECTED' || form.wechatStatus == 'REJECTED'">修改</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</el-form>
|
||||||
|
<singCodeDialog ref="singCodeDialogRef" />
|
||||||
|
<!-- 分店复用主店信息弹窗 -->
|
||||||
|
<el-dialog title="注意" width="400px" top="40vh" v-model="mainDialogVisable">
|
||||||
|
<span>是否复用主店?</span>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="toApplymentRouter">自己申请</el-button>
|
||||||
|
<el-button type="primary" @click="shopMerchantPutAjax" :loading="mainDialogVisableLoading">复用主店信息</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import { shopMerchantGet, getMainMerchant, shopMerchantPut, entryManagerDetail, queryEntry } from '@/api/common'
|
||||||
|
import singCodeDialog from '@/views/applyments/components/singCodeDialog.vue';
|
||||||
|
|
||||||
|
const singCodeDialogRef = ref(null)
|
||||||
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
const shopId = ref(route.query.shopId)
|
||||||
|
const userTypeList = ref([
|
||||||
|
{
|
||||||
|
value: '0',
|
||||||
|
label: '个体商户'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: '1',
|
||||||
|
label: '企业商户'
|
||||||
|
},
|
||||||
|
])
|
||||||
|
function userTypeListFilter(userType) {
|
||||||
|
let obj = userTypeList.value.find(item => item.value == userType)
|
||||||
|
if (obj) {
|
||||||
|
return obj
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
label: userType,
|
||||||
|
value: userType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const statusList = ref([
|
||||||
|
{
|
||||||
|
value: 'WAIT',
|
||||||
|
label: '待提交',
|
||||||
|
type: 'info'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'INIT',
|
||||||
|
label: '待处理',
|
||||||
|
type: 'info'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'AUDIT',
|
||||||
|
label: '待审核',
|
||||||
|
type: 'warning'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'SIGN',
|
||||||
|
label: '待签约',
|
||||||
|
type: 'primary'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'FINISH',
|
||||||
|
label: '已完成',
|
||||||
|
type: 'success'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'REJECTED',
|
||||||
|
label: '失败',
|
||||||
|
type: 'danger'
|
||||||
|
},
|
||||||
|
])
|
||||||
|
function statusListFilter(status) {
|
||||||
|
let obj = statusList.value.find(item => item.value == status)
|
||||||
|
if (obj) {
|
||||||
|
return obj
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
label: status,
|
||||||
|
value: status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const loading = ref(false)
|
||||||
|
const form = ref({})
|
||||||
|
|
||||||
|
|
||||||
|
// 查询状态
|
||||||
|
async function checkStatusHandle() {
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
const businessLicenceInfo = form.value.businessLicenceInfo
|
||||||
|
await queryEntry({
|
||||||
|
shopId: form.value.shopId,
|
||||||
|
licenceNo: businessLicenceInfo.licenceNo
|
||||||
|
})
|
||||||
|
updateData()
|
||||||
|
} catch (error) {
|
||||||
|
loading.value = false
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取主店进件信息
|
||||||
|
const mainInfo = ref({})
|
||||||
|
async function headShopApplmentInfo() {
|
||||||
|
try {
|
||||||
|
if (route.query.mainId) {
|
||||||
|
const res = await getMainMerchant({
|
||||||
|
shopId: route.query.mainId
|
||||||
|
})
|
||||||
|
mainInfo.value = res
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转进件逻辑处理
|
||||||
|
const mainDialogVisable = ref(false)
|
||||||
|
const mainDialogVisableLoading = ref(false)
|
||||||
|
const isHeadShop = ref(route.query.isHeadShop)
|
||||||
|
async function toApplyment() {
|
||||||
|
let shopType = route.query.shopType
|
||||||
|
if (shopType == 'chain' || shopType == 'join') {
|
||||||
|
if (isHeadShop == 1) {
|
||||||
|
toApplymentRouter()
|
||||||
|
} else {
|
||||||
|
// 分店弹窗选择
|
||||||
|
await headShopApplmentInfo()
|
||||||
|
if (mainInfo.value && mainInfo.value.shopId) {
|
||||||
|
mainDialogVisable.value = true
|
||||||
|
} else {
|
||||||
|
toApplymentRouter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toApplymentRouter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转进件
|
||||||
|
function toApplymentRouter() {
|
||||||
|
router.push({ name: 'applyment_in', query: { shopId: shopId.value } });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复用主店的进件信息
|
||||||
|
async function shopMerchantPutAjax() {
|
||||||
|
try {
|
||||||
|
mainDialogVisableLoading.value = true
|
||||||
|
await shopMerchantPut({
|
||||||
|
shopId: shopId.value,
|
||||||
|
relatedId: mainInfo.value.shopId,
|
||||||
|
nativeMerchantDTO: {
|
||||||
|
wechatMerchantId: mainInfo.value.wechatMerchantId,
|
||||||
|
alipayMerchantId: mainInfo.value.alipayMerchantId,
|
||||||
|
alipayAuthInfo: mainInfo.value.alipayAuthInfo
|
||||||
|
}
|
||||||
|
})
|
||||||
|
ElNotification({
|
||||||
|
title: '注意',
|
||||||
|
message: '复用成功',
|
||||||
|
type: 'success'
|
||||||
|
})
|
||||||
|
mainDialogVisable.value = false
|
||||||
|
updateData()
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
mainDialogVisableLoading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 跳转编辑页面
|
||||||
|
function toDetail(type) {
|
||||||
|
const businessLicenceInfo = form.value.businessLicenceInfo
|
||||||
|
router.push({
|
||||||
|
name: 'applyment_in',
|
||||||
|
query: {
|
||||||
|
shopId: shopId.value,
|
||||||
|
licenceNo: businessLicenceInfo.licenceNo,
|
||||||
|
type: type
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换进件类型
|
||||||
|
const typeValue = ref('')
|
||||||
|
async function typeValueChange(e) {
|
||||||
|
await ElMessageBox.confirm('确定要切换进件类型吗?', '注意').then(async () => {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
await shopMerchantPut({
|
||||||
|
shopId: shopId.value,
|
||||||
|
relatedId: e,
|
||||||
|
})
|
||||||
|
typeValue.value = e
|
||||||
|
updateData()
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}).catch(() => { })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新进件数据
|
||||||
|
async function updateData() {
|
||||||
|
try {
|
||||||
|
loading.value = true
|
||||||
|
const res = await shopMerchantGet({
|
||||||
|
shopId: shopId.value
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res && res.shopDirectMerchant) {
|
||||||
|
form.value = res.shopDirectMerchant
|
||||||
|
typeValue.value = res.relatedId
|
||||||
|
} else {
|
||||||
|
typeValue.value = shopId.value
|
||||||
|
const applymentRes = await entryManagerDetail({ shopId: shopId.value })
|
||||||
|
if (applymentRes && applymentRes.shopId) {
|
||||||
|
form.value = applymentRes
|
||||||
|
} else {
|
||||||
|
form.value = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
updateData()
|
||||||
|
headShopApplmentInfo()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.row {
|
||||||
|
&.mt14 {
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
display: flex;
|
||||||
|
gap: 14px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error_text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -3,19 +3,50 @@
|
|||||||
<div class="head-container">
|
<div class="head-container">
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="3">
|
<el-col :span="3">
|
||||||
<el-input v-model="state.query.name" clearable placeholder="请输入店铺名称" style="width: 100%" class="filter-item"
|
<el-input
|
||||||
@keyup.enter="getTableData" />
|
v-model="state.query.name"
|
||||||
|
clearable
|
||||||
|
placeholder="请输入店铺名称"
|
||||||
|
style="width: 100%"
|
||||||
|
class="filter-item"
|
||||||
|
@keyup.enter="getTableData"
|
||||||
|
/>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="3">
|
<el-col :span="3">
|
||||||
<el-input v-model="state.query.account" clearable placeholder="请输入商户号" style="width: 100%" class="filter-item"
|
<el-input
|
||||||
@keyup.enter="getTableData" />
|
v-model="state.query.phone"
|
||||||
|
clearable
|
||||||
|
placeholder="请输入手机号"
|
||||||
|
style="width: 100%"
|
||||||
|
class="filter-item"
|
||||||
|
@keyup.enter="getTableData"
|
||||||
|
/>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="3">
|
<el-col :span="3">
|
||||||
<el-select v-model="state.query.status" placeholder="请选择店铺状态" style="width: 100%">
|
<el-select v-model="state.query.status" placeholder="请选择店铺状态" style="width: 100%">
|
||||||
<el-option v-for="item in state.status" :key="item.type" :label="item.label" :value="item.type" />
|
<el-option
|
||||||
|
v-for="item in state.status"
|
||||||
|
:key="item.type"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.type"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="3">
|
||||||
|
<el-select
|
||||||
|
v-model="state.query.profiles"
|
||||||
|
placeholder="请选择商户版本"
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in state.profiles"
|
||||||
|
:key="item.type"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.type"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="3">
|
||||||
<el-button type="primary" @click="getTableData">查询</el-button>
|
<el-button type="primary" @click="getTableData">查询</el-button>
|
||||||
<el-button @click="resetHandle">重置</el-button>
|
<el-button @click="resetHandle">重置</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -25,12 +56,14 @@
|
|||||||
<el-button type="primary" icon="plus" @click="addShopShow">添加店铺</el-button>
|
<el-button type="primary" icon="plus" @click="addShopShow">添加店铺</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="head-container">
|
<div class="head-container">
|
||||||
<el-table v-loading="state.tableData.loading" :data="state.tableData.list">
|
<el-table v-loading="state.tableData.loading" :data="state.tableData.list" stripe border>
|
||||||
<el-table-column label="店铺信息" width="200">
|
<el-table-column label="店铺信息" width="200">
|
||||||
<template v-slot="scope">
|
<template v-slot="scope">
|
||||||
<div class="shop_info">
|
<div class="shop_info">
|
||||||
<el-image :src="scope.row.logo"
|
<el-image
|
||||||
style="width: 50px; height: 50px; border-radius: 4px; background-color: #efefef">
|
:src="scope.row.logo"
|
||||||
|
style="width: 50px; height: 50px; border-radius: 4px; background-color: #efefef"
|
||||||
|
>
|
||||||
<template #error>
|
<template #error>
|
||||||
<div class="img_error">
|
<div class="img_error">
|
||||||
<i class="icon el-icon-document-delete" />
|
<i class="icon el-icon-document-delete" />
|
||||||
@@ -57,23 +90,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column label="手机号" prop="phone"></el-table-column>
|
||||||
<el-table-column prop="registerType" label="经营模式">
|
<el-table-column prop="registerType" label="经营模式">
|
||||||
<template v-slot="scope">
|
<template v-slot="scope">
|
||||||
<span v-if="scope.row.registerType == 'before'">快餐版</span>
|
<span v-if="scope.row.registerType == 'before'">快餐版</span>
|
||||||
<span v-if="scope.row.registerType == 'after'">餐饮版</span>
|
<span v-if="scope.row.registerType == 'after'">餐饮版</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="address" label="商户号" />
|
|
||||||
<el-table-column prop="status" label="店铺类型" align="center">
|
<el-table-column prop="status" label="店铺类型" align="center">
|
||||||
<template v-slot="scope">
|
<template v-slot="scope">
|
||||||
<div>
|
<div>
|
||||||
<span v-if="scope.row.shopType == 'only'">单店</span>
|
<span v-if="scope.row.shopType == 'only'">单店</span>
|
||||||
<span v-if="scope.row.shopType == 'chain'">连锁店</span>
|
<span v-if="scope.row.shopType == 'chain'">连锁店</span>
|
||||||
<span v-if="scope.row.shopType == 'join'">加盟店</span>
|
<span v-if="scope.row.shopType == 'join'">加盟店</span>
|
||||||
<div v-if="scope.row.shopType != 'only'&&scope.row.isHeadShop == 0">(主店:{{ scope.row.headShopName }})</div>
|
<div v-if="scope.row.shopType != 'only' && scope.row.isHeadShop == 0">
|
||||||
|
(主店:{{ scope.row.headShopName }})
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column prop="address" label="商户详细地址" />
|
||||||
<el-table-column prop="status" label="店铺状态">
|
<el-table-column prop="status" label="店铺状态">
|
||||||
<template v-slot="scope">
|
<template v-slot="scope">
|
||||||
<el-switch v-model="scope.row.status" :active-value="1" :inactive-value="0" disabled />
|
<el-switch v-model="scope.row.status" :active-value="1" :inactive-value="0" disabled />
|
||||||
@@ -111,9 +147,11 @@
|
|||||||
|
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item v-if="scope.row.isHeadShop == 1" :command="0">添加分店</el-dropdown-item>
|
<el-dropdown-item v-if="scope.row.isHeadShop == 1" :command="0">
|
||||||
|
添加分店
|
||||||
|
</el-dropdown-item>
|
||||||
<el-dropdown-item :command="{ row: scope.row, command: 1 }">
|
<el-dropdown-item :command="{ row: scope.row, command: 1 }">
|
||||||
三方配置
|
支付配置
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item :command="2">续费记录</el-dropdown-item>
|
<el-dropdown-item :command="2">续费记录</el-dropdown-item>
|
||||||
<el-dropdown-item :command="3">前往店铺</el-dropdown-item>
|
<el-dropdown-item :command="3">前往店铺</el-dropdown-item>
|
||||||
@@ -127,12 +165,17 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
<div class="head-container">
|
<div class="head-container">
|
||||||
<el-pagination v-model:current-page="state.tableData.page" v-model:page-size="state.tableData.size"
|
<el-pagination
|
||||||
:total="state.tableData.total" :page-sizes="[10, 20, 30, 50, 100]"
|
v-model:current-page="state.tableData.page"
|
||||||
layout="total, sizes , prev, pager ,next, jumper " @current-change="paginationChange" />
|
v-model:page-size="state.tableData.size"
|
||||||
|
:total="state.tableData.total"
|
||||||
|
:page-sizes="[10, 20, 30, 50, 100]"
|
||||||
|
layout="total, sizes , prev, pager ,next, jumper "
|
||||||
|
@current-change="paginationChange"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<addShop ref="refAddShop" @success="getTableData" />
|
<addShop ref="refAddShop" @success="getTableData" />
|
||||||
<detailModal ref="refDetailModal" />
|
<!-- <detailModal ref="refDetailModal" /> -->
|
||||||
<!-- 激活码 -->
|
<!-- 激活码 -->
|
||||||
<activateCode ref="refActivateCode" @success="getTableData" />
|
<activateCode ref="refActivateCode" @success="getTableData" />
|
||||||
</div>
|
</div>
|
||||||
@@ -145,6 +188,10 @@ import ShopApi from "@/api/account/shop";
|
|||||||
import { ElNotification, ElMessageBox } from "element-plus";
|
import { ElNotification, ElMessageBox } from "element-plus";
|
||||||
import addShop from "./components/addShop.vue";
|
import addShop from "./components/addShop.vue";
|
||||||
import detailModal from "./components/detailModal.vue";
|
import detailModal from "./components/detailModal.vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const refActivateCode = ref(null);
|
const refActivateCode = ref(null);
|
||||||
function activateCodeShow(row) {
|
function activateCodeShow(row) {
|
||||||
refActivateCode.value.open(row);
|
refActivateCode.value.open(row);
|
||||||
@@ -156,8 +203,9 @@ function addShopShow(row) {
|
|||||||
const state = reactive({
|
const state = reactive({
|
||||||
query: {
|
query: {
|
||||||
name: "",
|
name: "",
|
||||||
account: "",
|
phone: "",
|
||||||
status: "",
|
status: "",
|
||||||
|
profiles: "",
|
||||||
},
|
},
|
||||||
status: [
|
status: [
|
||||||
{
|
{
|
||||||
@@ -169,6 +217,16 @@ const state = reactive({
|
|||||||
label: "关闭",
|
label: "关闭",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
profiles: [
|
||||||
|
{
|
||||||
|
type: "probation",
|
||||||
|
label: "试用版",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "release",
|
||||||
|
label: "正式版",
|
||||||
|
},
|
||||||
|
],
|
||||||
tableData: {
|
tableData: {
|
||||||
list: [],
|
list: [],
|
||||||
page: 1,
|
page: 1,
|
||||||
@@ -186,12 +244,24 @@ function dropdownClick(e, row) {
|
|||||||
console.log(e);
|
console.log(e);
|
||||||
console.log(row);
|
console.log(row);
|
||||||
if (e == 0) {
|
if (e == 0) {
|
||||||
refAddShop.value.show({mainId:row.id,shopType:row.shopType,isHeadShop:0},'addBranch');
|
refAddShop.value.show({ mainId: row.id, shopType: row.shopType, isHeadShop: 0 }, "addBranch");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e.command == 1) {
|
if (e.command == 1) {
|
||||||
refDetailModal.value.show(e.row);
|
console.log("row===", row);
|
||||||
|
|
||||||
|
// refDetailModal.value.show(e.row);
|
||||||
|
router.push({
|
||||||
|
name: "pay_setting",
|
||||||
|
query: {
|
||||||
|
shopId: row.id,
|
||||||
|
shopType: row.shopType,
|
||||||
|
isHeadShop: row.isHeadShop,
|
||||||
|
mainId: row.mainId,
|
||||||
|
shopName: row.shopName,
|
||||||
|
},
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e == 5) {
|
if (e == 5) {
|
||||||
@@ -208,15 +278,16 @@ function dropdownClick(e, row) {
|
|||||||
});
|
});
|
||||||
getTableData();
|
getTableData();
|
||||||
})
|
})
|
||||||
.catch(() => { });
|
.catch(() => {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 重置查询
|
// 重置查询
|
||||||
function resetHandle() {
|
function resetHandle() {
|
||||||
state.query.name = "";
|
state.query.name = "";
|
||||||
state.query.account = "";
|
state.query.phone = "";
|
||||||
state.query.status = "";
|
state.query.status = "";
|
||||||
|
state.query.profiles = "";
|
||||||
getTableData();
|
getTableData();
|
||||||
}
|
}
|
||||||
// 分页回调
|
// 分页回调
|
||||||
@@ -232,8 +303,9 @@ async function getTableData() {
|
|||||||
page: state.tableData.page,
|
page: state.tableData.page,
|
||||||
size: state.tableData.size,
|
size: state.tableData.size,
|
||||||
shopName: state.query.name,
|
shopName: state.query.name,
|
||||||
account: state.query.account,
|
phone: state.query.phone,
|
||||||
status: state.query.status,
|
status: state.query.status,
|
||||||
|
profiles: state.query.profiles,
|
||||||
});
|
});
|
||||||
state.tableData.loading = false;
|
state.tableData.loading = false;
|
||||||
state.tableData.list = res.records;
|
state.tableData.list = res.records;
|
||||||
|
|||||||
149
src/views/shop/list/pay_setting.vue
Normal file
149
src/views/shop/list/pay_setting.vue
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
<!-- 支付配置页面 -->
|
||||||
|
<template>
|
||||||
|
<div class="gyq_container">
|
||||||
|
<div class="header_wrap">
|
||||||
|
<div class="left_btn" @click="router.back()">
|
||||||
|
<el-icon size="22" color="#333">
|
||||||
|
<Back />
|
||||||
|
</el-icon>
|
||||||
|
</div>
|
||||||
|
<div class="info">
|
||||||
|
<div class="t">{{ route.query.shopName }} | 支付配置</div>
|
||||||
|
<div class="intro">管理您的支付渠道和进件信息</div>
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
<el-text size="large">当前模式:</el-text>
|
||||||
|
<el-radio-group size="large" :model-value="payModel" @change="handleRadioChange">
|
||||||
|
<el-radio :label="item.label" :value="item.value" v-for="item in tabList" :key="item.value"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="gyq_content row mt14">
|
||||||
|
<tabHeader v-model="tabActiveIndex" :list="tabList" />
|
||||||
|
<payStatusCard name="payStatusCard" key="payStatusCard" ref="payStatusCardRef" v-if="tabActiveIndex == 0" />
|
||||||
|
<detailModal name="detailModal" key="detailModal" ref="detailModalRef" v-model="detail"
|
||||||
|
v-if="tabActiveIndex == 1" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, watch, onMounted } from 'vue'
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
import detailModal from './components/detailModal.vue';
|
||||||
|
import payStatusCard from './components/payStatusCard.vue';
|
||||||
|
import { shopMerchantGet, shopMerchantPut } from '@/api/common'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
const payModel = ref('')
|
||||||
|
const tabActiveIndex = ref(0)
|
||||||
|
const tabList = ref([
|
||||||
|
{
|
||||||
|
label: '支付进件',
|
||||||
|
value: 'native'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '聚合支付',
|
||||||
|
value: 'poly'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
// 二次确认支付模式 更换支付模式
|
||||||
|
async function handleRadioChange(value) {
|
||||||
|
await ElMessageBox.confirm('确定要选择该模式吗?', '注意').then(async () => {
|
||||||
|
try {
|
||||||
|
await shopMerchantPut({
|
||||||
|
shopId: route.query.shopId,
|
||||||
|
channel: value
|
||||||
|
})
|
||||||
|
payModel.value = value
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}).catch(() => { })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 与子组件的form绑定
|
||||||
|
const detail = ref({})
|
||||||
|
async function shopMerchantGetAjax() {
|
||||||
|
try {
|
||||||
|
const res = await shopMerchantGet({ shopId: route.query.shopId })
|
||||||
|
console.log('shopMerchantGetAjax===', res);
|
||||||
|
if (res && res.shopId) {
|
||||||
|
payModel.value = res.channel
|
||||||
|
|
||||||
|
if (res && res.polyMerchantDTO) {
|
||||||
|
detail.value = res.polyMerchantDTO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
shopMerchantGetAjax()
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.gyq_container {
|
||||||
|
padding: 14px;
|
||||||
|
|
||||||
|
.gyq_content {
|
||||||
|
padding: 14px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
&.mt14 {
|
||||||
|
margin-top: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.center {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header_wrap {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-right: 14px;
|
||||||
|
|
||||||
|
.left_btn {
|
||||||
|
height: 73px;
|
||||||
|
padding: 14px 24px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
flex: 1;
|
||||||
|
padding: 14px 14px 14px 0;
|
||||||
|
|
||||||
|
.t {
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.intro {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<div class="head-container">
|
<div class="head-container">
|
||||||
<el-form :model="query" inline>
|
<el-form :model="query" inline>
|
||||||
<el-form-item label="">
|
<el-form-item label="">
|
||||||
<el-input v-model="query.name" placeholder="请输入昵称或手机号"></el-input>
|
<el-input v-model="query.key" placeholder="请输入昵称或手机号"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
@@ -22,7 +22,10 @@
|
|||||||
<el-table-column label="用户" prop="headImg" width="200px">
|
<el-table-column label="用户" prop="headImg" width="200px">
|
||||||
<template v-slot="scope">
|
<template v-slot="scope">
|
||||||
<div class="user_info">
|
<div class="user_info">
|
||||||
<el-image :src="scope.row.headImg" style="width: 40px; height: 40px; flex-shrink: 0">
|
<el-image
|
||||||
|
:src="scope.row.headImg"
|
||||||
|
style="width: 40px; height: 40px; flex-shrink: 0"
|
||||||
|
>
|
||||||
<template #error>
|
<template #error>
|
||||||
<div class="image-slot">
|
<div class="image-slot">
|
||||||
<i class="el-icon-user"></i>
|
<i class="el-icon-user"></i>
|
||||||
@@ -30,7 +33,14 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-image>
|
</el-image>
|
||||||
<span class="name">{{ scope.row.nickName }}</span>
|
<span class="name">{{ scope.row.nickName }}</span>
|
||||||
<el-tag disable-transitions type="primary" style="margin-left: 10px;" v-if="scope.row.new">新</el-tag>
|
<el-tag
|
||||||
|
disable-transitions
|
||||||
|
type="primary"
|
||||||
|
style="margin-left: 10px"
|
||||||
|
v-if="scope.row.new"
|
||||||
|
>
|
||||||
|
新
|
||||||
|
</el-tag>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -38,7 +48,9 @@
|
|||||||
|
|
||||||
<el-table-column label="会员" prop="isVip" width="140">
|
<el-table-column label="会员" prop="isVip" width="140">
|
||||||
<template v-slot="scope">
|
<template v-slot="scope">
|
||||||
<el-tag type="warning" v-if="scope.row.isVip">会员等级{{ scope.row.memberLevelName }}</el-tag>
|
<el-tag type="warning" v-if="scope.row.isVip">
|
||||||
|
会员等级{{ scope.row.memberLevelName }}
|
||||||
|
</el-tag>
|
||||||
<span v-else>否</span>
|
<span v-else>否</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -47,9 +59,9 @@
|
|||||||
{{ multiplyAndFormat(scope.row.amount || 0) }}
|
{{ multiplyAndFormat(scope.row.amount || 0) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="积分" prop="accountPoints">
|
<el-table-column label="积分" prop="pointBalance">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ scope.row.accountPoints || 0 }}
|
{{ scope.row.pointBalance || 0 }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="90" fixed="right">
|
<el-table-column label="操作" width="90" fixed="right">
|
||||||
@@ -60,9 +72,14 @@
|
|||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
<div class="head-container">
|
<div class="head-container">
|
||||||
<el-pagination :total="tableData.total" :current-page="tableData.page" :page-size="tableData.size"
|
<el-pagination
|
||||||
@size-change="sizeChange" @current-change="paginationChange"
|
:total="tableData.total"
|
||||||
layout="total, sizes, prev, pager, next, jumper"></el-pagination>
|
:current-page="tableData.page"
|
||||||
|
:page-size="tableData.size"
|
||||||
|
@size-change="sizeChange"
|
||||||
|
@current-change="paginationChange"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
></el-pagination>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -71,13 +88,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import shopUserApi from "@/api/account/shopUser";
|
import shopUserApi from "@/api/account/shopUser";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { multiplyAndFormat } from '@/utils'
|
import { multiplyAndFormat } from "@/utils";
|
||||||
let cacheData = {};
|
let cacheData = {};
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
show: false,
|
show: false,
|
||||||
query: {
|
query: {
|
||||||
name: "",
|
key: "",
|
||||||
// isVip: 1,
|
// isVip: 1,
|
||||||
},
|
},
|
||||||
tableData: {
|
tableData: {
|
||||||
|
|||||||
@@ -220,6 +220,25 @@
|
|||||||
<popup-coupon ref="refCoupon" :user="carts.vipUser" @confirm="refCouponConfirm"></popup-coupon>
|
<popup-coupon ref="refCoupon" :user="carts.vipUser" @confirm="refCouponConfirm"></popup-coupon>
|
||||||
<!-- 挂账 -->
|
<!-- 挂账 -->
|
||||||
<chooseGuaZahng ref="refGuaZhang" :payMoney="currentpayMoney" @confirm="refGuaZhangConfirm"></chooseGuaZahng>
|
<chooseGuaZahng ref="refGuaZhang" :payMoney="currentpayMoney" @confirm="refGuaZhangConfirm"></chooseGuaZahng>
|
||||||
|
<!-- 扫码等待用户支付转台查询 -->
|
||||||
|
<el-dialog v-model="showCheckPayStauts" width="400" title="订单支付状态查询中..." :close-on-click-modal="false"
|
||||||
|
:show-close="false">
|
||||||
|
<div class="pay_status_content">
|
||||||
|
<div class="loading" v-loading="checkPayStautsLoading" element-loading-text="用户支付中..."></div>
|
||||||
|
<div class="btn">
|
||||||
|
<el-button style="width: 100%" :disabled="!closeState" type="primary" @click="resetScanCode">
|
||||||
|
<span v-if="!closeState">{{ closeStateTime }}秒后可重新扫码</span>
|
||||||
|
<span v-else>重新扫码</span>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<div class="btn">
|
||||||
|
<el-button style="width: 100%" :disabled="!closeState" @click="closeScanCode">
|
||||||
|
<span v-if="!closeState">{{ closeStateTime }}秒后可关闭</span>
|
||||||
|
<span v-else>关闭</span>
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -243,6 +262,7 @@ import discount from "./discount.vue";
|
|||||||
import { ElLoading } from "element-plus";
|
import { ElLoading } from "element-plus";
|
||||||
import { ElMessage, ElMessageBox } from "element-plus";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
import { BigNumber } from "bignumber.js";
|
import { BigNumber } from "bignumber.js";
|
||||||
|
import { onUnmounted } from 'vue'
|
||||||
|
|
||||||
// 配置BigNumber精度
|
// 配置BigNumber精度
|
||||||
BigNumber.set({
|
BigNumber.set({
|
||||||
@@ -439,11 +459,17 @@ async function pointsInit() {
|
|||||||
|
|
||||||
// 保险取值
|
// 保险取值
|
||||||
const eq = pointsConfig?.equivalentPoints || 0;
|
const eq = pointsConfig?.equivalentPoints || 0;
|
||||||
const maxRatio = pointsConfig?.maxDeductionRatio || 0;
|
const rawMaxRatio = pointsConfig?.maxDeductionRatio || 0;
|
||||||
|
// 兼容后端返回的百分比或小数两种形式:如果大于1,则视为百分比(如100表示100%),需除以100
|
||||||
|
const maxRatio = rawMaxRatio > 1 ? rawMaxRatio / 100 : rawMaxRatio;
|
||||||
const minPay = pointsConfig?.minPaymentAmount || 0;
|
const minPay = pointsConfig?.minPaymentAmount || 0;
|
||||||
|
|
||||||
// 计算当前订单可抵扣金额上限(元)
|
// 计算当前订单可抵扣金额上限(元)
|
||||||
|
// 使用“抵扣前实付金额”作为门槛判断(即把当前已应用的积分抵扣金额加回),
|
||||||
|
// 避免在已经抵扣导致 finalPay 变小后错误地判定为不可用。
|
||||||
let finalPay = Number(carts.orderCostSummary.finalPayAmount) || 0;
|
let finalPay = Number(carts.orderCostSummary.finalPayAmount) || 0;
|
||||||
|
const currentPointDeduction = Number(carts.orderCostSummary.pointDeductionAmount) || 0;
|
||||||
|
const basePay = finalPay + currentPointDeduction;
|
||||||
|
|
||||||
const res = {
|
const res = {
|
||||||
usable: true,
|
usable: true,
|
||||||
@@ -455,8 +481,9 @@ async function pointsInit() {
|
|||||||
unusableReason: "",
|
unusableReason: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
// 如果订单实付低于最小使用门槛,则不可用
|
// 如果订单实付低于最小使用门槛,则不可用(门槛仅作为启用条件)
|
||||||
if (finalPay <= 0 || (minPay > 0 && finalPay < minPay)) {
|
// 这里使用 basePay(抵扣前实付)进行判断,确保已填写积分后不会回退为不可用
|
||||||
|
if (basePay <= 0 || (minPay > 0 && basePay < minPay)) {
|
||||||
res.usable = false;
|
res.usable = false;
|
||||||
res.unusableReason = `订单实付金额低于 ${minPay} 元,无法使用积分抵扣`;
|
res.unusableReason = `订单实付金额低于 ${minPay} 元,无法使用积分抵扣`;
|
||||||
} else if (eq <= 0) {
|
} else if (eq <= 0) {
|
||||||
@@ -464,23 +491,22 @@ async function pointsInit() {
|
|||||||
res.unusableReason = `积分换算比例配置错误,无法使用积分抵扣`;
|
res.unusableReason = `积分换算比例配置错误,无法使用积分抵扣`;
|
||||||
} else {
|
} else {
|
||||||
// 计算基于比例限制的最大抵扣金额(元)
|
// 计算基于比例限制的最大抵扣金额(元)
|
||||||
let maxByRatio = finalPay * maxRatio;
|
// 注意:此处不再减少 minPaymentAmount,minPaymentAmount 仅用作是否可用的门槛;
|
||||||
// 保证抵扣后剩余金额 >= minPaymentAmount
|
// 真正的最大抵扣由 maxRatio(抵扣比例)与用户积分数量共同决定。
|
||||||
if (minPay > 0) {
|
// 计算基于比例限制的最大抵扣金额(元),基于抵扣前实付金额
|
||||||
const allowed = finalPay - minPay;
|
let maxByRatio = basePay * maxRatio;
|
||||||
if (allowed <= 0) {
|
|
||||||
res.usable = false;
|
|
||||||
res.unusableReason = `抵扣后实付金额必须大于等于 ${minPay} 元,当前不可使用积分`;
|
|
||||||
} else {
|
|
||||||
maxByRatio = Math.min(maxByRatio, allowed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.usable) {
|
if (res.usable) {
|
||||||
// 可用积分上限(向下取整为 eq 的倍数)
|
// 可用积分上限(按等价积分步长对齐到 eq 的倍数)
|
||||||
const maxByMoney = Math.floor(maxByRatio * eq);
|
const maxByMoney = Math.floor(maxByRatio * eq);
|
||||||
const userPoints = carts.vipUser.pointBalance || 0;
|
const userPoints = carts.vipUser.pointBalance || 0;
|
||||||
res.maxUsablePoints = Math.min(userPoints, maxByMoney);
|
let computedMax = Math.min(userPoints, maxByMoney);
|
||||||
|
// 对齐到等价积分步长,保证输入步长生效
|
||||||
|
if (eq > 0) {
|
||||||
|
computedMax = Math.floor(computedMax / eq) * eq;
|
||||||
|
}
|
||||||
|
res.maxUsablePoints = computedMax;
|
||||||
|
console.debug("pointsInit debug:", { finalPay: finalPay, basePay: basePay, eq, rawMaxRatio, maxRatio, maxByMoney, userPoints, computedMax });
|
||||||
// 最小抵扣积分为配置值或等于换算比
|
// 最小抵扣积分为配置值或等于换算比
|
||||||
res.minDeductionPoints = pointsConfig?.minDeductionPoints || eq;
|
res.minDeductionPoints = pointsConfig?.minDeductionPoints || eq;
|
||||||
if (res.maxUsablePoints < res.minDeductionPoints) {
|
if (res.maxUsablePoints < res.minDeductionPoints) {
|
||||||
@@ -498,8 +524,20 @@ async function pointsInit() {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果可用则默认填充可用最大值,否则清零
|
// 如果可用则默认填充可用最大值(对齐步长),否则清零
|
||||||
usePointsNumber.value = res.usable ? res.maxUsablePoints : 0;
|
if (res.usable) {
|
||||||
|
// 计算默认填充值:基于抵扣前实付的比例上限与等价比计算需要的积分数
|
||||||
|
const defaultMaxByMoney = Math.floor(basePay * res.maxDeductionRatio * res.equivalentPoints);
|
||||||
|
let defaultPts = Math.min(res.maxUsablePoints || 0, defaultMaxByMoney || 0);
|
||||||
|
if (res.equivalentPoints > 0) {
|
||||||
|
defaultPts = Math.floor(defaultPts / res.equivalentPoints) * res.equivalentPoints;
|
||||||
|
}
|
||||||
|
// 最终确保不超过用户积分
|
||||||
|
const userPts = carts.vipUser.pointBalance || 0;
|
||||||
|
usePointsNumber.value = Math.min(defaultPts, userPts);
|
||||||
|
} else {
|
||||||
|
usePointsNumber.value = 0;
|
||||||
|
}
|
||||||
if (!res.usable) score.sel = -1;
|
if (!res.usable) score.sel = -1;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@@ -532,17 +570,15 @@ function pointsToMoney(val) {
|
|||||||
// 再次校验不超过允许的最大抵扣金额(基于比例或门槛)
|
// 再次校验不超过允许的最大抵扣金额(基于比例或门槛)
|
||||||
let finalPay = Number(carts.orderCostSummary.finalPayAmount) || 0;
|
let finalPay = Number(carts.orderCostSummary.finalPayAmount) || 0;
|
||||||
let maxByRatio = finalPay * cfg.maxDeductionRatio;
|
let maxByRatio = finalPay * cfg.maxDeductionRatio;
|
||||||
if (cfg.minPaymentAmount > 0) {
|
// 对于单笔抵扣:若订单实付低于配置的最小门槛,则不可使用(作为启用条件)
|
||||||
const allowed = finalPay - cfg.minPaymentAmount;
|
if (cfg.minPaymentAmount > 0 && finalPay < cfg.minPaymentAmount) {
|
||||||
if (allowed <= 0) {
|
usePointsNumber.value = 0;
|
||||||
usePointsNumber.value = 0;
|
carts.orderCostSummary.pointUsed = 0;
|
||||||
carts.orderCostSummary.pointUsed = 0;
|
carts.orderCostSummary.pointDeductionAmount = 0;
|
||||||
carts.orderCostSummary.pointDeductionAmount = 0;
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
maxByRatio = Math.min(maxByRatio, allowed);
|
|
||||||
}
|
}
|
||||||
const maxAllowedMoney = new BigNumber(maxByRatio).decimalPlaces(2, BigNumber.ROUND_DOWN).toNumber();
|
const maxAllowedMoney = new BigNumber(maxByRatio).decimalPlaces(2, BigNumber.ROUND_DOWN).toNumber();
|
||||||
|
console.debug("pointsToMoney debug:", { finalPay, cfg, pts, money, maxByRatio, maxAllowedMoney });
|
||||||
if (money > maxAllowedMoney) {
|
if (money > maxAllowedMoney) {
|
||||||
// 调整积分到允许的最大金额对应的积分
|
// 调整积分到允许的最大金额对应的积分
|
||||||
const allowedPts = Math.floor(maxAllowedMoney * cfg.equivalentPoints);
|
const allowedPts = Math.floor(maxAllowedMoney * cfg.equivalentPoints);
|
||||||
@@ -735,7 +771,12 @@ async function payOrder(payType, isScan, guazhangren) {
|
|||||||
}
|
}
|
||||||
carts.clear();
|
carts.clear();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log('payOrder===', error);
|
||||||
|
// 启动状态查询
|
||||||
|
if (error.code == 211) {
|
||||||
|
showCheckPayStauts.value = true
|
||||||
|
autoCheckOrder()
|
||||||
|
}
|
||||||
clearTimeout(payTimer);
|
clearTimeout(payTimer);
|
||||||
loading.close();
|
loading.close();
|
||||||
}
|
}
|
||||||
@@ -746,6 +787,102 @@ async function payOrder(payType, isScan, guazhangren) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clearAutoCheckOrder() {
|
||||||
|
clearInterval(timer.value)
|
||||||
|
timer.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭查询
|
||||||
|
function closeScanCode() {
|
||||||
|
showCheckPayStauts.value = false;
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新扫码
|
||||||
|
function resetScanCode() {
|
||||||
|
reset()
|
||||||
|
showCheckPayStauts.value = false;
|
||||||
|
clearInterval(timer.value)
|
||||||
|
timer.value = null
|
||||||
|
|
||||||
|
clearInterval(closeStateTimer.value)
|
||||||
|
closeStateTimer.value = null
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
refScanPay.value.open(returnPayParams(), "scanCode")
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeState = ref(false)
|
||||||
|
const closeStateTime = ref(5);
|
||||||
|
const closeStateTimer = ref(null)
|
||||||
|
|
||||||
|
function closeStateTimerFuc() {
|
||||||
|
closeStateTimer.value = setInterval(() => {
|
||||||
|
closeStateTime.value--
|
||||||
|
if (closeStateTime.value <= 0) {
|
||||||
|
clearInterval(closeStateTimer.value)
|
||||||
|
closeStateTimer.value = null
|
||||||
|
closeState.value = true
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动查询订单状态
|
||||||
|
const timer = ref(null)
|
||||||
|
function autoCheckOrder() {
|
||||||
|
closeStateTimerFuc()
|
||||||
|
timer.value = setInterval(() => {
|
||||||
|
// 开始锁单
|
||||||
|
// goodsStore.isOrderLock({
|
||||||
|
// table_code: table_code.value
|
||||||
|
// }, 'pay_lock')
|
||||||
|
checkPayStauts(false)
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset() {
|
||||||
|
checkPayStautsLoading.value = true;
|
||||||
|
closeState.value = false
|
||||||
|
closeStateTime.value = 5
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询订单支付状态
|
||||||
|
const showCheckPayStauts = ref(false)
|
||||||
|
const checkPayStautsLoading = ref(true)
|
||||||
|
async function checkPayStauts(tips = true) {
|
||||||
|
try {
|
||||||
|
// 扫码下单
|
||||||
|
const res = await payApi.queryOrderStatus({ orderId: props.orderInfo.id });
|
||||||
|
if (res == "done") {
|
||||||
|
// 支付成功,解锁订单
|
||||||
|
// await goodsStore.isOrderLock({
|
||||||
|
// table_code: table_code.value
|
||||||
|
// }, 'pay_unlock')
|
||||||
|
|
||||||
|
// userPayWait.value = false
|
||||||
|
checkPayStautsLoading.value = false;
|
||||||
|
// scanCode.value = "";
|
||||||
|
showCheckPayStauts.value = false;
|
||||||
|
clearAutoCheckOrder()
|
||||||
|
paysuccess();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (res == "unpaid") {
|
||||||
|
if (tips) {
|
||||||
|
ElMessage.warning("用户支付中...");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
clearAutoCheckOrder()
|
||||||
|
ElMessage.warning(res.msg || '');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function paysuccess() {
|
function paysuccess() {
|
||||||
clearTimeout(payTimer);
|
clearTimeout(payTimer);
|
||||||
ElMessage.success("支付成功");
|
ElMessage.success("支付成功");
|
||||||
@@ -806,6 +943,10 @@ watch(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearAutoCheckOrder()
|
||||||
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
carts.payParamsInit();
|
carts.payParamsInit();
|
||||||
getPaytype();
|
getPaytype();
|
||||||
@@ -858,9 +999,13 @@ defineExpose({
|
|||||||
.order-info {
|
.order-info {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
||||||
.title {}
|
.title {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
.value {}
|
.value {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
.price {
|
.price {
|
||||||
color: #fa5555;
|
color: #fa5555;
|
||||||
@@ -879,4 +1024,30 @@ defineExpose({
|
|||||||
color: #666;
|
color: #666;
|
||||||
padding: 8px 10px 8px 20px;
|
padding: 8px 10px 8px 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pay_status_content {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0 var(--el-font-size-base);
|
||||||
|
height: 400px;
|
||||||
|
padding-bottom: 100px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
--el-loading-spinner-size: 100px;
|
||||||
|
|
||||||
|
:deep(.el-loading-text) {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
width: 200px;
|
||||||
|
padding-top: var(--el-font-size-base);
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -2,12 +2,8 @@
|
|||||||
<el-dialog width="400px" :title="title" v-model="show" @close="reset">
|
<el-dialog width="400px" :title="title" v-model="show" @close="reset">
|
||||||
<div class="u-p-15">
|
<div class="u-p-15">
|
||||||
<div v-if="openSwitch" class="u-m-b-20">
|
<div v-if="openSwitch" class="u-m-b-20">
|
||||||
<el-button
|
<el-button @click="changeKey('paysSel', index)" v-for="(item, index) in pays" :key="index"
|
||||||
@click="changeKey('paysSel', index)"
|
:type="paysSel == index ? 'primary' : ''">
|
||||||
v-for="(item, index) in pays"
|
|
||||||
:key="index"
|
|
||||||
:type="paysSel == index ? 'primary' : ''"
|
|
||||||
>
|
|
||||||
{{ item.text }}
|
{{ item.text }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -21,13 +17,8 @@
|
|||||||
<el-input :value="form.money" disabled></el-input>
|
<el-input :value="form.money" disabled></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="付款码">
|
<el-form-item label="付款码">
|
||||||
<el-input
|
<el-input v-model="form.code" @change="inputChange" autofocus placeholder="请扫码或者输入付款码"
|
||||||
v-model="form.code"
|
ref="refInputCode"></el-input>
|
||||||
@change="codeInputChange"
|
|
||||||
autofocus
|
|
||||||
placeholder="请扫码或者输入付款码"
|
|
||||||
ref="refInputCode"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div class="u-flex u-row-center u-m-t-50">
|
<div class="u-flex u-row-center u-m-t-50">
|
||||||
<el-button @click="close">取消</el-button>
|
<el-button @click="close">取消</el-button>
|
||||||
@@ -46,7 +37,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="color-333 u-font-20 u-m-t-20">{{ form.money }}元</div>
|
<div class="color-333 u-font-20 u-m-t-20">{{ form.money }}元</div>
|
||||||
<div class="color-aaa u-font-12 u-m-t-10">
|
<div class="color-aaa u-font-12 u-m-t-10">
|
||||||
<el-icon class="loading-ani"><Loading /></el-icon>
|
<el-icon class="loading-ani">
|
||||||
|
<Loading />
|
||||||
|
</el-icon>
|
||||||
<span>等待用户支付</span>
|
<span>等待用户支付</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,7 +48,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
import _ from 'lodash'
|
||||||
import QRCode from "qrcode";
|
import QRCode from "qrcode";
|
||||||
import orderApi from "@/api/order/order";
|
import orderApi from "@/api/order/order";
|
||||||
import payApi from "@/api/order/pay";
|
import payApi from "@/api/order/pay";
|
||||||
@@ -90,10 +84,10 @@ export default {
|
|||||||
"https://zhyx.eingdong.com/qrcode/api.php?url=https%3A%2F%2Fzhyx.eingdong.com%2Fcopyright%2F%23%2Fpay%3Fid%3D139451580",
|
"https://zhyx.eingdong.com/qrcode/api.php?url=https%3A%2F%2Fzhyx.eingdong.com%2Fcopyright%2F%23%2Fpay%3Fid%3D139451580",
|
||||||
pays: [
|
pays: [
|
||||||
{
|
{
|
||||||
text: "主扫",
|
text: "扫码收款",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "被扫",
|
text: "二维码收款",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
number: "0",
|
number: "0",
|
||||||
@@ -128,6 +122,9 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
inputChange: _.debounce(function (e) {
|
||||||
|
this.confirm();
|
||||||
|
}, 100),
|
||||||
to2(n) {
|
to2(n) {
|
||||||
return n.toFixed(2);
|
return n.toFixed(2);
|
||||||
},
|
},
|
||||||
@@ -175,7 +172,6 @@ export default {
|
|||||||
changeKey(key, val) {
|
changeKey(key, val) {
|
||||||
this[key] = val;
|
this[key] = val;
|
||||||
},
|
},
|
||||||
|
|
||||||
confirm() {
|
confirm() {
|
||||||
if (!this.form.code) {
|
if (!this.form.code) {
|
||||||
return ElMessage.error("请输入或扫付款码");
|
return ElMessage.error("请输入或扫付款码");
|
||||||
@@ -240,13 +236,14 @@ export default {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.codeImg {
|
.codeImg {
|
||||||
width: 164px;
|
width: 164px;
|
||||||
border: 1px solid rgb(220, 223, 230);
|
border: 1px solid rgb(220, 223, 230);
|
||||||
height: 164px;
|
height: 164px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes rotating {
|
@keyframes rotating {
|
||||||
0% {
|
0% {
|
||||||
-webkit-transform: rotate(0deg);
|
-webkit-transform: rotate(0deg);
|
||||||
@@ -258,6 +255,7 @@ export default {
|
|||||||
transform: rotate(1turn);
|
transform: rotate(1turn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-ani {
|
.loading-ani {
|
||||||
animation: rotating 2s linear infinite;
|
animation: rotating 2s linear infinite;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -601,6 +601,24 @@ function dinerDisabled(item, index) {
|
|||||||
return !shopUser.userInfo.eatModel.includes("take-out");
|
return !shopUser.userInfo.eatModel.includes("take-out");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 监听店铺就餐类型配置变化,自动同步 diners.sel,避免切换路由后需刷新才能生效
|
||||||
|
watch(
|
||||||
|
() => shopUser.userInfo && shopUser.userInfo.eatModel,
|
||||||
|
(eatModel) => {
|
||||||
|
console.log("watch eatModel change:", eatModel);
|
||||||
|
if (!eatModel) return;
|
||||||
|
const sel = eatModel.includes("dine-in") ? 0 : 1;
|
||||||
|
if (diners.sel !== sel) {
|
||||||
|
console.log("update diners.sel:", diners.sel, "=>", sel);
|
||||||
|
diners.sel = sel;
|
||||||
|
// 同步 carts 的就餐类型
|
||||||
|
changeCartsDinerType();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
// 商品分类
|
// 商品分类
|
||||||
const category = reactive({
|
const category = reactive({
|
||||||
list: [],
|
list: [],
|
||||||
@@ -795,6 +813,34 @@ onMounted(async () => {
|
|||||||
}
|
}
|
||||||
console.log(table.value);
|
console.log(table.value);
|
||||||
init();
|
init();
|
||||||
|
// 尝试在挂载时主动刷新店铺配置,确保从设置页面返回时能生效
|
||||||
|
await refreshShopUserInfo();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 主动刷新店铺信息并同步就餐类型(用于从设置页返回时生效)
|
||||||
|
async function refreshShopUserInfo() {
|
||||||
|
try {
|
||||||
|
const res = await shopUser.getUserInfo();
|
||||||
|
if (res && res.eatModel) {
|
||||||
|
const sel = res.eatModel.includes("dine-in") ? 0 : 1;
|
||||||
|
if (diners.sel !== sel) {
|
||||||
|
diners.sel = sel;
|
||||||
|
changeCartsDinerType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("refreshShopUserInfo error", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// keep-alive 激活时刷新
|
||||||
|
onActivated(() => {
|
||||||
|
refreshShopUserInfo();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 路由复用或更新时刷新
|
||||||
|
onBeforeRouteUpdate((to, from) => {
|
||||||
|
refreshShopUserInfo();
|
||||||
});
|
});
|
||||||
|
|
||||||
function resetOldOrder() {
|
function resetOldOrder() {
|
||||||
|
|||||||
@@ -23,13 +23,18 @@
|
|||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
|
||||||
<div class="">
|
<div class="" style="display: flex;">
|
||||||
<el-button icon="plus" @click="addEaraShow()">添加区域</el-button>
|
<el-button icon="plus" @click="addEaraShow()">添加区域</el-button>
|
||||||
<el-button type="primary" icon="plus" @click="addTableShow()">添加台桌</el-button>
|
<el-button type="primary" icon="plus" @click="addTableShow()">添加台桌</el-button>
|
||||||
<el-button type="danger" icon="Setting" @click="clearTabDialogRef.show()">清台设置</el-button>
|
<el-button type="danger" icon="Setting" @click="clearTabDialogRef.show()">清台设置</el-button>
|
||||||
<el-button type="primary" icon="download" @click="showDownloadTableCode">
|
<el-button type="primary" icon="download" @click="showDownloadTableCode">
|
||||||
下载桌台码
|
下载桌台码
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<!-- 批量导入 -->
|
||||||
|
<importData :type="5" @close="init" />
|
||||||
|
<!-- <el-button icon="Upload" @click="importDataRef.show()">
|
||||||
|
批量导入
|
||||||
|
</el-button> -->
|
||||||
<!-- <el-button type="primary" icon="download" @click="downloadShopCpde">
|
<!-- <el-button type="primary" icon="download" @click="downloadShopCpde">
|
||||||
下载店铺码
|
下载店铺码
|
||||||
</el-button> -->
|
</el-button> -->
|
||||||
@@ -205,6 +210,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import importData from "@/components/importData/index.vue";
|
||||||
import status from "./status.js";
|
import status from "./status.js";
|
||||||
import { useUserStore } from "@/store/modules/user";
|
import { useUserStore } from "@/store/modules/user";
|
||||||
const shopUser = useUserStore();
|
const shopUser = useUserStore();
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const contentConfig: IContentConfig<any> = {
|
|||||||
// // return shopUserApi.edit(data);
|
// // return shopUserApi.edit(data);
|
||||||
// },
|
// },
|
||||||
pk: "id",
|
pk: "id",
|
||||||
toolbar: ["add"],
|
toolbar: ["add", 'export'],
|
||||||
defaultToolbar: ["refresh", "filter", "search"],
|
defaultToolbar: ["refresh", "filter", "search"],
|
||||||
cols: [
|
cols: [
|
||||||
{ type: "selection", width: 50, align: "center" },
|
{ type: "selection", width: 50, align: "center" },
|
||||||
@@ -82,7 +82,7 @@ const contentConfig: IContentConfig<any> = {
|
|||||||
{
|
{
|
||||||
label: "消费次数累计",
|
label: "消费次数累计",
|
||||||
align: "center",
|
align: "center",
|
||||||
prop: "consumeAmount",
|
prop: "consumeCount",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "注册时间",
|
label: "注册时间",
|
||||||
|
|||||||
@@ -29,8 +29,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 列表 -->
|
<!-- 列表 -->
|
||||||
<page-content ref="contentRef" :content-config="contentConfig" @add-click="handleAddClick"
|
<page-content ref="contentRef" :content-config="contentConfig" @add-click="handleAddClick"
|
||||||
@edit-click="handleEditClick" @export-click="handleExportClick" @search-click="handleSearchClick"
|
@edit-click="handleEditClick" @export-click="handleExportClick" @upload-click="" @search-click="handleSearchClick"
|
||||||
@toolbar-click="handleToolbarClick" @operat-click="handleOperatClick" @filter-change="handleFilterChange">
|
@toolbar-click="handleToolbarClick" @operat-click="handleOperatClick" @filter-change="handleFilterChange">
|
||||||
|
<template #custom>
|
||||||
|
<importData ref="importDataRef" :type="6" @close="searchQueryClick" />
|
||||||
|
</template>
|
||||||
<template #status="scope">
|
<template #status="scope">
|
||||||
<el-link :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
|
<el-link :type="scope.row[scope.prop] == 1 ? 'success' : 'info'">
|
||||||
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
|
{{ scope.row[scope.prop] == 1 ? "启用" : "禁用" }}
|
||||||
@@ -146,6 +149,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import importData from "@/components/importData/index.vue";
|
||||||
import UserCouponDialog from "./components/user-coupon-dialog.vue";
|
import UserCouponDialog from "./components/user-coupon-dialog.vue";
|
||||||
import GiveCoupon from "./components/give-coupon.vue";
|
import GiveCoupon from "./components/give-coupon.vue";
|
||||||
import usePage from "@/components/CURD/usePage";
|
import usePage from "@/components/CURD/usePage";
|
||||||
@@ -158,6 +162,8 @@ import { returnOptionsLabel } from "./config/config";
|
|||||||
import shopUserApi from "@/api/account/shopUser";
|
import shopUserApi from "@/api/account/shopUser";
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { ElNotification } from 'element-plus'
|
import { ElNotification } from 'element-plus'
|
||||||
|
import { downloadFile } from "@/utils/index";
|
||||||
|
|
||||||
const editMoneyModalRef = ref(null);
|
const editMoneyModalRef = ref(null);
|
||||||
const userCouponDialogRef = ref(null);
|
const userCouponDialogRef = ref(null);
|
||||||
const GiveCouponRef = ref(null);
|
const GiveCouponRef = ref(null);
|
||||||
@@ -175,7 +181,7 @@ const {
|
|||||||
// handleAddClick,
|
// handleAddClick,
|
||||||
// handleEditClick,
|
// handleEditClick,
|
||||||
handleSubmitClick,
|
handleSubmitClick,
|
||||||
handleExportClick,
|
// handleExportClick,
|
||||||
handleSearchClick,
|
handleSearchClick,
|
||||||
handleFilterChange,
|
handleFilterChange,
|
||||||
} = usePage();
|
} = usePage();
|
||||||
@@ -217,6 +223,16 @@ function formDataChange(type, val) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 导出
|
||||||
|
async function handleExportClick() {
|
||||||
|
try {
|
||||||
|
const file = await shopUserApi.export(searchRef.value.getQueryParams());
|
||||||
|
downloadFile(file, "用户列表", "xlsx");
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 新增
|
// 新增
|
||||||
async function handleAddClick() {
|
async function handleAddClick() {
|
||||||
addModalRef.value?.setModalVisible();
|
addModalRef.value?.setModalVisible();
|
||||||
@@ -239,6 +255,8 @@ function handleToolbarClick(name) {
|
|||||||
console.log(name);
|
console.log(name);
|
||||||
if (name === "custom1") {
|
if (name === "custom1") {
|
||||||
ElMessage.success("点击了自定义1按钮");
|
ElMessage.success("点击了自定义1按钮");
|
||||||
|
} else if (name === "upload") {
|
||||||
|
importDataRef.value.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,13 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
|||||||
target: env.VITE_APP_API_URL,
|
target: env.VITE_APP_API_URL,
|
||||||
rewrite: (path) => path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""),
|
rewrite: (path) => path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""),
|
||||||
},
|
},
|
||||||
|
// 代理 /dev-api 的请求
|
||||||
|
'/import_api': {
|
||||||
|
changeOrigin: true,
|
||||||
|
// 代理目标地址:https://api.youlai.tech
|
||||||
|
target: env.VITE_APP_API_PHP_IMPORT_URL,
|
||||||
|
rewrite: (path) => path.replace(new RegExp("^" + env.VITE_APP_API_PHP_IMPORT_URL), ""),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|||||||
Reference in New Issue
Block a user