| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- <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,
- fetchSetUpChannels
- } 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 options = ref<Api.goods.Channel[]>([]);
- const TypeName = ['企业用户', 'B端用户', 'C端用户'];
- const columns: NaiveUI.TableColumn<Api.goods.ShopSku>[] = [
- {
- type: 'selection',
- align: 'center',
- width: 48,
- fixed: 'left'
- },
- {
- key: 'skuName',
- title: '商品信息',
- align: 'left',
- width: 300,
- fixed: 'left',
- render: row => {
- if (!row.sku) {
- return '---';
- }
- const img = row.sku.pic?.split(',');
- return (
- <div class={'flex items-center'}>
- <NImage src={img[0]} class="h-[80px] min-w-80px w-[80px]" lazy />
- <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?.length) return '--';
- if (row.channelProdList) return <div>{row.channelProdList[0].purchasePrice || '--'}</div>;
- return '--';
- }
- },
- {
- key: 'deliveryPrice',
- title: '出货价/控制价(元)',
- align: 'center',
- width: 150,
- render: row => {
- if (!row.channelProdList?.length) return '--';
- if (row.channelProdList) return <div>{row.channelProdList[0].deliveryPrice || '--'}</div>;
- return '--';
- }
- },
- {
- key: 'name',
- title: '销售渠道及价格',
- align: 'center',
- width: 250,
- render: row => {
- return row.channelProdList?.map(it => {
- return (
- <div>
- {TypeName[Number(it.channelId) - 1]} ({it.channelName || '--'}) : {it.channelProdPrice || '--'}
- </div>
- );
- });
- }
- }
- ];
- 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}
- clearable
- onUpdate:value={value => {
- options.value.map(it => {
- if (it.id == row.channelId) {
- it.disabled = false;
- }
- return it;
- });
- row.channelId = value ? Number(value) : undefined;
- }}
- onUpdate:show={value => {
- options.value.map(it => {
- if (it.id == row.channelId) {
- if (value) {
- it.disabled = false;
- }
- if (!value) {
- it.disabled = true;
- }
- }
- return it;
- });
- }}
- ></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()} class={'w-full flex items-center justify-center'}>
- <SvgIcon
- icon={'proicons:add-square'}
- class={'cursor-pointer text-24px'}
- style={'color:var(--n-color)'}
- ></SvgIcon>
- </div>
- );
- },
- key: 'action',
- width: 80,
- align: 'center',
- render: row => {
- return (
- <div onClick={() => handleDelPrice(row.id)} class={'w-full flex items-center justify-center'}>
- <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, refresh, getTableData }] = 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, closeModal: closePriceModal }
- ] = useModal({
- title: '设置渠道及价格',
- width: 800,
- height: 300
- });
- const isDisabledExport = computed(() => {
- return !getTableCheckedRowKeys().length;
- });
- const tableData = computed(() => {
- return getTableData();
- });
- 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;
- if (row.channelProdList) {
- PriceData.value = row.channelProdList?.map(it => {
- return {
- channelId: Number(it.channelId),
- channelProdPrice: Number(it.channelProdPrice),
- id: Number(it.id)
- };
- });
- }
- openPriceModal();
- }
- function handleAddPrice() {
- if (PriceData.value.length == 3) {
- window.$message?.error('最多只能添加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);
- }
- async function handleSubmitPrice() {
- setSubModalLoding(false);
- if (!PriceData.value.length) {
- window.$message?.error('最少填写一条数据');
- return;
- }
- if (!areAllItemsAllFieldsFilled(PriceData.value)) {
- window.$message?.error('请填写完整数据');
- return;
- }
- setSubModalLoding(true);
- const form = {
- shopId: selectData.value?.shopId,
- skuId: selectData.value?.skuId,
- purchasePrice: selectData.value?.channelProdList?.length ? selectData.value.channelProdList[0].purchasePrice : null,
- deliveryPrice: selectData.value?.channelProdList?.length ? selectData.value.channelProdList[0].deliveryPrice : null,
- setChannelPriceDtoList: PriceData.value.map(item => {
- return {
- channelId: item.channelId,
- channelProdPrice: item.channelProdPrice
- };
- })
- };
- const { error } = await fetchSetUpChannels(form);
- if (!error) {
- closePriceModal();
- refresh();
- PriceData.value = [];
- options.value.map(it => (it.disabled = false));
- } else {
- setSubModalLoding(false);
- }
- 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" :disabled="tableData.length == 0">导出全部</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>
|