Commit f97656c0 authored by cxr's avatar cxr

Merge branch 'lmy' of http://119.78.67.12/git/root/ops_2024_vue into feature/JiraTML-148/cxr

parents b1eca428 c1da8356
import { tmallabHttp } from '/@/utils/http/axios';
enum Api {
List = '/system/productNegotiated/getList',
BrandList = '/regionalSpotManage/commit',
GetStatus = '/system/opsProduct/IsOpsSupplier',
List = '/system/opsProduct/getList',
GroupList = '/system/opsProduct/getTypeList',
BrandList = '/system/supplierBrandQualification/getApproveList',
ProductList = '/system/productNegotiated/getProductList',
GetAreaList = '/system/opsProduct/getAreaList',
OpsAddProduct = '/system/opsProduct/opsAddProduct',
GetGhsAreaList = '/system/opsProduct/getGhsAreaList',
OpsDeleteProduct = '/system/opsProduct/opsDeleteProduct',
OpsEditProduct = '/system/opsProduct/opsEditProduct',
UploadOpsProduct = '/excel/excelNew/uploadOpsProduct',
QueryList = '/system/logProductManager/queryList',
RevokeExcelUpload = '/system/logProductManager/revokeExcelUpload',
PlatformProBatchList = '/system/logNegotiationProductOperate/getList',
PlatformProBatchGetDetail = '/system/logNegotiationProductOperate/getList',
PlatformProBatchGetDetail = '/system/logNegotiationProductOperate/getDetail',
}
/**
* @description: 区域现货管理列表
*/
export const regionalSpotManageListApi = (data) =>
tmallabHttp.post({ url: Api.List, data }, { errorMessageMode: 'message'});
export const regionalSpotManageGetStatusApi = () => tmallabHttp.post({ url: Api.GetStatus });
/**
* @description: 区域现货管理列表
*/
export const regionalSpotManageListApi = (data) =>
tmallabHttp.post({ url: Api.List, data }, { errorMessageMode: 'message' });
/**
* @description: 获取品牌列表
*/
export const regionalSpotManageBrandListApi = (data) =>
tmallabHttp.post({ url: Api.BrandList,data }, { errorMessageMode: 'message'});
export const regionalSpotManageBrandListApi = (data) =>
tmallabHttp.post({ url: Api.BrandList, data });
/**
* @description: 获取分组列表
*/
export const regionalSpotManageGroupListApi = (data) =>
tmallabHttp.post({ url: Api.GroupList, data });
/**
* @description: 获取左边穿梭框商品列表
*/
export const regionalSpotManageProductListApi = (data) =>
tmallabHttp.post({ url: Api.ProductList, data });
/**
* @description: 获取现货区域列表
*/
export const regionalSpotManageGetAreaListApi = (data) =>
tmallabHttp.post({ url: Api.GetAreaList,data },{ errorMessageMode: 'message' });
export const regionalSpotManageGetAreaListApi = (data) =>
tmallabHttp.post({ url: Api.GetAreaList, data });
/**
* @description: 新增商品接口
*/
export const regionalSpotManageOpsAddProductApi = (data) =>
tmallabHttp.post({ url: Api.OpsAddProduct, data },{ errorMessageMode: 'message' });
export const regionalSpotManageOpsAddProductApi = (data) =>
tmallabHttp.post({ url: Api.OpsAddProduct, data }, { errorMessageMode: 'message' });
/**
* @description: 获取已开通区域
*/
export const regionalSpotManageGetGhsAreaListApi = (data) =>
tmallabHttp.post({ url: Api.GetGhsAreaList, data },{ errorMessageMode: 'message' });
tmallabHttp.post({ url: Api.GetGhsAreaList, data });
/**
* @description: 单条/批量删除
*/
export const regionalSpotManageOpsDeleteProductApi = (data) =>
tmallabHttp.post({ url: Api.OpsDeleteProduct, data },{ errorMessageMode: 'message' });
export const regionalSpotManageOpsDeleteProductApi = (data) =>
tmallabHttp.post({ url: Api.OpsDeleteProduct, data }, { errorMessageMode: 'message' });
/**
* @description: 增加区域
*/
export const regionalSpotManageOpsEditProductApi = (data) =>
tmallabHttp.post({ url: Api.OpsEditProduct, data },{ errorMessageMode: 'message' });
export const regionalSpotManageOpsEditProductApi = (data) =>
tmallabHttp.post({ url: Api.OpsEditProduct, data }, { errorMessageMode: 'message' });
/**
* @description: 批量上传
*/
export const regionalSpotManageUploadOpsProductApi = (data) =>
tmallabHttp.post({ url: Api.UploadOpsProduct, data },{ errorMessageMode: 'message' });
export const regionalSpotManageUploadOpsProductApi = (data, file) =>
tmallabHttp.uploadFile(
{
url: Api.UploadOpsProduct,
method: 'POST',
data,
baseURL: import.meta.env.VITE_GLOB_TMALLAB_URL,
},
{ file, data },
);
/**
* @description: 任务中心获取列表
*/
export const taskCenterQueryListApi = (data) =>
tmallabHttp.post({ url: Api.RevokeExcelUpload, data },{ errorMessageMode: 'message' });
export const taskCenterQueryListApi = (data) => tmallabHttp.post({ url: Api.QueryList, data });
/**
* @description: 撤销
*/
export const taskCenterRevokeExcelUploadApi = (data) =>
tmallabHttp.post({ url: Api.RevokeExcelUpload, data },{ errorMessageMode: 'message' });
export const taskCenterRevokeExcelUploadApi = (data) =>
tmallabHttp.post({ url: Api.RevokeExcelUpload, data }, { errorMessageMode: 'message' });
/**
* @description: 任务中心获取列表--平台商品批量页签
*/
export const platformProBatchGetListApi = (data) =>
tmallabHttp.post({ url: Api.PlatformProBatchList, data },{ errorMessageMode: 'message' });
tmallabHttp.post({ url: Api.PlatformProBatchList, data }, { errorMessageMode: 'message' });
/**
* @description: 任务中心获取列表--平台商品批量页签--操作记录详情
*/
export const platformProBatchGetDetailApi = (data) =>
tmallabHttp.post({ url: Api.PlatformProBatchGetDetail, data },{ errorMessageMode: 'message' });
tmallabHttp.post({ url: Api.PlatformProBatchGetDetail, data }, { errorMessageMode: 'message' });
......@@ -69,5 +69,5 @@ span.anticon:not(.app-iconify) {
margin-left: 24px;
}
.ant-modal-body {
margin-top: 20px;
padding: 20px !important;
}
......@@ -41,7 +41,7 @@ async function bootstrap() {
app.use(Antd);
app.mount('#app');
app.use(Antd)
app.use(Antd);
}
bootstrap();
......@@ -12,6 +12,7 @@ const product: AppRouteModule = {
orderNo: 500,
icon: 'ion:grid-outline',
title: '商品管理',
roles: ['supplier'],
},
children: [
{
......@@ -29,7 +30,7 @@ const product: AppRouteModule = {
meta: {
title: '任务中心',
},
}
},
],
};
......
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { message } from 'ant-design-vue';
import { Input, Button } from 'ant-design-vue';
import { RightOutlined, LeftOutlined } from '@ant-design/icons-vue';
const emit = defineEmits(['close']);
import {
regionalSpotManageBrandListApi,
regionalSpotManageGetAreaListApi,
regionalSpotManageOpsAddProductApi,
} from '/@/api/regionalSpotManage';
import { getAuthCache } from '/@/utils/auth';
const userInfo: any = getAuthCache('USER__INFO__');
const ghsCode = userInfo.supplier.ghsCode;
let searchBrand = ref('');
let searchItemNo = ref('');
let searchBrandList = ref<any[]>([]);
const handleSearch = async (value) => {
const res = await regionalSpotManageBrandListApi({ brand: value });
if (res.code === 20000) {
searchBrandList.value = res.data;
} else {
searchBrandList.value = [];
}
};
const closeModal = () => {
emit('close', false);
};
const leftData = ref<any[]>([]);
const leftColumns = [
{
title: '商品名称',
dataIndex: 'productName',
key: 'productName',
width: '25%',
align: 'center',
},
{ title: '品牌', dataIndex: 'brand', key: 'brand', width: '25%', align: 'center' },
{ title: '货号', dataIndex: 'goodsNo', key: 'goodsNo', width: '20%', align: 'center' },
{ title: '规格', dataIndex: 'spec', key: 'spec', width: '20%', align: 'center' },
];
const pagination = ref({
size: 'small',
pageSize: 10,
current: 1,
total: 0,
showTotal: (total) => `共 ${total} 条`,
hideOnSinglePage: false,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '30', '50', '100'],
onChange: (current) => {
pagination.value.current = current;
getLeftData();
},
onShowSizeChange: (size) => {
pagination.value.pageSize = size;
getLeftData();
},
});
const getLeftData = () => {
leftData.value = [
{
productName: '测试产品1',
brand: '测试品牌1',
goodsNo: '213651',
spec: '100ml',
sysid: '1',
},
{
productName: '测试产品2',
brand: '测试品牌2',
goodsNo: '213652',
spec: '100ml',
sysid: '2',
},
{
productName: '测试产品3',
brand: '测试品牌3',
goodsNo: '213653',
spec: '100ml',
sysid: '3',
},
{
productName: '测试产品4',
brand: '测试品牌4',
goodsNo: '213654',
spec: '100ml',
sysid: '4',
},
{
productName: '测试产品5',
brand: '测试品牌5',
goodsNo: '213655',
spec: '100ml',
sysid: '5',
choice: true,
},
{
productName: '测试产品6',
brand: '测试品牌6',
goodsNo: '213656',
spec: '100ml',
sysid: '6',
choice: true,
},
];
if (rightData.value.length > 0) {
for (let i = 0; i < rightData.value.length; i++) {
if (
leftData.value.findIndex(
(v) =>
v.brand + v.goodsNo + v.spec ===
rightData.value[i].brand + rightData.value[i].goodsNo + rightData.value[i].spec,
) !== -1
) {
leftData.value.find(
(v) =>
v.brand + v.goodsNo + v.spec ===
rightData.value[i].brand + rightData.value[i].goodsNo + rightData.value[i].spec,
).choice = true;
}
}
}
leftData.value = [...leftData.value];
pagination.value.total = leftData.value.length;
};
let selectedRowKeys = ref<any[]>([]);
let selectedRows = ref<any[]>([]);
const rowSelection = computed(() => {
return {
selectedRowKeys: selectedRowKeys.value,
onChange: (RowKeys, Rows) => {
selectedRowKeys.value = RowKeys;
selectedRows.value = Rows;
},
getCheckboxProps: (record) => ({
disabled: record.choice === true,
}),
};
});
const toRight = () => {
console.log(selectedRows.value);
let arr = JSON.parse(JSON.stringify(selectedRows.value));
rightData.value = [...arr, ...rightData.value];
for (let i = 0; i < selectedRows.value.length; i++) {
if (
leftData.value.findIndex(
(v) =>
v.brand + v.goodsNo + v.spec ===
selectedRows.value[i].brand +
selectedRows.value[i].goodsNo +
selectedRows.value[i].spec,
) !== -1
) {
leftData.value.find(
(v) =>
v.brand + v.goodsNo + v.spec ===
selectedRows.value[i].brand +
selectedRows.value[i].goodsNo +
selectedRows.value[i].spec,
).choice = true;
}
}
leftData.value = [...leftData.value];
selectedRowKeys.value = [];
selectedRows.value = [];
};
const rightData = ref<any[]>([]);
const rightSelectedRowKeys = ref<any[]>([]);
const rightSelectedRows = ref<any[]>([]);
const rightRowSelection = computed(() => {
return {
selectedRowKeys: rightSelectedRowKeys.value,
onChange: (RowKeys, Rows) => {
rightSelectedRowKeys.value = RowKeys;
rightSelectedRows.value = Rows;
},
};
});
const toLeft = () => {
for (let i = 0; i < rightSelectedRows.value.length; i++) {
if (
leftData.value.findIndex(
(v) =>
v.brand + v.goodsNo + v.spec ===
rightSelectedRows.value[i].brand +
rightSelectedRows.value[i].goodsNo +
rightSelectedRows.value[i].spec,
) !== -1
) {
leftData.value.find(
(v) =>
v.brand + v.goodsNo + v.spec ===
rightSelectedRows.value[i].brand +
rightSelectedRows.value[i].goodsNo +
rightSelectedRows.value[i].spec,
).choice = false;
rightData.value.splice(
rightData.value.findIndex(
(v) =>
v.brand + v.goodsNo + v.spec ==
rightSelectedRows.value[i].brand +
rightSelectedRows.value[i].goodsNo +
rightSelectedRows.value[i].spec,
),
1,
);
} else {
rightData.value.splice(
rightData.value.findIndex(
(v) =>
v.brand + v.goodsNo + v.spec ==
rightSelectedRows.value[i].brand +
rightSelectedRows.value[i].goodsNo +
rightSelectedRows.value[i].spec,
),
1,
);
}
}
leftData.value = [...leftData.value];
rightData.value = [...rightData.value];
rightSelectedRowKeys.value = [];
rightSelectedRows.value = [];
};
const rowClassName = () => {
return 'table-back';
};
let loading = ref(false);
let addressLoading = ref(false);
const goNext = async () => {
if (!rightData.value.length) return message.error('请先选择商品');
addressVisible.value = true;
addressLoading.value = true;
const res = await regionalSpotManageGetAreaListApi({});
if (res.code === 20000) {
areaList.value = res.data;
} else {
areaList.value = [];
}
addressLoading.value = false;
};
// ==================================================
const confirmLoading = ref(false);
const addressVisible = ref(false);
const checkboxValue = ref([]);
const areaList = ref<any[]>([
{
id: '0',
provinceId: '0',
province: '北京市',
cityId: 0,
city: '市辖区',
creator: '',
creationTime: '',
},
{
id: '1',
provinceId: '1',
province: '河北省',
cityId: 1,
city: '保定市',
creator: '',
creationTime: '',
},
{
id: '2',
provinceId: '2',
province: '河北省',
cityId: 2,
city: '石家庄市',
creator: '',
creationTime: '',
},
{
id: '3',
provinceId: '3',
province: '河北省',
cityId: 3,
city: '秦皇岛市',
creator: '',
creationTime: '',
},
{
id: '4',
provinceId: '4',
province: '河北省',
cityId: 3,
city: '承德市',
creator: '',
creationTime: '',
},
]);
const handleCancel = () => {
addressVisibleClose();
};
const goPrevious = () => {
addressVisibleClose();
};
const addressVisibleClose = () => {
addressVisible.value = false;
checkboxValue.value = [];
};
const confirm = async () => {
if (!checkboxValue.value.length) return message.error('请选择现货区域');
const param = ref<{ [key: string]: any }>({
products: [],
areas: '',
});
param.value.products = rightData.value.map((v) => {
return {
goodsNo: v.goodsNo,
brand: v.brand,
spec: v.spec,
ghscode: ghsCode,
};
});
param.value.areas = checkboxValue.value.join;
console.log(param.value);
confirmLoading.value = true;
const res = await regionalSpotManageOpsAddProductApi(param.value);
if (res.code === 20000) {
message.success('新增成功');
addressVisibleClose();
emit('close', false);
} else {
message.error(res.message);
}
confirmLoading.value = false;
};
</script>
<template>
<a-modal
:visible="true"
title="新增区域现货商品"
:width="1200"
@cancel="closeModal"
:maskClosable="false"
:keyboard="false"
>
<template #footer>
<a-button key="back" @click="closeModal">取消</a-button>
<a-button key="submit" type="primary" :loading="loading" @click="goNext">下一步</a-button>
</template>
<div>
<span>品牌名称:</span>
<a-select
v-model:value="searchBrand"
show-search
placeholder="请输入品牌名称"
style="width: 200px"
:default-active-first-option="false"
:show-arrow="false"
:filter-option="false"
:not-found-content="null"
@search="handleSearch"
>
<a-select-option
v-for="item in searchBrandList"
:key="item.value"
:label="item.label"
:value="item.value"
>
{{ item.label }}
</a-select-option>
</a-select>
<span style="margin-left: 15px">货号:</span>
<Input
v-model:value="searchItemNo"
allow-clear
placeholder="请输入货号"
style="width: 200px"
/>
<Button style="margin-left: 10px">重置</Button>
<Button @click="getLeftData" type="primary" style="margin-left: 10px">查询</Button>
</div>
<div class="main">
<div class="left">
<div class="header">
<div>筛选结果商品</div>
<span>{{ selectedRowKeys.length }}/{{ pagination.total }}</span>
</div>
<div class="table">
<a-table
bordered
:data-source="leftData"
:columns="leftColumns"
:pagination="pagination"
:row-selection="rowSelection"
:rowKey="(record) => record.brand + record.goodsNo + record.spec"
:scroll="{ x: false, y: 280 }"
:rowClassName="rowClassName"
:loading="loading"
>
<!-- <template #bodyCell="{ column, record }">
<template v-if="column.key === 'productName'">
<span>{{ record.chineseName ? record.chineseName : record.englishName }}</span>
</template>
</template> -->
</a-table>
</div>
</div>
<div class="operate">
<div style="margin-top: 200px; display: flex">
<a-button
@click="toLeft"
type="primary"
:disabled="rightSelectedRowKeys.length === 0"
style="display: block; margin-bottom: 10px; margin-right: 10px"
>
<template #icon>
<LeftOutlined />
</template>
</a-button>
<a-button
@click="toRight"
type="primary"
style="display: block"
:disabled="selectedRowKeys.length === 0"
>
<template #icon>
<RightOutlined />
</template>
</a-button>
</div>
</div>
<div class="right">
<div class="header">
<div>被选中商品</div>
<span>{{ rightSelectedRowKeys.length }}/{{ rightData.length }}</span>
</div>
<div class="table">
<a-table
:data-source="rightData"
:columns="leftColumns"
:pagination="false"
:rowKey="(record) => record.brand + record.goodsNo + record.spec"
:scroll="{ x: false, y: 280 }"
:rowClassName="rowClassName"
:row-selection="rightRowSelection"
/>
</div>
</div>
</div>
</a-modal>
<a-modal
v-model:visible="addressVisible"
title="新增区域现货商品"
@cancel="handleCancel"
@ok="confirm"
:width="1200"
:maskClosable="false"
:keyboard="false"
>
<template #footer>
<a-button :loading="confirmLoading" @click="handleCancel">取消</a-button>
<a-button :loading="confirmLoading" @click="goPrevious">上一步</a-button>
<a-button type="primary" :loading="confirmLoading" @click="confirm">提交</a-button>
</template>
<a-alert type="warning">
<template #message>
<span style="color: red">特别提醒:</span
>北京市-直辖市;天津市-直辖市。本次设置为,北京市-直辖市;四川省-成都市。提交后,商品现货区域将更新为
北京市-直辖市;天津市-直辖市;四川省-成都市。
</template>
</a-alert>
<a-spin v-if="addressLoading" style="height: 150px; width: 100%; line-height: 150px" />
<div v-else>
<p style="margin-top: 15px">选择现货区域:</p>
<a-checkbox-group v-model:value="checkboxValue" style="width: 100%">
<a-row>
<a-col :span="6" v-for="(item, index) in areaList" :key="index">
<a-checkbox :value="item.id">{{ item.province }}-{{ item.city }}</a-checkbox>
</a-col>
</a-row>
</a-checkbox-group>
</div>
</a-modal>
</template>
<style lang="less" scoped>
.main {
display: flex;
justify-content: space-around;
width: 100%;
margin-top: 15px;
.left {
width: 45%;
border: 1px solid #ddd;
height: 450px;
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
height: 60px;
background: #f3f6f9;
}
}
.right {
width: 45%;
border: 1px solid #ddd;
height: 450px;
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
height: 60px;
background: #f3f6f9;
}
}
.operate {
width: 10%;
height: 450px;
display: flex;
justify-content: center;
align-content: center;
}
}
/deep/.table-back {
background-color: #fff;
}
</style>
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { message } from 'ant-design-vue';
import { Input, Button } from 'ant-design-vue';
import { RightOutlined, LeftOutlined } from '@ant-design/icons-vue';
const emit = defineEmits(['close']);
import {
regionalSpotManageBrandListApi,
regionalSpotManageProductListApi,
regionalSpotManageGetAreaListApi,
regionalSpotManageOpsAddProductApi,
} from '/@/api/regionalSpotManage';
import { getAuthCache } from '/@/utils/auth';
const userInfo: any = getAuthCache('USER__INFO__');
const ghsCode = userInfo.supplier.ghsCode;
const searchBrand = ref('');
const searchItemNo = ref('');
const searchBrandList = ref<any[]>([]);
const handleSearch = async (value) => {
const res = await regionalSpotManageBrandListApi({ brand: value });
if (res.success) {
searchBrandList.value = res.data;
} else {
searchBrandList.value = [];
}
};
const closeModal = () => {
emit('close', false);
};
const leftLoading = ref(false);
const leftData = ref<any[]>([]);
const leftColumns = [
{
title: '商品名称',
key: 'productName',
width: '25%',
align: 'center',
},
{ title: '品牌', dataIndex: 'brand', key: 'brand', width: '25%', align: 'center' },
{ title: '货号', dataIndex: 'goodsNo', key: 'goodsNo', width: '20%', align: 'center' },
{ title: '规格', dataIndex: 'spec', key: 'spec', width: '20%', align: 'center' },
];
const pagination = ref({
size: 'small',
pageSize: 10,
current: 1,
total: 0,
showTotal: (total) => `共 ${total} 条`,
hideOnSinglePage: false,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '30', '50', '100'],
onChange: (current) => {
pagination.value.current = current;
getLeftData();
},
onShowSizeChange: (size) => {
pagination.value.pageSize = size;
getLeftData();
},
});
const reset = () => {
searchBrand.value = '';
searchItemNo.value = '';
pagination.value.current = 1;
getLeftData();
};
const getLeftData = async () => {
const param = {
pageIndex: pagination.value.current,
pageSize: pagination.value.pageSize,
ghsCode: ghsCode,
productName: '',
brand: searchBrand.value,
goodsNo: searchItemNo.value,
};
leftLoading.value = true;
const res = await regionalSpotManageProductListApi(param);
if (res.success) {
leftData.value = res.data;
} else {
leftData.value = [];
}
leftLoading.value = false;
if (rightData.value.length > 0) {
for (let i = 0; i < rightData.value.length; i++) {
if (
leftData.value.findIndex(
(v) =>
v.brand + v.goodsNo + v.spec ===
rightData.value[i].brand + rightData.value[i].goodsNo + rightData.value[i].spec,
) !== -1
) {
leftData.value.find(
(v) =>
v.brand + v.goodsNo + v.spec ===
rightData.value[i].brand + rightData.value[i].goodsNo + rightData.value[i].spec,
).choice = true;
}
}
}
leftData.value = [...leftData.value];
pagination.value.total = leftData.value.length;
};
const selectedRowKeys = ref<any[]>([]);
const selectedRows = ref<any[]>([]);
const rowSelection = computed(() => {
return {
selectedRowKeys: selectedRowKeys.value,
onChange: (RowKeys, Rows) => {
selectedRowKeys.value = RowKeys;
selectedRows.value = Rows;
},
getCheckboxProps: (record) => ({
disabled: record.choice === true,
}),
};
});
const toRight = () => {
let arr = JSON.parse(JSON.stringify(selectedRows.value));
rightData.value = [...arr, ...rightData.value];
for (let i = 0; i < selectedRows.value.length; i++) {
if (
leftData.value.findIndex(
(v) =>
v.brand + v.goodsNo + v.spec ===
selectedRows.value[i].brand +
selectedRows.value[i].goodsNo +
selectedRows.value[i].spec,
) !== -1
) {
leftData.value.find(
(v) =>
v.brand + v.goodsNo + v.spec ===
selectedRows.value[i].brand +
selectedRows.value[i].goodsNo +
selectedRows.value[i].spec,
).choice = true;
}
}
leftData.value = [...leftData.value];
selectedRowKeys.value = [];
selectedRows.value = [];
};
const rightData = ref<any[]>([]);
const rightSelectedRowKeys = ref<any[]>([]);
const rightSelectedRows = ref<any[]>([]);
const rightRowSelection = computed(() => {
return {
selectedRowKeys: rightSelectedRowKeys.value,
onChange: (RowKeys, Rows) => {
rightSelectedRowKeys.value = RowKeys;
rightSelectedRows.value = Rows;
},
};
});
const toLeft = () => {
for (let i = 0; i < rightSelectedRows.value.length; i++) {
if (
leftData.value.findIndex(
(v) =>
v.brand + v.goodsNo + v.spec ===
rightSelectedRows.value[i].brand +
rightSelectedRows.value[i].goodsNo +
rightSelectedRows.value[i].spec,
) !== -1
) {
leftData.value.find(
(v) =>
v.brand + v.goodsNo + v.spec ===
rightSelectedRows.value[i].brand +
rightSelectedRows.value[i].goodsNo +
rightSelectedRows.value[i].spec,
).choice = false;
rightData.value.splice(
rightData.value.findIndex(
(v) =>
v.brand + v.goodsNo + v.spec ==
rightSelectedRows.value[i].brand +
rightSelectedRows.value[i].goodsNo +
rightSelectedRows.value[i].spec,
),
1,
);
} else {
rightData.value.splice(
rightData.value.findIndex(
(v) =>
v.brand + v.goodsNo + v.spec ==
rightSelectedRows.value[i].brand +
rightSelectedRows.value[i].goodsNo +
rightSelectedRows.value[i].spec,
),
1,
);
}
}
leftData.value = [...leftData.value];
rightData.value = [...rightData.value];
rightSelectedRowKeys.value = [];
rightSelectedRows.value = [];
};
const rowClassName = () => {
return 'table-back';
};
const loading = ref(false);
const addressLoading = ref(false);
const goNext = async () => {
if (!rightData.value.length) return message.error('请先选择商品');
addressVisible.value = true;
addressLoading.value = true;
const res = await regionalSpotManageGetAreaListApi({});
if (res.success) {
areaList.value = res.data;
} else {
areaList.value = [];
}
addressLoading.value = false;
};
// ==================================================
const confirmLoading = ref(false);
const addressVisible = ref(false);
const checkboxValue = ref([]);
interface AreaIds {
city?: string;
cityId?: number;
creationTime?: string;
creator?: string;
id?: number;
province?: string;
provinceId?: number;
}
const areaList = ref<AreaIds[]>([]);
const handleCancel = () => {
addressVisibleClose();
};
const goPrevious = () => {
addressVisibleClose();
};
const addressVisibleClose = () => {
addressVisible.value = false;
checkboxValue.value = [];
};
const confirm = async () => {
if (!checkboxValue.value.length) return message.error('请选择现货区域');
const param = ref<{ [key: string]: any }>({
products: [],
areas: '',
});
param.value.products = rightData.value.map((v) => {
return {
goodsNo: v.goodsNo,
brand: v.brand,
spec: v.spec,
ghscode: ghsCode,
};
});
param.value.areas = checkboxValue.value;
confirmLoading.value = true;
const res = await regionalSpotManageOpsAddProductApi(param.value);
if (res.success) {
message.success('新增成功');
addressVisibleClose();
emit('close', false, 'refresh');
} else {
message.error(res.message);
}
confirmLoading.value = false;
};
</script>
<template>
<a-modal
:visible="true"
title="新增区域现货商品"
:width="1200"
@cancel="closeModal"
:maskClosable="false"
:keyboard="false"
>
<template #footer>
<a-button key="back" @click="closeModal">取消</a-button>
<a-button key="submit" type="primary" :loading="loading" @click="goNext">下一步</a-button>
</template>
<div>
<span>品牌名称:</span>
<a-select
v-model:value="searchBrand"
show-search
placeholder="请输入品牌名称"
style="width: 200px"
:default-active-first-option="false"
:show-arrow="false"
:filter-option="false"
:not-found-content="null"
@search="handleSearch"
>
<a-select-option
v-for="item in searchBrandList"
:key="item.brand"
:label="item.brand"
:value="item.brand"
>
{{ item.brand }}
</a-select-option>
</a-select>
<span style="margin-left: 15px">货号:</span>
<Input
v-model:value="searchItemNo"
allow-clear
placeholder="请输入货号"
style="width: 200px"
/>
<Button @click="reset" style="margin-left: 10px">重置</Button>
<Button @click="getLeftData" type="primary" style="margin-left: 10px">查询</Button>
</div>
<div class="main">
<div class="left">
<div class="header">
<div>筛选结果商品</div>
<span>{{ selectedRowKeys.length }}/{{ pagination.total }}</span>
</div>
<div class="table">
<a-table
bordered
:data-source="leftData"
:columns="leftColumns"
:pagination="pagination"
:row-selection="rowSelection"
:rowKey="(record) => record.brand + record.goodsNo + record.spec"
:scroll="{ x: false, y: 280 }"
:rowClassName="rowClassName"
:loading="leftLoading"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'productName'">
<span>{{ record.chineseName ? record.chineseName : record.englishName }}</span>
</template>
</template>
</a-table>
</div>
</div>
<div class="operate">
<div style="margin-top: 200px; display: flex">
<a-button
@click="toLeft"
type="primary"
:disabled="rightSelectedRowKeys.length === 0"
style="display: block; margin-bottom: 10px; margin-right: 10px"
>
<template #icon>
<LeftOutlined />
</template>
</a-button>
<a-button
@click="toRight"
type="primary"
style="display: block"
:disabled="selectedRowKeys.length === 0"
>
<template #icon>
<RightOutlined />
</template>
</a-button>
</div>
</div>
<div class="right">
<div class="header">
<div>被选中商品</div>
<span>{{ rightSelectedRowKeys.length }}/{{ rightData.length }}</span>
</div>
<div class="table">
<a-table
:data-source="rightData"
:columns="leftColumns"
:pagination="false"
:rowKey="(record) => record.brand + record.goodsNo + record.spec"
:scroll="{ x: false, y: 280 }"
:rowClassName="rowClassName"
:row-selection="rightRowSelection"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'productName'">
<span>{{ record.chineseName ? record.chineseName : record.englishName }}</span>
</template>
</template>
</a-table>
</div>
</div>
</div>
</a-modal>
<a-modal
v-model:visible="addressVisible"
title="新增区域现货商品"
@cancel="handleCancel"
@ok="confirm"
:width="1200"
:maskClosable="false"
:keyboard="false"
>
<template #footer>
<a-button :loading="confirmLoading" @click="handleCancel">取消</a-button>
<a-button :loading="confirmLoading" @click="goPrevious">上一步</a-button>
<a-button type="primary" :loading="confirmLoading" @click="confirm">提交</a-button>
</template>
<a-alert type="warning">
<template #message>
<span style="color: red">特别提醒:</span
>北京市-直辖市;天津市-直辖市。本次设置为,北京市-直辖市;四川省-成都市。提交后,商品现货区域将更新为
北京市-直辖市;天津市-直辖市;四川省-成都市。
</template>
</a-alert>
<a-spin v-if="addressLoading" style="height: 150px; width: 100%; line-height: 150px" />
<div v-else>
<p style="margin-top: 15px">选择现货区域:</p>
<a-checkbox-group v-model:value="checkboxValue" style="width: 100%">
<a-row>
<a-col :span="6" v-for="(item, index) in areaList" :key="index">
<a-checkbox :value="item.cityId">{{ item.province }}-{{ item.city }}</a-checkbox>
</a-col>
</a-row>
</a-checkbox-group>
</div>
</a-modal>
</template>
<style lang="less" scoped>
.main {
display: flex;
justify-content: space-around;
width: 100%;
margin-top: 15px;
.left {
width: 45%;
border: 1px solid #ddd;
height: 450px;
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
height: 60px;
background: #f3f6f9;
}
}
.right {
width: 45%;
border: 1px solid #ddd;
height: 450px;
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 10px;
height: 60px;
background: #f3f6f9;
}
}
.operate {
width: 10%;
height: 450px;
display: flex;
justify-content: center;
align-content: center;
}
}
/deep/.table-back {
background-color: #fff;
}
</style>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
const config = import.meta.env
import {
taskCenterQueryListApi,
} from '/@/api/regionalSpotManage';
onMounted(async () => {
getList()
});
let list = ref<any[]>([])
let listLoading = ref(false)
const downLoad = (url) => {
window.open(config.VITE_GLOB_API_URL + '/system/' + url, '_blank')
}
const getList = async () => {
listLoading.value = true
const res = await taskCenterQueryListApi({type:1})
if (res.code === 20000) {
list.value = res.data
} else {
list.value = []
}
listLoading.value = false
}
</script>
<template>
<div>
<a-button @click="getList" type="primary">刷新数据</a-button>
</div>
<a-table
:data-source="list"
:loading="listLoading"
bordered
:rowKey="(record) => record.sysid"
style="margin-top: 15px"
>
<a-table-column title="操作时间" align="center" :width="100">
<template v-slot="{record}">
{{ record.createTime }}
</template>
</a-table-column>
<a-table-column title="类型" align="center" :width="100">
<template v-slot="{record}">
{{ record.type }}
</template>
</a-table-column>
<a-table-column title="导出状态" align="center" :width="100">
<template v-slot="{record}">
<p>{{ record.status == 0 ? '待进行 ': (record.status == 1 ? '进行中' : '已完成') }}</p>
</template>
</a-table-column>
<a-table-column title="数据量" align="center" :width="100">
<template v-slot="{record}">
{{ record.successNum }}
</template>
</a-table-column>
<a-table-column title="操作人" align="center" :width="100">
<template v-slot="{record}">
{{ record.createName }}
</template>
</a-table-column>
<a-table-column title="操作" align="center" :width="200">
<template v-slot="{record}">
<Button v-if="record.fileUrl" type="link" @click="downLoad(record.fileUrl)">下载文件</Button>
<span v-else>——</span>
</template>
</a-table-column>
</a-table>
</template>
<style lang="less" scoped>
</style>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
const config = import.meta.env;
import { taskCenterQueryListApi } from '/@/api/regionalSpotManage';
onMounted(async () => {
getList();
});
let list = ref<any[]>([]);
let listLoading = ref(false);
const downLoad = (url) => {
window.open(config.VITE_GLOB_TMALLAB_URL + '/system/' + url, '_blank');
};
const getList = async () => {
listLoading.value = true;
const res = await taskCenterQueryListApi({ type: 1 });
if (res.success) {
list.value = res.data;
} else {
list.value = [];
}
listLoading.value = false;
};
</script>
<template>
<div>
<a-button @click="getList" type="primary">刷新数据</a-button>
</div>
<a-table
:data-source="list"
:loading="listLoading"
bordered
:rowKey="(record) => record.sysid"
style="margin-top: 15px"
>
<a-table-column title="操作时间" align="center" :width="100">
<template #default="{ record }">
{{ record.createTime }}
</template>
</a-table-column>
<a-table-column title="类型" align="center" :width="100">
<template #default="{ record }">
{{ record.type }}
</template>
</a-table-column>
<a-table-column title="导出状态" align="center" :width="100">
<template #default="{ record }">
<p>{{ record.status == 0 ? '待进行 ' : record.status == 1 ? '进行中' : '已完成' }}</p>
</template>
</a-table-column>
<a-table-column title="数据量" align="center" :width="100">
<template #default="{ record }">
{{ record.successNum }}
</template>
</a-table-column>
<a-table-column title="操作人" align="center" :width="100">
<template #default="{ record }">
{{ record.createName }}
</template>
</a-table-column>
<a-table-column title="操作" align="center" :width="200">
<template #default="{ record }">
<a-button v-if="record.fileUrl" type="link" @click="downLoad(record.fileUrl)"
>下载文件</a-button
>
<span v-else>——</span>
</template>
</a-table-column>
</a-table>
</template>
<style lang="less" scoped></style>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import {
Form,
FormItem,
Input,
Button,
Select,
SelectOption,
Row,
Col,
message,
} from 'ant-design-vue';
import { UploadOutlined } from '@ant-design/icons-vue';
import { useRouter } from 'vue-router';
import { getAuthCache } from '/@/utils/auth';
import {
regionalSpotManageBrandListApi,
regionalSpotManageListApi,
regionalSpotManageGetAreaListApi,
regionalSpotManageGetGhsAreaListApi,
regionalSpotManageOpsDeleteProductApi,
regionalSpotManageOpsEditProductApi,
regionalSpotManageUploadOpsProductApi,
} from '/@/api/regionalSpotManage';
import addProductModal from './addProduct.vue';
const config = import.meta.env;
const userInfo: any = getAuthCache('USER__INFO__');
const ghsCode = userInfo.supplier.ghsCode;
const router = useRouter();
const list = ref<any[]>([]);
onMounted(async () => {
getList();
getAllAreaList();
});
const searchForm = ref<{
brandList: any;
goodsNo: any;
areaIds: any;
types: any;
}>({
brandList: [],
goodsNo: '',
areaIds: [],
types: [],
});
const areaIdsOption = ref([
{ label: '区域1', value: '区域1' },
{ label: '区域2', value: '区域2' },
]);
const typesOption = ref([
{ label: '组1', value: '组1' },
{ label: '组2', value: '组2' },
]);
let searchBrandList = ref<any[]>([]);
const handleSearch = async (value) => {
const res = await regionalSpotManageBrandListApi({ brand: value });
if (res.code === 20000) {
searchBrandList.value = res.data;
} else {
searchBrandList.value = [];
}
};
let listLoading = ref(false);
const pagination = ref({
pageSize: 10,
current: 1,
total: 0,
showTotal: (total) => `共 ${total} 条`,
hideOnSinglePage: false,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '30', '50', '100'],
onChange: (current) => {
pagination.value.current = current;
getList();
},
onShowSizeChange: (size) => {
pagination.value.pageSize = size;
getList();
},
});
const getList = async () => {
const pager = ref({
pageIndex: 1,
pageSize: 10,
});
const param = ref({
...searchForm.value,
...pager.value,
});
param.value.areaIds = param.value.areaIds ? param.value.areaIds : [];
param.value.types = param.value.types ? param.value.types : [];
listLoading.value = true;
const res = await regionalSpotManageListApi(param.value);
if (res.code === 20000) {
list.value = res.data;
pagination.value.total = res.data[0].total;
} else {
list.value = [];
pagination.value.total = 0;
}
listLoading.value = false;
list.value = [
{
productName: '测试商品',
brand: '测试品牌',
goodsNo: '45641',
spec: '100ml',
productStatus: '上架',
sysid: '1',
},
{
productName: 'ffff',
brand: 'fff',
goodsNo: 'fff',
spec: 'ff',
productStatus: '上架',
sysid: '2',
},
];
};
const onRset = () => {
searchForm.value.brandList = [];
searchForm.value.goodsNo = '';
searchForm.value.areaIds = [];
searchForm.value.types = [];
getList();
};
const onSearch = () => {
pagination.value.pageSize = 1;
getList();
};
let showModal = ref(false);
const addProduct = () => {
showModal.value = true;
};
// 关闭新增商品弹窗
const closeVisible = (val) => {
showModal.value = val;
};
let curItem = ref<{ [key: string]: any }>({});
// =========查看区域现货 statr ===========
const loading1 = ref(false);
const visible = ref(false);
const regionalSpotGoods = ref([]);
const viewCurrent = async (val) => {
curItem.value = val;
visible.value = true;
const param = ref<{ [key: string]: any }>({
products: [
{
goodsNo: val.goodsNo,
brand: val.brand,
spec: val.spec,
ghscode: ghsCode,
},
],
});
console.log(param.value);
loading1.value = true;
const result = await getAreaList(param.value);
regionalSpotGoods.value = result;
loading1.value = false;
};
const getAreaList = async (param) => {
const res = await regionalSpotManageGetGhsAreaListApi(param);
if (res.code === 20000) {
return res.data;
} else {
return [];
}
};
// ==========查看区域现货 end =============
let selectedRowKeys = ref([]);
let selectedRows = ref<any[]>([]);
const onSelectChange = (Keys, Rows) => {
selectedRowKeys.value = Keys;
selectedRows.value = Rows;
};
// ===============增加区域 start=======================
let addVisible = ref(false);
let addAreaLoading = ref(false);
let addCheckboxValue = ref(['0']);
const addArea = async (row) => {
curItem.value = row;
addVisible.value = true;
addAreaLoading.value = true;
const param = ref<{ [key: string]: any }>({
products: [
{
goodsNo: row.goodsNo,
brand: row.brand,
spec: row.spec,
ghscode: ghsCode,
},
],
});
const result = await getAreaList(param.value);
delAreaList.value = result;
const curArr = delAreaList.value.map((it) => it.id);
for (const k of allAreaList.value) {
if (curArr.includes(k.id)) {
addCheckboxValue.value.push(k.id);
k.disabled = true;
}
}
addAreaLoading.value = false;
};
const addVisibleCancel = () => {
addVisible.value = false;
addCheckboxValue.value = [];
};
let confirmAddLoading = ref(false);
const confirmAddArea = async () => {
const param = ref<{ [key: string]: any }>({
products: [
{
goodsNo: curItem.value.goodsNo,
brand: curItem.value.brand,
spec: curItem.value.spec,
ghscode: ghsCode,
},
],
areas: addCheckboxValue.value.join,
});
confirmAddLoading.value = true;
const res = await regionalSpotManageOpsEditProductApi(param.value);
if (res.success) {
message.success('添加区域成功');
} else {
message.error(res.message);
}
confirmAddLoading.value = false;
};
// ===============增加区域 end=======================
// ================区域现货商品删除 start=====================
let delVisible = ref(false);
let delLoading = ref(false);
let deleteNum = ref(0);
let radioValue = ref(1);
let delAreaList = ref<any[]>([
{
id: '0',
provinceId: '0',
province: '北京市',
cityId: 0,
city: '市辖区',
creator: '',
creationTime: '',
},
{
id: '1',
provinceId: '1',
province: '河北省',
cityId: 1,
city: '保定市',
creator: '',
creationTime: '',
},
]); //已添加的区域
let delCheckboxValue = ref([]);
const del = async (val) => {
curItem.value = val;
deleteNum.value = 1;
delVisible.value = true;
const param = ref<{ [key: string]: any }>({
products: [
{
goodsNo: val.goodsNo,
brand: val.brand,
spec: val.spec,
ghscode: ghsCode,
},
],
});
console.log(param.value);
// delLoading.value = true
// const result = await getAreaList(param.value)
// delAreaList.value = result
// delLoading.value = false
};
const delVisibleCancel = () => {
delVisible.value = false;
deleteNum.value = 0;
radioValue.value = 1;
delCheckboxValue.value = [];
isBatchDel.value = false;
};
let delConfirLoading = ref(false);
const confirmDel = async () => {
if (radioValue.value === 2 && !delCheckboxValue.value.length)
return message.error('请选择需要删除的现货区域');
const param = ref<{ [key: string]: any }>({
products: [],
areas: '',
isAll: false,
});
if (isBatchDel.value) {
param.value.products = selectedRows.value.map((v) => {
return {
goodsNo: v.goodsNo,
brand: v.brand,
spec: v.spec,
ghscode: ghsCode,
};
});
} else {
param.value.products = [
{
goodsNo: curItem.value.goodsNo,
brand: curItem.value.brand,
spec: curItem.value.spec,
ghscode: ghsCode,
},
];
}
if (radioValue.value === 1) {
param.value.isAll = true;
param.value.areas = delAreaList.value.map((v) => v.id);
} else if (radioValue.value === 2) {
param.value.areas = delCheckboxValue.value;
}
delConfirLoading.value = true;
const res = await regionalSpotManageOpsDeleteProductApi(param.value);
if (res.success) {
message.success('删除成功');
} else {
message.success(res.message);
}
delConfirLoading.value = false;
};
// 批量删除
let isBatchDel = ref(false);
const batchDel = () => {
if (!selectedRowKeys.value.length) return message.error('请勾选商品');
isBatchDel.value = true;
deleteNum.value = selectedRows.value.length;
delVisible.value = true;
const param = ref<{ [key: string]: any }>({
products: [],
});
param.value.products = selectedRows.value.map((v) => {
return {
goodsNo: v.goodsNo,
brand: v.brand,
spec: v.spec,
ghscode: ghsCode,
};
});
// delLoading.value = true
// const result = await getAreaList(param.value)
// delAreaList.value = result
// delLoading.value = false
};
// ================区域现货商品删除 end=====================
let allAreaList = ref<any[]>([
{
id: '0',
provinceId: '0',
province: '北京市',
cityId: 0,
city: '市辖区',
creator: '',
creationTime: '',
disabled: true,
},
{
id: '1',
provinceId: '1',
province: '河北省',
cityId: 1,
city: '保定市',
creator: '',
creationTime: '',
},
{
id: '2',
provinceId: '2',
province: '河北省',
cityId: 2,
city: '石家庄市',
creator: '',
creationTime: '',
},
{
id: '3',
provinceId: '3',
province: '河北省',
cityId: 3,
city: '秦皇岛市',
creator: '',
creationTime: '',
},
{
id: '4',
provinceId: '4',
province: '河北省',
cityId: 3,
city: '承德市',
creator: '',
creationTime: '',
},
]);
const getAllAreaList = async () => {
const res = await regionalSpotManageGetAreaListApi({});
if (res.success) {
allAreaList.value = res.data;
} else {
allAreaList.value = [];
}
};
// =====================批量导入 start=======================
let productExcelList = ref<any[]>([]);
let importVisible = ref(false);
const impotrCheckboxValue = ref([]);
const batchImport = () => {
importVisible.value = true;
allAreaList.value.forEach((v) => {
v.disabled = false;
});
};
const productExcelBeforeUpload = (file, fileList) => {
const isLt8M = file.size / 1024 / 1024 <= 8;
const extension = file.name.substring(file.name.lastIndexOf('.') + 1);
if (!isLt8M) {
message.error('上传文件大小不能超过 8MB!');
return false;
}
if (extension !== 'xls' && extension !== 'xlsx') {
message.error('只能上传excel的文件');
return false;
}
let curFileList = [...fileList];
curFileList = curFileList.slice(-1);
productExcelList.value = curFileList;
return false;
};
const productExcelRemove = () => {
productExcelList.value = [];
};
const downLoad = () => {
window.open(config.VITE_GLOB_API_URL, '_blank');
};
let importLoading = ref(false);
const confirmImport = async () => {
if (!productExcelList.value.length) return message.error('请上传文件');
if (!impotrCheckboxValue.value.length) return message.error('请选择现货区域');
const param: FormData = new FormData();
param.append('ghsCode', ghsCode);
param.append('file', productExcelList.value[0]);
param.append('areaIds', impotrCheckboxValue.value.join(','));
importLoading.value = true;
const res = await regionalSpotManageUploadOpsProductApi(param);
if (res.code === 20000) {
message.success('批量导入成功');
} else {
message.error(res.message);
}
importLoading.value = false;
};
const importCancel = () => {
importVisible.value = false;
impotrCheckboxValue.value = [];
productExcelList.value = [];
};
// =====================批量导入 end=======================
const goTaskCenter = () => {
router.push({
path: '/taskCenter',
});
};
</script>
<template>
<div>
<div class="body-box">
<Form
:model="searchForm"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
class="top-search"
>
<Row :gutter="20">
<Col :xxl="4" :xl="6" :lg="8" :sm="12" :xs="24">
<FormItem label="品牌名称" name="brandList">
<!-- <Input v-model:value="searchForm.brandList" allow-clear placeholder="请输入品牌名称" /> -->
<a-select
v-model:value="searchForm.brandList"
show-search
mode="multiple"
placeholder="请输入品牌名称"
style="width: 100%"
:default-active-first-option="false"
:show-arrow="false"
:filter-option="false"
:not-found-content="null"
@search="handleSearch"
>
<a-select-option
v-for="item in searchBrandList"
:key="item.value"
:label="item.label"
:value="item.value"
>
{{ item.label }}
</a-select-option>
</a-select>
</FormItem>
</Col>
<Col :xxl="4" :xl="6" :lg="8" :sm="12" :xs="24">
<FormItem label="货号" name="goodsNo">
<Input v-model:value="searchForm.goodsNo" allow-clear placeholder="请输入货号" />
</FormItem>
</Col>
<Col :xxl="4" :xl="6" :lg="8" :sm="12" :xs="24">
<FormItem label="现货区域" name="areaIds">
<Select
v-model:value="searchForm.areaIds"
allowClear
mode="multiple"
placeholder="请选择现货区域"
style="width: 100%"
>
<SelectOption
v-for="(item, index) in areaIdsOption"
:key="index"
:value="item.value"
>{{ item.label }}</SelectOption
>
</Select>
</FormItem>
</Col>
<Col :xxl="4" :xl="6" :lg="8" :sm="12" :xs="24">
<FormItem label="商品分组" name="types">
<Select
v-model:value="searchForm.types"
allowClear
mode="multiple"
placeholder="请选择商品分组"
style="width: 100%"
>
<SelectOption
v-for="(item, index) in typesOption"
:key="index"
:value="item.value"
>{{ item.label }}</SelectOption
>
</Select>
</FormItem>
</Col>
<Col :span="24" style="display: flex; justify-content: space-between">
<div>
<Button type="primary" style="margin: 0 5px" @click="onSearch">查询</Button>
<Button style="margin: 0 5px" @click="onRset">重置</Button>
<Button type="primary" @click="addProduct" style="margin: 0 5px">新增商品</Button>
<Button type="primary" @click="batchImport" style="margin: 0 5px">批量导入</Button>
<Button type="primary" @click="batchDel" style="margin: 0 5px">批量删除</Button>
</div>
<Button @click="goTaskCenter" style="margin: 0 5px">任务中心日志</Button>
</Col>
</Row>
</Form>
<a-table
:data-source="list"
:loading="listLoading"
bordered
:pagination="pagination"
:rowKey="(record) => record.sysid"
:row-selection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
columnWidth: 65,
}"
style="margin-top: 15px"
>
<a-table-column title="商品名称" align="center" :width="100">
<template v-slot="{ record }">
{{ record.productName }}
</template>
</a-table-column>
<a-table-column title="品牌" align="center" :width="100">
<template v-slot="{ record }">
{{ record.brand }}
</template>
</a-table-column>
<a-table-column title="货号" align="center" :width="100">
<template v-slot="{ record }">
{{ record.goodsNo }}
</template>
</a-table-column>
<a-table-column title="规格" align="center" :width="100">
<template v-slot="{ record }">
{{ record.spec }}
</template>
</a-table-column>
<a-table-column title="当前现货区域" align="center" :width="100">
<template v-slot="{ record }">
<Button type="link" @click="viewCurrent(record)">查看区域现货</Button>
</template>
</a-table-column>
<a-table-column title="上架状态" align="center" :width="100">
<template v-slot="{ record }">
{{ record.productStatus }}
</template>
</a-table-column>
<a-table-column title="操作" align="center" :width="200">
<template #default="{ record }">
<Button type="link" @click="addArea(record)">增加区域</Button>
<Button type="link" style="margin-left: 5px" @click="del(record)">删除</Button>
</template>
</a-table-column>
</a-table>
</div>
<addProductModal v-if="showModal" @close="closeVisible" />
<a-modal
v-model:visible="visible"
title="商品可提供现货区域查看"
:width="600"
@ok="visible = false"
:footer="null"
:maskClosable="false"
okText="提交"
>
<div style="margin-top: -35px">商品名称:{{ curItem.productName }}</div>
<div>商品品牌:{{ curItem.brand }}</div>
<div>商品货号:{{ curItem.goodsNo }}</div>
<div>商品规格:{{ curItem.spec }}</div>
<a-table
:data-source="regionalSpotGoods"
bordered
:loading="loading1"
:pagination="false"
:rowKey="(record) => record.sysid"
style="margin-top: 15px"
>
<a-table-column title="区域" align="center" :width="100">
<template v-slot="{ record }"> {{ record.provinceName }}-{{ record.cityName }} </template>
</a-table-column>
<a-table-column title="添加时间" align="center" :width="100">
<template v-slot="{ record }">
{{ record.createTime }}
</template>
</a-table-column>
<a-table-column title="添加人" align="center" :width="100">
<template v-slot="{ record }">
{{ record.createName }}
</template>
</a-table-column>
</a-table>
</a-modal>
<!-- 删除 -->
<a-modal
v-model:visible="delVisible"
title="区域现货商品删除"
:width="650"
:maskClosable="false"
:keyboard="false"
@cancel="delVisibleCancel"
@ok="confirmDel"
:confirmLoading="delConfirLoading"
okText="提交"
>
<p
>您已选中 <span style="color: #1684fc">{{ deleteNum }}条</span> 商品</p
>
<a-spin v-if="delLoading" style="height: 150px; width: 100%; line-height: 150px" />
<p v-else
>选择需要删除的现货区域:
<a-radio-group v-model:value="radioValue">
<a-radio :value="1">全部区域</a-radio>
<a-radio :value="2">部分区域</a-radio>
</a-radio-group>
<a-checkbox-group
v-model:value="delCheckboxValue"
:disabled="radioValue === 1"
style="width: 100%; margin-top: 15px"
>
<a-row>
<a-col :span="6" v-for="(item, index) in delAreaList" :key="index">
<a-checkbox :value="item.id">{{ item.province }}-{{ item.city }}</a-checkbox>
</a-col>
</a-row>
</a-checkbox-group>
</p>
</a-modal>
<!-- 增加区域 -->
<a-modal
v-model:visible="addVisible"
title="现货商品增加区域"
:width="700"
:maskClosable="false"
@cancel="addVisibleCancel"
@ok="confirmAddArea"
okText="提交"
:confirmLoading="confirmAddLoading"
>
<div style="margin-top: -35px">商品名称:{{ curItem.productName }}</div>
<div>商品品牌:{{ curItem.brand }}</div>
<div>商品货号:{{ curItem.goodsNo }}</div>
<div>商品规格:{{ curItem.spec }}</div>
<p style="margin-top: 15px">选择可提供现货的区域:</p>
<a-checkbox-group v-model:value="addCheckboxValue" style="width: 100%">
<a-row>
<a-col :span="6" v-for="(item, index) in allAreaList" :key="index">
<a-checkbox :value="item.id" :disabled="item.disabled"
>{{ item.province }}-{{ item.city }}</a-checkbox
>
</a-col>
</a-row>
</a-checkbox-group>
</a-modal>
<!-- 批量导入 -->
<a-modal
v-model:visible="importVisible"
title="区域现货商品批量导入"
:width="700"
:maskClosable="false"
okText="提交"
@ok="confirmImport"
@cancel="importCancel"
:confirmLoading="importLoading"
>
<a-alert type="warning">
<template #message>
<span style="color: red">特别提醒:</span
>若商品之前已设置现货区域,则本次设置为在之前设置基础上新增。例如,原来商品设置为
北京市-直辖市;天津市-直辖市。本次设置为,北京市-直辖市;四川省-成都市。提交后,商品现货区域将更新为
北京市-直辖市;天津市-直辖市;四川省-成都市。
</template>
</a-alert>
<div style="margin-top: 15px; display: flex; align-items: center">
<span>上传商品文件:</span>
<a-upload
accept=".xls,.xlsx"
:file-list="productExcelList"
:before-upload="productExcelBeforeUpload"
@remove="productExcelRemove"
>
<a-button><upload-outlined />上传文件</a-button>
</a-upload>
<span style="margin-left: 15px">
下载
<a @click="downLoad">区域现货商品上传模板</a>
</span>
</div>
<p style="margin-top: 15px">选择现货区域:</p>
<a-checkbox-group v-model:value="impotrCheckboxValue" style="width: 100%">
<a-row>
<a-col :span="6" v-for="(item, index) in allAreaList" :key="index">
<a-checkbox :value="item.id" :disabled="item.disabled"
>{{ item.province }}-{{ item.city }}</a-checkbox
>
</a-col>
</a-row>
</a-checkbox-group>
</a-modal>
</div>
</template>
<style lang="less" scoped>
.body-box {
.top-search {
margin-top: 15px;
}
}
</style>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import {
Form,
FormItem,
Input,
Button,
Select,
SelectOption,
Row,
Col,
message,
} from 'ant-design-vue';
import { UploadOutlined } from '@ant-design/icons-vue';
import { useRouter } from 'vue-router';
import { getAuthCache } from '/@/utils/auth';
import {
regionalSpotManageBrandListApi,
regionalSpotManageGroupListApi,
regionalSpotManageListApi,
regionalSpotManageGetAreaListApi,
regionalSpotManageGetGhsAreaListApi,
regionalSpotManageOpsDeleteProductApi,
regionalSpotManageOpsEditProductApi,
regionalSpotManageUploadOpsProductApi,
} from '/@/api/regionalSpotManage';
import addProductModal from './addProduct.vue';
const config = import.meta.env;
const userInfo: any = getAuthCache('USER__INFO__');
const ghsCode = userInfo.supplier.ghsCode;
const ghsName = userInfo.supplier.ghsName;
const router = useRouter();
const list = ref<any[]>([]);
onMounted(async () => {
getList();
getAllAreaList();
getGroupOption();
});
const searchForm = ref<{
brands: any;
goodsNo: any;
areaIds: any;
types: any;
}>({
brands: [],
goodsNo: '',
areaIds: [],
types: [],
});
interface AreaIds {
city?: string;
cityId?: number;
creationTime?: string;
creator?: string;
id?: number;
province?: string;
provinceId?: number;
}
const areaIdsOption = ref<AreaIds[]>([]);
const typesOption = ref([]);
const searchBrandList = ref<any[]>([]);
const handleSearch = async (value) => {
const res = await regionalSpotManageBrandListApi({ brand: value });
if (res.success) {
searchBrandList.value = res.data;
} else {
searchBrandList.value = [];
}
};
const listLoading = ref(false);
const pagination = ref({
pageSize: 10,
current: 1,
total: 0,
showTotal: (total) => `共 ${total} 条`,
hideOnSinglePage: false,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '30', '50', '100'],
onChange: (current) => {
pagination.value.current = current;
getList();
},
onShowSizeChange: (size) => {
pagination.value.pageSize = size;
getList();
},
});
const getList = async () => {
const pager = ref({
pageIndex: 1,
pageSize: 10,
});
const param = ref({
...searchForm.value,
...pager.value,
});
param.value.areaIds = param.value.areaIds ? param.value.areaIds : [];
param.value.types = param.value.types ? param.value.types : [];
listLoading.value = true;
const res = await regionalSpotManageListApi(param.value);
if (res.success) {
list.value = res.data;
pagination.value.total = res.data[0].total;
} else {
list.value = [];
pagination.value.total = 0;
}
listLoading.value = false;
};
const onRset = () => {
searchForm.value.brands = [];
searchForm.value.goodsNo = '';
searchForm.value.areaIds = [];
searchForm.value.types = [];
getList();
};
const onSearch = () => {
pagination.value.current = 1;
getList();
};
const showModal = ref(false);
const addProduct = () => {
showModal.value = true;
};
// 关闭新增商品弹窗
const closeVisible = (val, action) => {
showModal.value = val;
if (action) {
onSearch();
}
};
const curItem = ref<{ [key: string]: any }>({});
// =========查看区域现货 statr ===========
const loading1 = ref(false);
const visible = ref(false);
const regionalSpotGoods = ref([]);
const viewCurrent = async (val) => {
curItem.value = val;
visible.value = true;
const param = ref<{ [key: string]: any }>({
products: [
{
goodsNo: val.goodsNo,
brand: val.brand,
spec: val.spec,
ghscode: ghsCode,
},
],
});
loading1.value = true;
const result = await getAreaList(param.value);
regionalSpotGoods.value = result;
loading1.value = false;
};
const getAreaList = async (param) => {
const res = await regionalSpotManageGetGhsAreaListApi(param);
if (res.success) {
return res.data;
} else {
return [];
}
};
// ==========查看区域现货 end =============
const selectedRowKeys = ref([]);
const selectedRows = ref<any[]>([]);
const onSelectChange = (Keys, Rows) => {
selectedRowKeys.value = Keys;
selectedRows.value = Rows;
};
// ===============增加区域 start=======================
const addVisible = ref(false);
const addAreaLoading = ref(false);
const addCheckboxValue = ref<number[]>([]);
const addArea = async (row) => {
curItem.value = row;
addVisible.value = true;
addAreaLoading.value = true;
const param = ref<{ [key: string]: any }>({
products: [
{
goodsNo: row.goodsNo,
brand: row.brand,
spec: row.spec,
ghscode: ghsCode,
},
],
});
const result = await getAreaList(param.value);
delAreaList.value = result;
const curArr = delAreaList.value.map((it) => it.cityCode);
for (const k of allAreaList.value) {
if (curArr.includes(k.cityId)) {
addCheckboxValue.value.push(k.cityId);
k.disabled = true;
}
}
addAreaLoading.value = false;
};
const addVisibleCancel = () => {
addVisible.value = false;
addCheckboxValue.value = [];
};
const confirmAddLoading = ref(false);
const confirmAddArea = async () => {
const param = ref<{ [key: string]: any }>({
products: [
{
goodsNo: curItem.value.goodsNo,
brand: curItem.value.brand,
spec: curItem.value.spec,
ghscode: ghsCode,
},
],
areas: addCheckboxValue.value,
});
confirmAddLoading.value = true;
const res = await regionalSpotManageOpsEditProductApi(param.value);
if (res.success) {
message.success('添加区域成功');
addVisibleCancel();
} else {
message.error(res.message);
}
confirmAddLoading.value = false;
};
// ===============增加区域 end=======================
// ================区域现货商品删除 start=====================
const delVisible = ref(false);
const delLoading = ref(false);
const deleteNum = ref(0);
const radioValue = ref(1);
const delAreaList = ref<any[]>([]); //已添加的区域
const delCheckboxValue = ref([]);
const del = async (val) => {
curItem.value = val;
deleteNum.value = 1;
delVisible.value = true;
const param = ref<{ [key: string]: any }>({
products: [
{
goodsNo: val.goodsNo,
brand: val.brand,
spec: val.spec,
ghscode: ghsCode,
},
],
});
delLoading.value = true;
const res = await getAreaList(param.value);
if (res) {
delAreaList.value = res;
}
delLoading.value = false;
};
const delVisibleCancel = () => {
delVisible.value = false;
deleteNum.value = 0;
radioValue.value = 1;
delCheckboxValue.value = [];
isBatchDel.value = false;
};
const delConfirLoading = ref(false);
const confirmDel = async () => {
if (!delAreaList.value.length) return message.error('暂无可删除区域');
if (radioValue.value === 2 && !delCheckboxValue.value.length)
return message.error('请选择需要删除的现货区域');
const param = ref<{ [key: string]: any }>({
products: [],
areas: '',
isAll: false,
});
if (isBatchDel.value) {
param.value.products = selectedRows.value.map((v) => {
return {
goodsNo: v.goodsNo,
brand: v.brand,
spec: v.spec,
ghscode: ghsCode,
};
});
} else {
param.value.products = [
{
goodsNo: curItem.value.goodsNo,
brand: curItem.value.brand,
spec: curItem.value.spec,
ghscode: ghsCode,
},
];
}
if (radioValue.value === 1) {
param.value.isAll = true;
param.value.areas = delAreaList.value.map((v) => v.cityCode);
} else if (radioValue.value === 2) {
param.value.areas = delCheckboxValue.value;
}
delConfirLoading.value = true;
const res = await regionalSpotManageOpsDeleteProductApi(param.value);
if (res.success) {
message.success('删除成功');
} else {
message.success(res.message);
}
delConfirLoading.value = false;
};
// 批量删除
const isBatchDel = ref(false);
const batchDel = async () => {
if (!selectedRowKeys.value.length) return message.error('请勾选商品');
isBatchDel.value = true;
deleteNum.value = selectedRows.value.length;
delVisible.value = true;
const param = ref<{ [key: string]: any }>({
products: [],
});
param.value.products = selectedRows.value.map((v) => {
return {
goodsNo: v.goodsNo,
brand: v.brand,
spec: v.spec,
ghscode: ghsCode,
};
});
delLoading.value = true;
const res = await getAreaList(param.value);
if (res.success) {
delAreaList.value = res.data;
}
delLoading.value = false;
};
// ================区域现货商品删除 end=====================
const allAreaList = ref<any[]>([]);
const getAllAreaList = async () => {
const res = await regionalSpotManageGetAreaListApi({});
if (res.success) {
allAreaList.value = res.data;
areaIdsOption.value = JSON.parse(JSON.stringify(res.data));
} else {
allAreaList.value = [];
}
};
const getGroupOption = async () => {
const res = await regionalSpotManageGroupListApi({});
if (res.success) {
typesOption.value = res.data;
} else {
typesOption.value = [];
}
};
// =====================批量导入 start=======================
const productExcelList = ref<any[]>([]);
const importVisible = ref(false);
const impotrCheckboxValue = ref<any[]>([]);
const batchImport = () => {
importVisible.value = true;
allAreaList.value.forEach((v) => {
v.disabled = false;
});
};
const productExcelBeforeUpload = (file, fileList) => {
const isLt8M = file.size / 1024 / 1024 <= 8;
const extension = file.name.substring(file.name.lastIndexOf('.') + 1);
if (!isLt8M) {
message.error('上传文件大小不能超过 8MB!');
return false;
}
if (extension !== 'xls' && extension !== 'xlsx') {
message.error('只能上传excel的文件');
return false;
}
let curFileList = [...fileList];
curFileList = curFileList.slice(-1);
productExcelList.value = curFileList;
return false;
};
const productExcelRemove = () => {
productExcelList.value = [];
};
const downLoad = () => {
window.open(
config.VITE_GLOB_TMALLAB_URL + '/system/resources/区域现货商品上传模板.xlsx',
'_blank',
);
};
let importLoading = ref(false);
const confirmImport = async () => {
if (!productExcelList.value.length) return message.error('请上传文件');
if (!impotrCheckboxValue.value.length) return message.error('请选择现货区域');
// const param: FormData = new FormData();
// param.append('ghsCode', ghsCode);
// param.append('ghsName', ghsName);
// param.append('file', productExcelList.value[0]);
// param.append('areaIds', impotrCheckboxValue.value.join(',') as any);
importLoading.value = true;
const res: any = await regionalSpotManageUploadOpsProductApi(
{
ghsCode: ghsCode,
ghsName: ghsName,
areaIds: impotrCheckboxValue.value,
},
productExcelList.value[0],
);
if (res.data.success) {
message.success('批量导入成功');
importCancel();
} else {
message.error(res.data.message);
}
importLoading.value = false;
};
const importCancel = () => {
importVisible.value = false;
impotrCheckboxValue.value = [];
productExcelList.value = [];
};
// =====================批量导入 end=======================
const goTaskCenter = () => {
router.push({
path: '/product/taskCenter',
});
};
</script>
<template>
<div>
<div class="body-box">
<Form
:model="searchForm"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
class="top-search"
>
<Row :gutter="20">
<Col :xxl="4" :xl="6" :lg="8" :sm="12" :xs="24">
<FormItem label="品牌名称" name="brandList">
<!-- <Input v-model:value="searchForm.brands" allow-clear placeholder="请输入品牌名称" /> -->
<a-select
v-model:value="searchForm.brands"
show-search
mode="multiple"
placeholder="请输入品牌名称"
style="width: 100%"
:default-active-first-option="false"
:show-arrow="false"
:filter-option="false"
:not-found-content="null"
:maxTagCount="1"
@search="handleSearch"
>
<a-select-option
v-for="item in searchBrandList"
:key="item.brand"
:label="item.brand"
:value="item.brand"
>
{{ item.brand }}
</a-select-option>
</a-select>
</FormItem>
</Col>
<Col :xxl="4" :xl="6" :lg="8" :sm="12" :xs="24">
<FormItem label="货号" name="goodsNo">
<Input v-model:value="searchForm.goodsNo" allow-clear placeholder="请输入货号" />
</FormItem>
</Col>
<Col :xxl="4" :xl="6" :lg="8" :sm="12" :xs="24">
<FormItem label="现货区域" name="areaIds">
<Select
v-model:value="searchForm.areaIds"
allowClear
mode="multiple"
placeholder="请选择现货区域"
:maxTagCount="1"
style="width: 100%"
>
<SelectOption
v-for="(item, index) in areaIdsOption"
:key="index"
:value="item.cityId"
>{{ item.province }}-{{ item.city }}</SelectOption
>
</Select>
</FormItem>
</Col>
<Col :xxl="4" :xl="6" :lg="8" :sm="12" :xs="24">
<FormItem label="商品分组" name="types">
<Select
v-model:value="searchForm.types"
allowClear
mode="multiple"
placeholder="请选择商品分组"
:maxTagCount="1"
style="width: 100%"
>
<SelectOption v-for="(item, index) in typesOption" :key="index" :value="item">{{
item
}}</SelectOption>
</Select>
</FormItem>
</Col>
<Col :span="24" style="display: flex; justify-content: space-between">
<div>
<Button type="primary" style="margin: 0 5px" @click="onSearch">查询</Button>
<Button style="margin: 0 5px" @click="onRset">重置</Button>
<Button type="primary" @click="addProduct" style="margin: 0 5px">新增商品</Button>
<Button type="primary" @click="batchImport" style="margin: 0 5px">批量导入</Button>
<Button type="primary" @click="batchDel" style="margin: 0 5px">批量删除</Button>
</div>
<Button @click="goTaskCenter" style="margin: 0 5px">任务中心日志</Button>
</Col>
</Row>
</Form>
<a-table
:data-source="list"
:loading="listLoading"
bordered
:pagination="pagination"
:rowKey="(record) => record.brand + record.goodsNo + record.spec"
:row-selection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
columnWidth: 65,
}"
style="margin-top: 15px"
>
<a-table-column title="商品名称" align="center" :width="100">
<template #default="{ record }">
{{ record.productName }}
</template>
</a-table-column>
<a-table-column title="品牌" align="center" :width="100">
<template #default="{ record }">
{{ record.brand }}
</template>
</a-table-column>
<a-table-column title="货号" align="center" :width="100">
<template #default="{ record }">
{{ record.goodsNo }}
</template>
</a-table-column>
<a-table-column title="规格" align="center" :width="100">
<template #default="{ record }">
{{ record.spec }}
</template>
</a-table-column>
<a-table-column title="当前现货区域" align="center" :width="100">
<template #default="{ record }">
<Button type="link" @click="viewCurrent(record)">查看区域现货</Button>
</template>
</a-table-column>
<a-table-column title="上架状态" align="center" :width="100">
<template #default="{ record }">
{{ record.productStatus }}
</template>
</a-table-column>
<a-table-column title="操作" align="center" :width="200">
<template #default="{ record }">
<Button type="link" @click="addArea(record)">增加区域</Button>
<Button type="link" style="margin-left: 5px" @click="del(record)">删除</Button>
</template>
</a-table-column>
</a-table>
</div>
<addProductModal v-if="showModal" @close="closeVisible" />
<a-modal
v-model:visible="visible"
title="商品可提供现货区域查看"
:width="600"
@ok="visible = false"
:footer="null"
:maskClosable="false"
okText="提交"
>
<div>商品名称:{{ curItem.productName }}</div>
<div>商品品牌:{{ curItem.brand }}</div>
<div>商品货号:{{ curItem.goodsNo }}</div>
<div>商品规格:{{ curItem.spec }}</div>
<a-table
:data-source="regionalSpotGoods"
bordered
:loading="loading1"
:pagination="false"
:rowKey="(record) => record.sysid"
style="margin-top: 15px"
>
<a-table-column title="区域" align="center" :width="100">
<template #default="{ record }">{{ record.provinceName }}-{{ record.cityName }}</template>
</a-table-column>
<a-table-column title="添加时间" align="center" :width="100">
<template #default="{ record }">
{{ record.createTime }}
</template>
</a-table-column>
<a-table-column title="添加人" align="center" :width="100">
<template #default="{ record }">
{{ record.createName }}
</template>
</a-table-column>
</a-table>
</a-modal>
<!-- 删除 -->
<a-modal
v-model:visible="delVisible"
title="区域现货商品删除"
:width="650"
:maskClosable="false"
:keyboard="false"
@cancel="delVisibleCancel"
@ok="confirmDel"
:confirmLoading="delConfirLoading"
okText="提交"
>
<p
>您已选中 <span style="color: #1684fc">{{ deleteNum }}条</span> 商品</p
>
<a-spin v-if="delLoading" style="height: 150px; width: 100%; line-height: 150px" />
<p v-else
>选择需要删除的现货区域:
<a-radio-group v-model:value="radioValue">
<a-radio :value="1">全部区域</a-radio>
<a-radio :value="2">部分区域</a-radio>
</a-radio-group>
<a-checkbox-group
v-model:value="delCheckboxValue"
:disabled="radioValue === 1"
style="width: 100%; margin-top: 15px"
>
<a-row>
<a-col :span="6" v-for="(item, index) in delAreaList" :key="index">
<a-checkbox :value="item.cityCode"
>{{ item.provinceName }}-{{ item.cityName }}</a-checkbox
>
</a-col>
</a-row>
</a-checkbox-group>
</p>
</a-modal>
<!-- 增加区域 -->
<a-modal
v-model:visible="addVisible"
title="现货商品增加区域"
:width="700"
:maskClosable="false"
@cancel="addVisibleCancel"
@ok="confirmAddArea"
okText="提交"
:confirmLoading="confirmAddLoading"
>
<div>商品名称:{{ curItem.productName }}</div>
<div>商品品牌:{{ curItem.brand }}</div>
<div>商品货号:{{ curItem.goodsNo }}</div>
<div>商品规格:{{ curItem.spec }}</div>
<p style="margin-top: 15px">选择可提供现货的区域:</p>
<a-checkbox-group v-model:value="addCheckboxValue" style="width: 100%">
<a-row>
<a-col :span="6" v-for="(item, index) in allAreaList" :key="index">
<a-checkbox :value="item.cityId" :disabled="item.disabled"
>{{ item.province }}-{{ item.city }}</a-checkbox
>
</a-col>
</a-row>
</a-checkbox-group>
</a-modal>
<!-- 批量导入 -->
<a-modal
v-model:visible="importVisible"
title="区域现货商品批量导入"
:width="700"
:maskClosable="false"
okText="提交"
@ok="confirmImport"
@cancel="importCancel"
:confirmLoading="importLoading"
>
<a-alert type="warning">
<template #message>
<span style="color: red">特别提醒:</span
>若商品之前已设置现货区域,则本次设置为在之前设置基础上新增。例如,原来商品设置为
北京市-直辖市;天津市-直辖市。本次设置为,北京市-直辖市;四川省-成都市。提交后,商品现货区域将更新为
北京市-直辖市;天津市-直辖市;四川省-成都市。
</template>
</a-alert>
<div style="margin-top: 15px; display: flex; align-items: center">
<span>上传商品文件:</span>
<a-upload
accept=".xls,.xlsx"
:file-list="productExcelList"
:before-upload="productExcelBeforeUpload"
@remove="productExcelRemove"
>
<a-button><upload-outlined />上传文件</a-button>
</a-upload>
<span style="margin-left: 15px">
下载
<a @click="downLoad">区域现货商品上传模板</a>
</span>
</div>
<p style="margin-top: 15px">选择现货区域:</p>
<a-checkbox-group v-model:value="impotrCheckboxValue" style="width: 100%">
<a-row>
<a-col :span="6" v-for="(item, index) in allAreaList" :key="index">
<a-checkbox :value="item.cityId" :disabled="item.disabled"
>{{ item.province }}-{{ item.city }}</a-checkbox
>
</a-col>
</a-row>
</a-checkbox-group>
</a-modal>
</div>
</template>
<style lang="less" scoped>
.body-box {
.top-search {
margin-top: 15px;
}
}
</style>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import {
platformProBatchGetListApi,
platformProBatchGetDetailApi
} from '/@/api/regionalSpotManage';
import { message } from 'ant-design-vue';
onMounted(async () => {
getList()
});
let list = ref<any[]>([
{
createTime: '2024/12/12 12:22:22',
operateModule: '平台商品管理-议价商品',
type: '批量导入议价商品',
operateNum: 8882,
successNum: 8882,
failNum: 0,
operateName: '赵欣雨'
}
])
let listLoading = ref(false)
const pagination = ref({
pageSize: 10,
current: 1,
total: 0,
showTotal: total => `共 ${total} 条`,
hideOnSinglePage: false,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '30', '50', '100'],
onChange: (current) => {
pagination.value.current = current
getList()
},
onShowSizeChange: (size) => {
pagination.value.pageSize = size
getList()
}
})
const search = () => {
pagination.value.current = 1
getList()
}
const getList = async () => {
const param = ref<{ [key: string]: any }>({
currentPage: pagination.value.current,
pageSize: pagination.value.pageSize
})
listLoading.value = true
const res = await platformProBatchGetListApi(param)
if (res.code === 20000) {
list.value = res.data
pagination.value.total = res.data[0].total
} else {
list.value = []
pagination.value.total = 0
}
listLoading.value = false
}
let curItem = ref<{ [key: string]: any }>({});
let visible = ref(false)
let operationList = ref<any[]>([])
let detailLoading = ref(false)
const viewRecord = (item) => {
curItem.value = item
visible.value = true
getDetails(item)
}
const getDetails = async (item) => {
const param = ref<{ [key: string]: any }>({
sysid: item.sysid,
type: ''
})
detailLoading.value = true
const res = await platformProBatchGetDetailApi(param)
if (res.code === 20000) {
operationList.value = res.data
} else {
operationList.value = []
}
detailLoading.value = false
}
// =================导出========================
let exportLoading = ref(false)
const exportExcel = async () => {
handleDownload([
{
"brand": "生工",
"category": "",
"createTime": "2024-03-29 14:42:35",
"discount": null,
"expirationDate": null,
"failReason": "该商品在商品目录不存在;",
"identificationType": "商品议价",
"itemNo": "G508013-0001",
"negotiationPrice": 5000,
"operateSysid": 13877,
"platforms": [
"北京协和医院"
],
"productName": "微孔板迷你离心机,500~3000 rpm",
"spec": "1 /PK",
"status": false,
"sysid": 83466873,
"total": 32,
"type": 2
}
])
const param = ref<{ [key: string]: any }>({
sysid: curItem.value.sysid,
type: ''
})
exportLoading.value = true
const res = await platformProBatchGetDetailApi(param)
if (res.code === 20000) {
handleDownload(res.data)
} else {
message.error('暂无数据')
}
exportLoading.value = false
}
const handleDownload = (list) => {
import('/@/vendor/Export2Excel').then(excel => {
let tHeader = ['商品名称', '品牌', '货号', '包装规格', '平台', '状态', '失败原因', '执行时间']
let filterVal = ['productName', 'brand', 'itemNo', 'spec', 'platforms', 'status', 'failReason', 'createTime']
list.forEach(item => {
if(item.status) {
item.status = '成功'
} else {
item.status = '失败'
}
if(item.platforms) {
item.platforms = item.platforms.join(',')
} else {
item.platforms = ''
}
});
const data = formatJson(filterVal, list)
excel.export_json_to_excel({
header: tHeader as any,
data: data as any,
filename: '操作记录详情' as any,
autoWidth: true as any,
bookType: 'xlsx' as any,
XlsWidth: null as any,
searchList: [] as any
})
})
}
const formatJson = (filterVal, jsonData) => {
return jsonData.map(v => filterVal.map(j => {
return v[j]
}))
}
</script>
<template>
<div>
<a-button @click="search" type="primary">刷新数据</a-button>
</div>
<a-table
:data-source="list"
:loading="listLoading"
:pagination="pagination"
bordered
:rowKey="(record) => record.sysid"
style="margin-top: 15px"
>
<a-table-column title="操作时间" align="center" :width="100">
<template v-slot="{record}">
{{ record.createTime }}
</template>
</a-table-column>
<a-table-column title="功能模块" align="center" :width="100">
<template v-slot="{record}">
{{ record.operateModule }}
</template>
</a-table-column>
<a-table-column title="类型" align="center" :width="100">
<template v-slot="{record}">
{{ record.type }}
</template>
</a-table-column>
<a-table-column title="操作数量" align="center" :width="100">
<template v-slot="{record}">
<a-button v-if="record.operateNum" type="link" @click="viewRecord(record)">{{ record.operateNum }}</a-button>
<span v-else>/</span>
</template>
</a-table-column>
<a-table-column title="解析成功数量" align="center" :width="100">
<template v-slot="{record}">
<span v-if="record.successNum">{{ record.successNum }}</span>
<span v-else>/</span>
</template>
</a-table-column>
<a-table-column title="解析失败数量" align="center" :width="100">
<template v-slot="{record}">
<span v-if="record.failNum">{{ record.failNum }}</span>
<span v-else>/</span>
</template>
</a-table-column>
<a-table-column title="操作人" align="center" :width="100">
<template v-slot="{record}">
{{ record.operateName }}
</template>
</a-table-column>
</a-table>
<a-modal v-model:visible="visible" title="操作记录详情" :width="1200" :maskClosable="false" :keyboard="false">
<template #footer>
<a-button type="primary" :loading="exportLoading" @click="exportExcel">导出数据</a-button>
</template>
<a-table
:data-source="operationList"
:loading="detailLoading"
bordered
:rowKey="(record) => record.sysid"
style="margin-top: -15px"
>
<a-table-column title="商品名称" align="center" :width="100">
<template v-slot="{record}">
{{ record.productName }}
</template>
</a-table-column>
<a-table-column title="品牌" align="center" :width="100">
<template v-slot="{record}">
{{ record.brand }}
</template>
</a-table-column>
<a-table-column title="货号" align="center" :width="100">
<template v-slot="{record}">
{{ record.itemNo }}
</template>
</a-table-column>
<a-table-column title="包装规格" align="center" :width="100">
<template v-slot="{record}">
{{ record.spec }}
</template>
</a-table-column>
<a-table-column title="平台" align="center" :width="150">
<template v-slot="{record}">
<span v-if="record.platforms && record.platforms.length > 1" :title="record.platforms.join(',')">{{ record.platforms[0] + '...' }}</span>
<span v-else>{{ record.platforms ? record.platforms[0] : '' }}</span>
</template>
</a-table-column>
<a-table-column title="状态" align="center" :width="100">
<template v-slot="{record}">
{{ record.status ? '成功' : '失败' }}
</template>
</a-table-column>
<a-table-column title="失败原因" :width="150">
<template v-slot="{record}">
<span class="opinionClass" :title="record.failReason">{{ record.failReason }}</span>
</template>
</a-table-column>
<a-table-column title="执行时间" align="center" :width="100">
<template v-slot="{record}">
{{ record.createTime }}
</template>
</a-table-column>
</a-table>
</a-modal>
</template>
<style lang="less" scoped>
.opinionClass {
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
</style>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import {
platformProBatchGetListApi,
platformProBatchGetDetailApi,
} from '/@/api/regionalSpotManage';
import { message } from 'ant-design-vue';
onMounted(async () => {
getList();
});
let list = ref<any[]>([]);
let listLoading = ref(false);
const pagination = ref({
pageSize: 10,
current: 1,
total: 0,
showTotal: (total) => `共 ${total} 条`,
hideOnSinglePage: false,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: ['10', '20', '30', '50', '100'],
onChange: (current) => {
pagination.value.current = current;
getList();
},
onShowSizeChange: (size) => {
pagination.value.pageSize = size;
getList();
},
});
const search = () => {
pagination.value.current = 1;
getList();
};
const getList = async () => {
const param = ref<{ [key: string]: any }>({
currentPage: pagination.value.current,
pageSize: pagination.value.pageSize,
});
listLoading.value = true;
const res = await platformProBatchGetListApi(param.value);
if (res.success) {
list.value = res.data;
pagination.value.total = res.data[0].total;
} else {
list.value = [];
pagination.value.total = 0;
}
listLoading.value = false;
};
let curItem = ref<{ [key: string]: any }>({});
let visible = ref(false);
let operationList = ref<any[]>([]);
let detailLoading = ref(false);
const viewRecord = (item) => {
curItem.value = item;
visible.value = true;
getDetails(item);
};
const getDetails = async (item) => {
const param = ref<{ [key: string]: any }>({
currentPage: 1,
pageSize: 10,
sysid: item.sysid,
type: '',
});
detailLoading.value = true;
const res = await platformProBatchGetDetailApi(param.value);
if (res.success) {
operationList.value = res.data;
} else {
operationList.value = [];
}
detailLoading.value = false;
};
// =================导出========================
let exportLoading = ref(false);
const exportExcel = async () => {
const param = ref<{ [key: string]: any }>({
sysid: curItem.value.sysid,
type: '',
});
exportLoading.value = true;
const res = await platformProBatchGetDetailApi(param.value);
if (res.success) {
handleDownload(res.data);
} else {
message.error('暂无数据');
}
exportLoading.value = false;
};
const handleDownload = (list) => {
import('/@/vendor/Export2Excel').then((excel) => {
let tHeader = [
'商品名称',
'品牌',
'货号',
'包装规格',
'平台',
'状态',
'失败原因',
'执行时间',
];
let filterVal = [
'productName',
'brand',
'itemNo',
'spec',
'platforms',
'status',
'failReason',
'createTime',
];
list.forEach((item) => {
if (item.status) {
item.status = '成功';
} else {
item.status = '失败';
}
if (item.platforms) {
item.platforms = item.platforms.join(',');
} else {
item.platforms = '';
}
});
const data = formatJson(filterVal, list);
excel.export_json_to_excel({
header: tHeader,
data: data,
filename: '操作记录详情',
autoWidth: false,
bookType: 'xlsx',
XlsWidth: [],
searchList: null,
});
});
};
const formatJson = (filterVal, jsonData) => {
return jsonData.map((v) =>
filterVal.map((j) => {
return v[j];
}),
);
};
</script>
<template>
<div>
<a-button @click="search" type="primary">刷新数据</a-button>
</div>
<a-table
:data-source="list"
:loading="listLoading"
:pagination="pagination"
bordered
:rowKey="(record) => record.sysid"
style="margin-top: 15px"
>
<a-table-column title="操作时间" align="center" :width="100">
<template #default="{ record }">
{{ record.createTime }}
</template>
</a-table-column>
<a-table-column title="功能模块" align="center" :width="100">
<template #default="{ record }">
{{ record.operateModule }}
</template>
</a-table-column>
<a-table-column title="类型" align="center" :width="100">
<template #default="{ record }">
{{ record.type }}
</template>
</a-table-column>
<a-table-column title="操作数量" align="center" :width="100">
<template #default="{ record }">
<a-button v-if="record.operateNum" type="link" @click="viewRecord(record)">{{
record.operateNum
}}</a-button>
<span v-else>/</span>
</template>
</a-table-column>
<a-table-column title="解析成功数量" align="center" :width="100">
<template #default="{ record }">
<span v-if="record.successNum">{{ record.successNum }}</span>
<span v-else>/</span>
</template>
</a-table-column>
<a-table-column title="解析失败数量" align="center" :width="100">
<template #default="{ record }">
<span v-if="record.failNum">{{ record.failNum }}</span>
<span v-else>/</span>
</template>
</a-table-column>
<a-table-column title="操作人" align="center" :width="100">
<template #default="{ record }">
{{ record.operateName }}
</template>
</a-table-column>
</a-table>
<a-modal
v-model:visible="visible"
title="操作记录详情"
:width="1200"
:maskClosable="false"
:keyboard="false"
>
<template #footer>
<a-button type="primary" :loading="exportLoading" @click="exportExcel">导出数据</a-button>
</template>
<a-table
:data-source="operationList"
:loading="detailLoading"
bordered
:rowKey="(record) => record.sysid"
>
<a-table-column title="商品名称" align="center" :width="100">
<template #default="{ record }">
{{ record.productName }}
</template>
</a-table-column>
<a-table-column title="品牌" align="center" :width="100">
<template #default="{ record }">
{{ record.brand }}
</template>
</a-table-column>
<a-table-column title="货号" align="center" :width="100">
<template #default="{ record }">
{{ record.itemNo }}
</template>
</a-table-column>
<a-table-column title="包装规格" align="center" :width="100">
<template #default="{ record }">
{{ record.spec }}
</template>
</a-table-column>
<a-table-column title="平台" align="center" :width="150">
<template #default="{ record }">
<span
v-if="record.platforms && record.platforms.length > 1"
:title="record.platforms.join(',')"
>{{ record.platforms[0] + '...' }}</span
>
<span v-else>{{ record.platforms ? record.platforms[0] : '' }}</span>
</template>
</a-table-column>
<a-table-column title="状态" align="center" :width="100">
<template #default="{ record }">
{{ record.status ? '成功' : '失败' }}
</template>
</a-table-column>
<a-table-column title="失败原因" :width="150">
<template #default="{ record }">
<span class="opinionClass" :title="record.failReason">{{ record.failReason }}</span>
</template>
</a-table-column>
<a-table-column title="执行时间" align="center" :width="100">
<template #default="{ record }">
{{ record.createTime }}
</template>
</a-table-column>
</a-table>
</a-modal>
</template>
<style lang="less" scoped>
.opinionClass {
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
</style>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import { message } from 'ant-design-vue';
const config = import.meta.env;
import {
taskCenterQueryListApi,
taskCenterRevokeExcelUploadApi,
} from '/@/api/regionalSpotManage';
onMounted(async () => {
getList();
});
let list = ref<any[]>([]);
let listLoading = ref(false);
const downLoad = (url) => {
window.open(config.VITE_GLOB_API_URL + '/system/excelFile/' + url, '_blank');
};
const downloadFail = (record) => {
if (record.failNum === 0) return;
let href =
config.VITE_GLOB_API_URL +
'/excel/excelNew/fail/download?sysid=' +
record.sysid +
'&type=' +
record.type.slice(2, 6);
window.open(href, 'blank');
};
const cancel = async (record) => {
const param = ref<{ [key: string]: any }>({
sysid: record.sysid,
});
const res = await taskCenterRevokeExcelUploadApi(param.value);
if (res.code === 20000) {
message.success('操作成功');
getList();
} else {
message.error(res.message);
}
};
const getList = async () => {
listLoading.value = true;
const res = await taskCenterQueryListApi({ type: 0 });
if (res.code === 20000) {
list.value = res.data;
} else {
list.value = [];
}
listLoading.value = false;
};
</script>
<template>
<div>
<a-button @click="getList" type="primary">刷新数据</a-button>
</div>
<a-table
:data-source="list"
:loading="listLoading"
bordered
:rowKey="(record) => record.sysid"
style="margin-top: 15px"
>
<a-table-column title="操作时间" align="center" :width="100">
<template #default="{ record }">
{{ record.createTime }}
</template>
</a-table-column>
<a-table-column title="类型" align="center" :width="100">
<template #default="{ record }">
{{ record.type }}
</template>
</a-table-column>
<a-table-column title="状态" align="center" :width="100">
<template #default="{ record }">
<p>{{
record.isRevoke
? '已撤销'
: record.status == 0
? '待进行'
: record.status == 1
? '进行中'
: '已完成'
}}</p>
</template>
</a-table-column>
<a-table-column title="操作数据" align="center" :width="100">
<template #default="{ record }">
{{ record.sproductNumpec }}
</template>
</a-table-column>
<a-table-column title="成功数据" align="center" :width="100">
<template #default="{ record }">
{{ record.successNum }}
</template>
</a-table-column>
<a-table-column title="错误数据" align="center" :width="100">
<template #default="{ record }">
{{ record.failNum }}
</template>
</a-table-column>
<a-table-column title="操作人" align="center" :width="100">
<template #default="{ record }">
{{ record.createName }}
</template>
</a-table-column>
<a-table-column title="操作" align="center" :width="200">
<template #default="{ record }">
<Button type="link" @click="downLoad(record.fileUrl)">下载源文件</Button>
<Button type="link" v-if="record.failNum" @click="downloadFail(record)"
>下载错误数据</Button
>
<Button type="link" v-if="record.status == 0 && !record.isRevoke" @click="cancel(record)"
>撤销</Button
>
</template>
</a-table-column>
</a-table>
</template>
<style lang="less" scoped></style>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import { message } from 'ant-design-vue';
const config = import.meta.env;
import {
taskCenterQueryListApi,
taskCenterRevokeExcelUploadApi,
} from '/@/api/regionalSpotManage';
onMounted(async () => {
getList();
});
let list = ref<any[]>([]);
let listLoading = ref(false);
const downLoad = (url) => {
window.open(config.VITE_GLOB_TMALLAB_URL + '/system/excelFile/' + url, '_blank');
};
const downloadFail = (record) => {
if (record.failNum === 0) return;
let href =
config.VITE_GLOB_TMALLAB_URL +
'/excel/excelNew/fail/download?sysid=' +
record.sysid +
'&type=' +
record.type.slice(2, 6);
window.open(href, 'blank');
};
const cancel = async (record) => {
const param = ref<{ [key: string]: any }>({
sysid: record.sysid,
});
const res = await taskCenterRevokeExcelUploadApi(param.value);
if (res.success) {
message.success('操作成功');
getList();
} else {
message.error(res.message);
}
};
const getList = async () => {
listLoading.value = true;
const res = await taskCenterQueryListApi({ type: 0 });
if (res.success) {
list.value = res.data;
} else {
list.value = [];
}
listLoading.value = false;
};
</script>
<template>
<div>
<a-button @click="getList" type="primary">刷新数据</a-button>
</div>
<a-table
:data-source="list"
:loading="listLoading"
bordered
:rowKey="(record) => record.sysid"
style="margin-top: 15px"
>
<a-table-column title="操作时间" align="center" :width="100">
<template #default="{ record }">
{{ record.createTime }}
</template>
</a-table-column>
<a-table-column title="类型" align="center" :width="100">
<template #default="{ record }">
{{ record.type }}
</template>
</a-table-column>
<a-table-column title="状态" align="center" :width="100">
<template #default="{ record }">
<p>{{
record.isRevoke
? '已撤销'
: record.status == 0
? '待进行'
: record.status == 1
? '进行中'
: '已完成'
}}</p>
</template>
</a-table-column>
<a-table-column title="操作数据" align="center" :width="100">
<template #default="{ record }">
{{ record.productNum }}
</template>
</a-table-column>
<a-table-column title="成功数据" align="center" :width="100">
<template #default="{ record }">
{{ record.successNum }}
</template>
</a-table-column>
<a-table-column title="错误数据" align="center" :width="100">
<template #default="{ record }">
{{ record.failNum }}
</template>
</a-table-column>
<a-table-column title="操作人" align="center" :width="100">
<template #default="{ record }">
{{ record.createName }}
</template>
</a-table-column>
<a-table-column title="操作" align="center" :width="200">
<template #default="{ record }">
<a-button type="link" @click="downLoad(record.fileUrl)">下载源文件</a-button>
<a-button type="link" v-if="record.failNum" @click="downloadFail(record)"
>下载错误数据</a-button
>
<a-button type="link" v-if="record.status == 0 && !record.isRevoke" @click="cancel(record)"
>撤销</a-button
>
</template>
</a-table-column>
</a-table>
</template>
<style lang="less" scoped></style>
<script lang="ts" setup>
import ManageList from './components/list.vue';
</script>
<template>
<ManageList />
</template>
<style lang="less" scoped>
</style>
<script lang="ts" setup>
import { ref, onMounted } from 'vue';
import { regionalSpotManageGetStatusApi } from '/@/api/regionalSpotManage';
import ManageList from './components/list.vue';
const show = ref(false);
const loading = ref(false);
onMounted(async () => {
loading.value = true;
const res = await regionalSpotManageGetStatusApi().catch(() => (loading.value = false));
if (res.success) {
show.value = true;
}
loading.value = false;
});
</script>
<template>
<div>
<!-- <ManageList /> -->
<a-spin v-if="loading" style="height: 150px; width: 100%; line-height: 150px" />
<ManageList v-if="show && !loading" />
<div v-if="!show && !loading" class="status">
<img src="../../assets/images/logo.png" alt="" srcset="" />
</div>
</div>
</template>
<style lang="less" scoped>
.status {
height: 100vh;
img {
width: 100%;
height: 100vh;
object-fit: contain;
}
}
</style>
......@@ -56,6 +56,7 @@ declare global {
interface ImportMeta {
env: {
VITE_GLOB_API_URL?: string;
VITE_GLOB_TMALLAB_URL?: string;
};
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment