feat:【mall 商城】商品发布 - 库存价格【antd】100%: 迁移完成
This commit is contained in:
@@ -29,7 +29,7 @@ interface Props {
|
|||||||
isDetail?: boolean;
|
isDetail?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputValue = ref(''); // 输入框值
|
const inputValue = ref<string[]>([]); // 输入框值(tags 模式使用数组)
|
||||||
const attributeIndex = ref<null | number>(null); // 获取焦点时记录当前属性项的index
|
const attributeIndex = ref<null | number>(null); // 获取焦点时记录当前属性项的index
|
||||||
// 输入框显隐控制
|
// 输入框显隐控制
|
||||||
const inputVisible = computed(() => (index: number) => {
|
const inputVisible = computed(() => (index: number) => {
|
||||||
@@ -95,26 +95,29 @@ const showInput = async (index: number) => {
|
|||||||
|
|
||||||
// 定义 success 事件,用于操作成功后的回调
|
// 定义 success 事件,用于操作成功后的回调
|
||||||
const handleInputConfirm = async (index: number, propertyId: number) => {
|
const handleInputConfirm = async (index: number, propertyId: number) => {
|
||||||
if (inputValue.value) {
|
// 从数组中取最后一个输入的值(tags 模式下 inputValue 是数组)
|
||||||
|
const currentValue = inputValue.value?.[inputValue.value.length - 1]?.trim();
|
||||||
|
|
||||||
|
if (currentValue) {
|
||||||
// 1. 重复添加校验
|
// 1. 重复添加校验
|
||||||
if (
|
if (
|
||||||
attributeList.value?.[index]?.values?.find(
|
attributeList.value?.[index]?.values?.find(
|
||||||
(item) => item.name === inputValue.value,
|
(item) => item.name === currentValue,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
message.warning('已存在相同属性值,请重试');
|
message.warning('已存在相同属性值,请重试');
|
||||||
attributeIndex.value = null;
|
attributeIndex.value = null;
|
||||||
inputValue.value = '';
|
inputValue.value = [];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2.1 情况一:属性值已存在,则直接使用并结束
|
// 2.1 情况一:属性值已存在,则直接使用并结束
|
||||||
const existValue = attributeOptions.value.find(
|
const existValue = attributeOptions.value.find(
|
||||||
(item) => item.name === inputValue.value,
|
(item) => item.name === currentValue,
|
||||||
);
|
);
|
||||||
if (existValue) {
|
if (existValue) {
|
||||||
attributeIndex.value = null;
|
attributeIndex.value = null;
|
||||||
inputValue.value = '';
|
inputValue.value = [];
|
||||||
attributeList.value?.[index]?.values?.push({
|
attributeList.value?.[index]?.values?.push({
|
||||||
id: existValue.id!,
|
id: existValue.id!,
|
||||||
name: existValue.name,
|
name: existValue.name,
|
||||||
@@ -127,11 +130,11 @@ const handleInputConfirm = async (index: number, propertyId: number) => {
|
|||||||
try {
|
try {
|
||||||
const id = await createPropertyValue({
|
const id = await createPropertyValue({
|
||||||
propertyId,
|
propertyId,
|
||||||
name: inputValue.value,
|
name: currentValue,
|
||||||
});
|
});
|
||||||
attributeList.value?.[index]?.values?.push({
|
attributeList.value?.[index]?.values?.push({
|
||||||
id,
|
id,
|
||||||
name: inputValue.value,
|
name: currentValue,
|
||||||
});
|
});
|
||||||
message.success($t('common.createSuccess'));
|
message.success($t('common.createSuccess'));
|
||||||
emit('success', attributeList.value);
|
emit('success', attributeList.value);
|
||||||
@@ -140,7 +143,7 @@ const handleInputConfirm = async (index: number, propertyId: number) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
attributeIndex.value = null;
|
attributeIndex.value = null;
|
||||||
inputValue.value = '';
|
inputValue.value = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 获取商品属性下拉选项 */
|
/** 获取商品属性下拉选项 */
|
||||||
@@ -179,11 +182,11 @@ const getAttributeOptions = async (propertyId: number) => {
|
|||||||
:ref="setInputRef"
|
:ref="setInputRef"
|
||||||
v-model:value="inputValue"
|
v-model:value="inputValue"
|
||||||
allow-clear
|
allow-clear
|
||||||
class="!w-30"
|
|
||||||
mode="tags"
|
mode="tags"
|
||||||
:max-tag-count="1"
|
:max-tag-count="1"
|
||||||
:filter-option="true"
|
:filter-option="true"
|
||||||
size="small"
|
size="small"
|
||||||
|
style="width: 100px"
|
||||||
@blur="handleInputConfirm(index, item.id)"
|
@blur="handleInputConfirm(index, item.id)"
|
||||||
@change="handleInputConfirm(index, item.id)"
|
@change="handleInputConfirm(index, item.id)"
|
||||||
@keyup.enter="handleInputConfirm(index, item.id)"
|
@keyup.enter="handleInputConfirm(index, item.id)"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import type { MallSpuApi } from '#/api/mall/product/spu';
|
|||||||
|
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
import { formatToFraction, isEmpty } from '@vben/utils';
|
import { copyValueToTarget, formatToFraction, isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
import { Button, Image, Input, InputNumber, message } from 'ant-design-vue';
|
import { Button, Image, Input, InputNumber, message } from 'ant-design-vue';
|
||||||
|
|
||||||
@@ -59,20 +59,11 @@ const skuList = ref<MallSpuApi.Sku[]>([
|
|||||||
},
|
},
|
||||||
]); // 批量添加时的临时数据
|
]); // 批量添加时的临时数据
|
||||||
|
|
||||||
/** 商品图预览 */
|
|
||||||
const imagePreview = (imgUrl: string) => {
|
|
||||||
// TODO @puhui999: 图片预览
|
|
||||||
// createImageViewer({
|
|
||||||
// zIndex: 9_999_999,
|
|
||||||
// urlList: [imgUrl],
|
|
||||||
// });
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 批量添加 */
|
/** 批量添加 */
|
||||||
const batchAdd = () => {
|
const batchAdd = () => {
|
||||||
validateProperty();
|
validateProperty();
|
||||||
formData.value!.skus!.forEach((item: MallSpuApi.Sku) => {
|
formData.value!.skus!.forEach((item: MallSpuApi.Sku) => {
|
||||||
// copyValueToTarget(item, skuList.value[0]);
|
copyValueToTarget(item, skuList.value[0]);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -478,8 +469,7 @@ defineExpose({ generateTableData, validateSku, getSkuTableRef });
|
|||||||
v-if="row.picUrl"
|
v-if="row.picUrl"
|
||||||
:src="row.picUrl"
|
:src="row.picUrl"
|
||||||
class="h-[50px] w-[50px] cursor-pointer"
|
class="h-[50px] w-[50px] cursor-pointer"
|
||||||
:preview="false"
|
:preview="true"
|
||||||
@click="imagePreview(row.picUrl)"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</VxeColumn>
|
</VxeColumn>
|
||||||
@@ -563,8 +553,7 @@ defineExpose({ generateTableData, validateSku, getSkuTableRef });
|
|||||||
<Image
|
<Image
|
||||||
:src="row.picUrl"
|
:src="row.picUrl"
|
||||||
class="h-[60px] w-[60px] cursor-pointer"
|
class="h-[60px] w-[60px] cursor-pointer"
|
||||||
:preview="false"
|
:preview="true"
|
||||||
@click="imagePreview(row.picUrl)"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</VxeColumn>
|
</VxeColumn>
|
||||||
|
|||||||
@@ -68,3 +68,22 @@ export const getUrlValue = (
|
|||||||
const url = new URL(decodeURIComponent(urlStr));
|
const url = new URL(decodeURIComponent(urlStr));
|
||||||
return url.searchParams.get(key) ?? '';
|
return url.searchParams.get(key) ?? '';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将值复制到目标对象,且以目标对象属性为准,例:target: {a:1} source:{a:2,b:3} 结果为:{a:2}
|
||||||
|
* @param target 目标对象
|
||||||
|
* @param source 源对象
|
||||||
|
*/
|
||||||
|
export const copyValueToTarget = (target: any, source: any) => {
|
||||||
|
const newObj = Object.assign({}, target, source);
|
||||||
|
// 删除多余属性
|
||||||
|
Object.keys(newObj).forEach((key) => {
|
||||||
|
// 如果不是target中的属性则删除
|
||||||
|
if (!Object.keys(target).includes(key)) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||||
|
delete newObj[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// 更新目标对象值
|
||||||
|
Object.assign(target, newObj);
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user