|
@@ -0,0 +1,294 @@
|
|
|
+<script setup lang="tsx">
|
|
|
+import { computed, ref } from 'vue';
|
|
|
+import { NButton, NImage, NInputNumber, NSelect } from 'naive-ui';
|
|
|
+import dayjs from 'dayjs';
|
|
|
+import { fetchGetAllStoreList } from '@/service/api/goods/desk-category';
|
|
|
+import { fetchGetAllChannelList, fetchGetGoodsList, fetchImportGoods } from '@/service/api/goods/store-goods';
|
|
|
+import { areAllItemsAllFieldsFilled } from '@/utils/zt';
|
|
|
+import { useTable } from '@/components/zt/Table/hooks/useTable';
|
|
|
+import type { ModalMethods } from '@/components/zt/Modal/types';
|
|
|
+import SvgIcon from '@/components/custom/svg-icon.vue';
|
|
|
+import { useModal } from '@/components/zt/Modal/hooks/useModal';
|
|
|
+type Price = { channelId: number | undefined; channelProdPrice: number; id: number };
|
|
|
+const importTemplateRef = ref<ModalMethods>();
|
|
|
+const columns: NaiveUI.TableColumn<Api.goods.ShopSku>[] = [
|
|
|
+ {
|
|
|
+ type: 'selection',
|
|
|
+ align: 'center',
|
|
|
+ width: 48,
|
|
|
+ fixed: 'left'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'skuName',
|
|
|
+ title: '商品信息',
|
|
|
+ align: 'left',
|
|
|
+ width: 300,
|
|
|
+ fixed: 'left',
|
|
|
+ ellipsis: {
|
|
|
+ tooltip: true
|
|
|
+ },
|
|
|
+ render: row => {
|
|
|
+ if (!row.sku) {
|
|
|
+ return '---';
|
|
|
+ }
|
|
|
+ return (
|
|
|
+ <div class={'flex items-center'}>
|
|
|
+ <NImage src={row.sku.pic} class="h-[80px] w-[80px]" />
|
|
|
+ <div class={'ml-[10px]'}>
|
|
|
+ <div class={'text-[16px] font-semibold'}>{row.sku.skuName || '--'}</div>
|
|
|
+ <div class={'text-gray'}>海博商品ID: {row.sku.hbSkuId || '--'} </div>
|
|
|
+ <div class={'text-gray'}>商品编码:{row.sku.partyCode || '--'} </div>
|
|
|
+ <div class={'text-gray'}>SPUID: {row.sku.hbSpuId || '--'} </div>
|
|
|
+ <div class={'text-gray'}>外部商品编码:{row.sku.skuCode || '--'} </div>
|
|
|
+ <div class={'text-gray'}>条形码:{row.sku.modelId || '--'} </div>
|
|
|
+ <div class={'text-gray'}>
|
|
|
+ 重量/规格/单位:{row.sku.weight || '--'} / {row.sku.weightUnit || '--'} / {row.sku.weightUnit || '--'}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'shopName',
|
|
|
+ title: '门店名称',
|
|
|
+ align: 'center',
|
|
|
+ width: 120,
|
|
|
+ ellipsis: {
|
|
|
+ tooltip: true
|
|
|
+ },
|
|
|
+ render: row => {
|
|
|
+ const nameList = row.channelProdList?.map(it => it.shopName);
|
|
|
+ return <div>{nameList?.join(',')}</div>;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'shopSkuStocks',
|
|
|
+ title: '线上可售库存',
|
|
|
+ align: 'center',
|
|
|
+ width: 120
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'purchasePrice',
|
|
|
+ title: '进货价(元)',
|
|
|
+ align: 'center',
|
|
|
+ width: 120,
|
|
|
+ render: row => {
|
|
|
+ if (row.channelProdList) return <div>{row.channelProdList[0].purchasePrice}</div>;
|
|
|
+ return '--';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'deliveryPrice',
|
|
|
+ title: '出货价/控制价(元)',
|
|
|
+ align: 'center',
|
|
|
+ width: 150,
|
|
|
+ render: row => {
|
|
|
+ if (row.channelProdList) return <div>{row.channelProdList[0].deliveryPrice}</div>;
|
|
|
+ return '--';
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'name',
|
|
|
+ title: '销售渠道及价格',
|
|
|
+ align: 'center',
|
|
|
+ width: 150,
|
|
|
+ render: row => {
|
|
|
+ return row.channelProdList?.map(it => {
|
|
|
+ return (
|
|
|
+ <div>
|
|
|
+ {it.channelName} : {it.channelProdPrice}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+];
|
|
|
+const options = ref<Api.goods.Channel[]>([]);
|
|
|
+const PriceColumns: NaiveUI.TableColumn<Price>[] = [
|
|
|
+ {
|
|
|
+ title: '销售渠道',
|
|
|
+ key: 'channelId',
|
|
|
+ align: 'center',
|
|
|
+ width: 250,
|
|
|
+ render: row => {
|
|
|
+ return (
|
|
|
+ <NSelect
|
|
|
+ options={options.value}
|
|
|
+ labelField="channelName"
|
|
|
+ valueField="id"
|
|
|
+ value={row.channelId}
|
|
|
+ onUpdate:value={value => {
|
|
|
+ row.channelId = Number(value);
|
|
|
+ }}
|
|
|
+ ></NSelect>
|
|
|
+ );
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '售价(元)',
|
|
|
+ key: 'channelProdPrice',
|
|
|
+ align: 'center',
|
|
|
+ width: 250,
|
|
|
+ render: row => {
|
|
|
+ return (
|
|
|
+ <NInputNumber
|
|
|
+ value={row.channelProdPrice}
|
|
|
+ precision={2}
|
|
|
+ onUpdate:value={value => {
|
|
|
+ row.channelProdPrice = Number(value);
|
|
|
+ }}
|
|
|
+ min={1}
|
|
|
+ />
|
|
|
+ );
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: () => {
|
|
|
+ return (
|
|
|
+ <div onClick={() => handleAddPrice()}>
|
|
|
+ <SvgIcon
|
|
|
+ icon={'proicons:add-square'}
|
|
|
+ class={'cursor-pointer text-24px'}
|
|
|
+ style={'color:var(--n-color)'}
|
|
|
+ ></SvgIcon>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ },
|
|
|
+ key: 'action',
|
|
|
+ width: 80,
|
|
|
+ render: row => {
|
|
|
+ return (
|
|
|
+ <div onClick={() => handleDelPrice(row.id)}>
|
|
|
+ <SvgIcon
|
|
|
+ icon={'proicons:subtract-square'}
|
|
|
+ class={'cursor-pointer text-24px'}
|
|
|
+ style={'color:#f5222d'}
|
|
|
+ ></SvgIcon>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+];
|
|
|
+const PriceData = ref<Price[]>([]);
|
|
|
+const selectData = ref<Api.goods.ShopSku>();
|
|
|
+const [registerTable, { getTableCheckedRowKeys }] = useTable({
|
|
|
+ searchFormConfig: {
|
|
|
+ schemas: [
|
|
|
+ {
|
|
|
+ label: '门店名称',
|
|
|
+ component: 'ApiSelect',
|
|
|
+ field: 'shopId',
|
|
|
+ componentProps: {
|
|
|
+ api: fetchGetAllStoreList,
|
|
|
+ labelFeild: 'shopName',
|
|
|
+ valueFeild: 'hbStationId'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '商品名称',
|
|
|
+ component: 'NInput',
|
|
|
+ field: 'shopId'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ inline: false,
|
|
|
+ size: 'small',
|
|
|
+ labelPlacement: 'left',
|
|
|
+ isFull: false
|
|
|
+ },
|
|
|
+ tableConfig: {
|
|
|
+ keyField: 'id',
|
|
|
+ title: '商品列表',
|
|
|
+ showAddButton: false,
|
|
|
+ scrollX: 1200
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const [registerModalPrice, { openModal: openPriceModal, setSubLoading: setSubModalLoding }] = useModal({
|
|
|
+ title: '设置渠道及价格',
|
|
|
+ width: 800,
|
|
|
+ height: 300
|
|
|
+});
|
|
|
+
|
|
|
+const isDisabledExport = computed(() => {
|
|
|
+ return !getTableCheckedRowKeys().length;
|
|
|
+});
|
|
|
+
|
|
|
+async function handleSubmitImport(file: File) {
|
|
|
+ const { error } = await fetchImportGoods({ file });
|
|
|
+ if (!error) {
|
|
|
+ importTemplateRef.value?.closeModal();
|
|
|
+ }
|
|
|
+ importTemplateRef.value?.setSubLoading(false);
|
|
|
+}
|
|
|
+function openImportModal() {
|
|
|
+ importTemplateRef.value?.openModal();
|
|
|
+}
|
|
|
+function handleModalPrice(row: Api.goods.ShopSku) {
|
|
|
+ selectData.value = row;
|
|
|
+ openPriceModal();
|
|
|
+}
|
|
|
+function handleAddPrice() {
|
|
|
+ if (PriceData.value.length == 3) return;
|
|
|
+ PriceData.value.push({
|
|
|
+ channelId: undefined,
|
|
|
+ channelProdPrice: 1,
|
|
|
+ id: dayjs().valueOf()
|
|
|
+ });
|
|
|
+}
|
|
|
+function handleDelPrice(id: number) {
|
|
|
+ PriceData.value = PriceData.value.filter(item => item.id != id);
|
|
|
+}
|
|
|
+
|
|
|
+function handleSubmitPrice() {
|
|
|
+ setSubModalLoding(false);
|
|
|
+ if (!PriceData.value.length) {
|
|
|
+ window.$message?.error('最少填写一条数据');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!areAllItemsAllFieldsFilled(PriceData.value)) {
|
|
|
+ window.$message?.error('请填写完整数据');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ setSubModalLoding(true);
|
|
|
+
|
|
|
+ console.log(PriceData.value, 'asdsad');
|
|
|
+}
|
|
|
+async function getData() {
|
|
|
+ const { data, error } = await fetchGetAllChannelList();
|
|
|
+ if (!error) {
|
|
|
+ options.value = data;
|
|
|
+ }
|
|
|
+}
|
|
|
+getData();
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <LayoutTable>
|
|
|
+ <ZTable :columns="columns" :api="fetchGetGoodsList" @register="registerTable">
|
|
|
+ <template #op="{ row }">
|
|
|
+ <NButton size="small" ghost type="primary" @click="handleModalPrice(row)">设置渠道及价格</NButton>
|
|
|
+ </template>
|
|
|
+ <template #prefix>
|
|
|
+ <NSpace>
|
|
|
+ <NButton size="small" @click="openImportModal">导入商品销售渠道及价格</NButton>
|
|
|
+ <NButton size="small">导出全部</NButton>
|
|
|
+ <NButton size="small" :disabled="isDisabledExport">导出选中数据</NButton>
|
|
|
+ <NButton size="small">修改记录</NButton>
|
|
|
+ </NSpace>
|
|
|
+ </template>
|
|
|
+ </ZTable>
|
|
|
+ <ZImportTemplate
|
|
|
+ ref="importTemplateRef"
|
|
|
+ url="/platform/channelProd/template/download"
|
|
|
+ template-text="商品渠道及价格导入模版.xlsx"
|
|
|
+ modal-text="导入商品销售渠道及价格"
|
|
|
+ @submit="handleSubmitImport"
|
|
|
+ ></ZImportTemplate>
|
|
|
+ <BasicModal @register="registerModalPrice" @ok="handleSubmitPrice">
|
|
|
+ <NDataTable :columns="PriceColumns" :data="PriceData" :row-key="row => row.id" />
|
|
|
+ </BasicModal>
|
|
|
+ </LayoutTable>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped></style>
|