|
@@ -0,0 +1,258 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import { useDebounceFn } from "@vueuse/core";
|
|
|
+import { ref, onMounted, reactive, onUnmounted, watch } from "vue";
|
|
|
+import { getCategories } from "/@/api/user";
|
|
|
+import { useResponseHandle } from "/@/hooks/core/useAsync";
|
|
|
+import { useCompany } from "/@/hooks/core/useCompany";
|
|
|
+import { useUserInfo } from "/@/hooks/core/useUser";
|
|
|
+
|
|
|
+import { useVModel } from "@vueuse/core"
|
|
|
+
|
|
|
+const emit = defineEmits(["change", "update:modelValue"]);
|
|
|
+
|
|
|
+
|
|
|
+const props = withDefaults(
|
|
|
+ defineProps<{
|
|
|
+ noAll?: boolean;
|
|
|
+ noSet?: boolean;
|
|
|
+ modelValue?: string;
|
|
|
+ isSupplier?: boolean;
|
|
|
+ placeholder?: string;
|
|
|
+ classWrapper?:string
|
|
|
+ }>(),
|
|
|
+ {
|
|
|
+ modelValue: "",
|
|
|
+ classWrapper: 'procure-item'
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+const value = useVModel(props, 'modelValue')
|
|
|
+
|
|
|
+
|
|
|
+const { setCurrentCompany } = useCompany();
|
|
|
+const responseHandle = useResponseHandle();
|
|
|
+
|
|
|
+const { userLevel } = useUserInfo();
|
|
|
+
|
|
|
+const selectRef = ref(null);
|
|
|
+const list = ref<any[]>([]);
|
|
|
+
|
|
|
+const state = reactive({
|
|
|
+ loading: false,
|
|
|
+ noMore: false,
|
|
|
+ name: "",
|
|
|
+ count: 0,
|
|
|
+ page: 1
|
|
|
+});
|
|
|
+
|
|
|
+let scrollWrapper: HTMLDivElement | null = null;
|
|
|
+
|
|
|
+const debouceScroll = useDebounceFn(handleScroll, 500);
|
|
|
+
|
|
|
+async function requesetSupplierAll(name: string) {
|
|
|
+ state.name = name;
|
|
|
+ state.page = 1;
|
|
|
+ state.noMore = false;
|
|
|
+ const api = getCategories
|
|
|
+ const { data, message, code } = await api({
|
|
|
+ cat_name: name,
|
|
|
+ size:10,
|
|
|
+ page: state.page
|
|
|
+ });
|
|
|
+
|
|
|
+ responseHandle({
|
|
|
+ code,
|
|
|
+ message,
|
|
|
+ handler: () => {
|
|
|
+ list.value = data.list.map(({ short_name, cat_name, merge_code,tax }) => ({
|
|
|
+ tax,
|
|
|
+ subTitle: short_name,
|
|
|
+ value: merge_code,
|
|
|
+ label: cat_name
|
|
|
+ }))
|
|
|
+
|
|
|
+ state.count = data.count;
|
|
|
+ state.loading = false;
|
|
|
+ const maxPage = Math.ceil(state.count / 10);
|
|
|
+ state.noMore = maxPage <= 1;
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function handleChange(v) {
|
|
|
+ const item = list.value.find(({ value }) => v === value);
|
|
|
+ console.log(list.value, value, item)
|
|
|
+ emit("change", item);
|
|
|
+}
|
|
|
+
|
|
|
+async function handleScroll() {
|
|
|
+ const height = scrollWrapper?.clientHeight;
|
|
|
+ const scrollTop = scrollWrapper?.scrollTop;
|
|
|
+ const scrollHeight = scrollWrapper?.scrollHeight;
|
|
|
+
|
|
|
+ if (height + scrollTop >= scrollHeight && !state.noMore) {
|
|
|
+ state.page++;
|
|
|
+ state.loading = true;
|
|
|
+
|
|
|
+ const api = getCategories
|
|
|
+
|
|
|
+
|
|
|
+ const { data, message, code } = await api({
|
|
|
+ cat_name: state.name,
|
|
|
+ page: state.page,
|
|
|
+ size:10,
|
|
|
+ noRela: true
|
|
|
+ });
|
|
|
+
|
|
|
+ const pushCompany = (_list: any[]) => {
|
|
|
+ list.value = [...list.value, ..._list.map(({ short_name, cat_name, merge_code, tax }) => ({
|
|
|
+ tax,
|
|
|
+ subTitle: short_name,
|
|
|
+ value: merge_code,
|
|
|
+ label: cat_name
|
|
|
+ }))];
|
|
|
+ };
|
|
|
+
|
|
|
+ responseHandle({
|
|
|
+ code,
|
|
|
+ message,
|
|
|
+ handler: () => {
|
|
|
+ state.count = data.count;
|
|
|
+ const maxPage = Math.ceil(state.count / 10);
|
|
|
+
|
|
|
+ if (state.page > maxPage) {
|
|
|
+ state.noMore = true;
|
|
|
+ state.loading = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ pushCompany(data.list);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ setTimeout(() => {
|
|
|
+ const superItem = document.querySelector("." + props.classWrapper);
|
|
|
+ if (!superItem) return;
|
|
|
+ scrollWrapper = superItem.parentElement?.parentElement as HTMLDivElement;
|
|
|
+ if (scrollWrapper) {
|
|
|
+ scrollWrapper.addEventListener("scroll", debouceScroll, false);
|
|
|
+ }
|
|
|
+ }, 1000);
|
|
|
+});
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ state.loading = false;
|
|
|
+ state.noMore = false;
|
|
|
+ state.name = "";
|
|
|
+ state.page = 1;
|
|
|
+
|
|
|
+ if (scrollWrapper) {
|
|
|
+ scrollWrapper.removeEventListener("scroll", debouceScroll);
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+watch(
|
|
|
+ () => userLevel.value,
|
|
|
+ level => {
|
|
|
+ if (level !== "") {
|
|
|
+ state.loading = false;
|
|
|
+ state.noMore = false;
|
|
|
+ state.name = "";
|
|
|
+ state.page = 1;
|
|
|
+ list.value = [];
|
|
|
+ requesetSupplierAll(undefined);
|
|
|
+ }
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+const getLabel = company => {
|
|
|
+ const { value, label } = company;
|
|
|
+ return value + " / " + label;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const getLabel2 = company => {
|
|
|
+ const { value, label, subTitle } = company;
|
|
|
+ return value + " / " + label + '-' + subTitle;
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+requesetSupplierAll(undefined);
|
|
|
+
|
|
|
+
|
|
|
+defineExpose({
|
|
|
+ async initalData(params){
|
|
|
+ const { data, message, code } = await getCategories(params);
|
|
|
+
|
|
|
+ list.value = (data.list || []).map(({ tax, cat_name ,merge_code, short_name }) => ({
|
|
|
+ tax,
|
|
|
+ value: merge_code,
|
|
|
+ label: cat_name,
|
|
|
+ subTitle: short_name
|
|
|
+ }))
|
|
|
+
|
|
|
+ value.value = (list.value[0] || {}).value
|
|
|
+ emit('change', list.value[0], true)
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <ElSelect
|
|
|
+ filterable
|
|
|
+ remote
|
|
|
+ v-model="value"
|
|
|
+ :remote-method="requesetSupplierAll"
|
|
|
+ @change="handleChange"
|
|
|
+ style="width: 100%"
|
|
|
+ ref="selectRef"
|
|
|
+ placeholder="商品类目"
|
|
|
+ >
|
|
|
+ <ElOption
|
|
|
+ :class="classWrapper"
|
|
|
+ v-for="item in list"
|
|
|
+ :key="item.value"
|
|
|
+ :value="item.value"
|
|
|
+ :label="getLabel2(item)"
|
|
|
+ >
|
|
|
+ <span style="float: left">
|
|
|
+ {{getLabel(item)}}
|
|
|
+ </span>
|
|
|
+
|
|
|
+ <span style="float: right;color: var(--el-text-color-secondary);font-size: 13px;">
|
|
|
+ {{item.subTitle}}
|
|
|
+ </span>
|
|
|
+ </ElOption>
|
|
|
+
|
|
|
+ <p class="super-loading" v-if="state.loading">
|
|
|
+ <IconifyIconOffline class="animate-spin" icon="Loading" />
|
|
|
+ 加载中
|
|
|
+ </p>
|
|
|
+
|
|
|
+ <p class="super-no-more" v-if="state.noMore">没有更多数据了...</p>
|
|
|
+ </ElSelect>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.super-no-more {
|
|
|
+ text-align: center;
|
|
|
+ color: #999;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 38px;
|
|
|
+}
|
|
|
+
|
|
|
+.super-loading {
|
|
|
+ display: flex;
|
|
|
+ font-size: 14px;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ color: #999;
|
|
|
+ gap: 10px;
|
|
|
+ line-height: 38px;
|
|
|
+}
|
|
|
+</style>
|