123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- <template>
- <div class="component-sku-select">
- <el-dialog
- v-model.sync="show"
- class="custom-select-sku-dialog"
- title="选择SKU"
- :close-on-click-modal="false"
- :close-on-press-escape="false"
- :before-close="close"
- width="1200px"
- >
- <div
- v-loading="loading"
- class="flex items-start"
- style="max-height: 100%"
- >
- <div class="max-h-[800px] overflow-auto min-w-[180px]">
- <el-input
- v-model="keywords"
- placeholder="SKU / 商品名"
- style="margin-bottom: 24px"
- @keyup.enter="search"
- >
- <template #append>
- <el-button
- size="small"
- @click="search"
- >
- 查询
- </el-button>
- </template>
- </el-input>
- <div class="catgory-area">
- <el-tree
- node-key="id"
- :default-expanded-keys="defaultExpandID"
- :data="categoryList"
- :props="defaultProps"
- @node-click="clickNode"
- ></el-tree>
- </div>
- </div>
- <div class="flex-auto pl-[24px]">
- <el-button
- v-if="scene !== 'changeOrder'"
- type="primary"
- class="mb-2"
- @click="dialogApplySkuVisible = true"
- >
- 申请
- </el-button>
- <div
- v-if="skuList.length"
- class="sku-area flex flex-wrap items-center"
- >
- <div
- v-for="sku in skuList"
- :key="sku.id"
- class="sku-item"
- >
- <div class="image flex justify-center">
- <img
- v-if="sku.images.length"
- :src="sku.images[0]"
- class="h-[100%] w-auto"
- />
- </div>
- <div class="sku-name">{{ sku.product_name }}</div>
- <div class="flex justify-between items-center">
- <div class="sku-code">Product Code: {{ sku.product_sku }}</div>
- <el-button
- type="primary"
- size="small"
- plain
- @click="selectSku(sku)"
- >
- 使用
- </el-button>
- </div>
- </div>
- </div>
- <div
- v-else-if="scene === 'changeOrder'"
- class="sku-area flex-auto flex items-center"
- style="padding-left: 25%"
- >
- 未找到你想要的Indent商品
- </div>
- <div
- v-else
- class="sku-area flex-auto flex items-center"
- style="padding-left: 25%"
- >
- 未找到你想要的Indent商品, 可进行
- <el-button
- link
- type="primary"
- @click="dialogApplySkuVisible = true"
- >
- 申请
- </el-button>
- </div>
- </div>
- </div>
- <template #footer>
- <div class="flex items-center justify-end">
- <el-pagination
- v-show="total > 0"
- v-model:current-page="pageForm.page"
- v-model:page-size="pageForm.limit"
- :page-sizes="[10, 20, 50, 100]"
- :total="total"
- :layout="'total, sizes, prev, pager, next, jumper'"
- @size-change="getSku"
- @current-change="getSku"
- />
- </div>
- </template>
- </el-dialog>
- <sku-apply
- v-model:visible="dialogApplySkuVisible"
- @apply="onSkuApply"
- ></sku-apply>
- </div>
- </template>
- <script lang="ts" setup>
- import { defineComponent, ref, inject, watch } from 'vue'
- import { ElButton, ElInput, ElTree, ElDialog, ElPagination } from 'element-plus'
- import algoliasearch from 'algoliasearch'
- import { getCategoryTree, getSkuList } from '@/api/indent.js'
- import skuApply from './skuApply.vue'
- defineComponent({
- name: 'ComponentSkuSelect',
- })
- const $mediaRegExp = inject('mediaRegExp') as RegExp
- const { visible = false, scene = '' } = defineProps<{ visible: boolean; scene?: string }>()
- const $emit = defineEmits(['update:visible', 'select'])
- const defaultProps = {
- children: 'children',
- label: 'name',
- }
- const dialogApplySkuVisible = ref(false)
- const loading = ref(false)
- const keywords = ref('')
- const defaultExpandID = ref([] as any[])
- const show = ref(false)
- const currentCategory = ref('')
- const categoryList = ref([] as any[])
- const skuList = ref([] as any[])
- const pageForm = ref({
- page: 1,
- limit: 20,
- })
- const total = ref(0)
- const onSkuApply = (data: any) => {
- $emit('select', {
- product_name: data.product_name,
- product_sku: '申请中',
- id: data.id,
- })
- close()
- }
- const search = () => {
- currentCategory.value = ''
- skuList.value = []
- pageForm.value = {
- page: 1,
- limit: 20,
- }
- total.value = 0
- getSku()
- }
- const resetData = () => {
- currentCategory.value = ''
- categoryList.value = []
- skuList.value = []
- pageForm.value = {
- page: 1,
- limit: 20,
- }
- total.value = 0
- }
- const selectSku = (item: any) => {
- $emit('select', item)
- close()
- }
- const clickNode = (obj: any) => {
- currentCategory.value = obj.name
- }
- const getCategory = () => {
- getCategoryTree().then((response: any) => {
- const res = response.result
- categoryList.value = res
- categoryList.value.forEach((i) => {
- defaultExpandID.value.push(i.id)
- i.path = `${i.id}`
- if (Array.isArray(i.children) && i.children.length > 0) {
- i.children.forEach((son: any) => {
- son.path = `${i.id},${son.id}`
- if (Array.isArray(son.children) && son.children.length > 0) {
- defaultExpandID.value.push(son.id)
- son.children.forEach((grandson: any) => {
- grandson.path = `${i.id},${son.id},${grandson.id}`
- })
- }
- })
- }
- })
- })
- }
- let index = ref({} as any)
- const initAI = () => {
- const client = algoliasearch('7BX4P6RSP2', 'aa9ec8e7e12a6633e7924fab6487e6af')
- index.value = client.initIndex('indent_app')
- }
- const getSku = () => {
- loading.value = true
- index.value
- .search(currentCategory.value || keywords.value, {
- hitsPerPage: pageForm.value.limit,
- page: pageForm.value.page - 1,
- })
- .then((response: any) => {
- const res = response.hits
- let temp = res.map((item: any) => {
- const t =
- typeof item.images === 'string'
- ? `${item.images}`.split(',').filter((i: string) => i.length > 0)
- : []
- return {
- ...item,
- images: t.map((i: string) => {
- return $mediaRegExp.test(i) ? i : import.meta.env.VITE_APP_OSS_PREFIX + i
- }),
- }
- })
- // product_type属性有几种类型 indent Express Stock Other. 把他们按这个顺序排雷, 所有indent要出现在嘴在前面, Other在最后面
- temp.sort((a: any, b: any) => {
- const order = ['indent', 'Express', 'Stock', 'Other']
- return order.indexOf(a.product_type) - order.indexOf(b.product_type)
- })
- skuList.value = temp
- total.value = response.nbHits > 1000 ? 1000 : response.nbHits
- })
- .finally(() => {
- loading.value = false
- })
- }
- watch(
- () => visible,
- () => {
- show.value = visible
- resetData()
- if (show.value) {
- initAI()
- setTimeout(() => {
- getSku()
- }, 500)
- getCategory()
- }
- },
- )
- watch(currentCategory, () => {
- if (!currentCategory.value) return
- keywords.value = ''
- skuList.value = []
- pageForm.value = {
- page: 1,
- limit: 20,
- }
- total.value = 0
- getSku()
- })
- const close = (done = {} as any) => {
- $emit('update:visible', false)
- if (typeof done === 'function') done()
- }
- </script>
- <style lang="scss">
- .component-sku-select {
- .custom-select-sku-dialog {
- margin-top: 0 !important;
- margin-bottom: 0 !important;
- height: 100vh;
- .el-dialog__body {
- position: relative;
- // max-height: 87vh;
- // overflow-y: scroll;
- // overflow-x: auto;
- padding-top: 8px;
- padding-bottom: 8px;
- }
- }
- }
- </style>
- <style lang="scss" scoped>
- .component-sku-select {
- .catgory-area {
- width: 180px;
- min-width: 180px;
- border: 1px solid #eee;
- padding: 0 12px 24px 0;
- }
- .sku-area {
- width: 100%;
- // padding-left: 24px;
- height: 82vh;
- overflow-y: auto;
- }
- .sku-item {
- border: 1px solid #eee;
- padding: 12px;
- width: 280px;
- margin: 0 18px 12px 0;
- .sku-name {
- overflow: hidden;
- font-size: 18px;
- line-height: 24px;
- height: 48px;
- max-height: 48px;
- color: #222;
- margin-bottom: 8px;
- word-break: break-word;
- }
- .sku-code {
- color: #409eff;
- }
- .image {
- border: 1px solid #eee;
- position: relative;
- width: 100%;
- height: 120px;
- margin-bottom: 8px;
- }
- }
- }
- </style>
|