diff --git a/package-lock.json b/package-lock.json index 196dc26..0d8c448 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "element-plus": "^2.9.9", "pinia": "^3.0.2", "pinia-plugin-persistedstate": "^4.2.0", + "sortablejs": "^1.15.6", "vue": "^3.5.13", "vue-router": "^4.5.1", "xlsx": "^0.18.5", @@ -4139,6 +4140,12 @@ "node": ">=18" } }, + "node_modules/sortablejs": { + "version": "1.15.6", + "resolved": "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.15.6.tgz", + "integrity": "sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==", + "license": "MIT" + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", diff --git a/package.json b/package.json index 4b23fcb..7e8a36a 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "element-plus": "^2.9.9", "pinia": "^3.0.2", "pinia-plugin-persistedstate": "^4.2.0", + "sortablejs": "^1.15.6", "vue": "^3.5.13", "vue-router": "^4.5.1", "xlsx": "^0.18.5", diff --git a/src/components/Base.vue b/src/components/Base.vue index 699ef25..b7c2e47 100644 --- a/src/components/Base.vue +++ b/src/components/Base.vue @@ -91,38 +91,40 @@ :cell-style="{borderColor: 'black'}" style="border: 1px solid black;" size="small" + row-key="id" border @row-click="handleRowEdit" > - + + + + {{ $index + 1 }} + + + - - {{ row.b_name }} + {{ row.b_name }} - - {{ row.code }} + {{ row.code }} - - {{ row.new_code }} + {{ row.new_code }} - - {{ scope.row.name }} + {{ scope.row.name }} - - {{ (+scope.row.price).toFixed(2) }} + {{ (+scope.row.price).toFixed(2) }} @@ -132,32 +134,27 @@ - - {{ (+scope.row.sell_price).toFixed(2) }} + {{ (+scope.row.sell_price).toFixed(2) }} - - {{ scope.row.weight }} + {{ scope.row.weight }} - - {{ scope.row.volumn }} + {{ scope.row.volumn }} - - {{ scope.row.amount }} + {{ scope.row.amount }} - - {{ scope.row.note }} + {{ scope.row.note }} @@ -197,68 +194,131 @@ - + - - - - - - - - goodsList.splice(scope.$index,1)" - /> - - - - - - - {}" - > - - - + goodsList.splice(scope.$index,1)" + /> + + + + + + + {}" + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{ row.add_time }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -275,7 +335,7 @@ - + @@ -358,6 +418,7 @@ import BrandPicker from '@/components/BrandPicker.vue' import ProductPicker from '@/components/ProductPicker.vue' import { useUserStore } from '@/store' + import Sortable from "sortablejs"; const user_store = useUserStore() const order_id = ref(0) @@ -420,25 +481,7 @@ const { data:rb } = await hasSupplyInquiry(order_id.value) has_supply_inquiry.value = +rb.data > 0 } - if(editable.value) { - goodsList.value.push({ - brand_info: {id: 0,name: ''}, - code: '', - new_code: '', - name: '', - b_name: '', - brand: 0, - price: 0, - sell_price: 0, - weight: 0.000, - volumn: 0.000, - amount: 1, - type: 'other', - seller: '待定', - seller_id: 0, - note: '' - }) - } + setSort() } onMounted(async() => { @@ -447,6 +490,7 @@ if(order_id.value != 0) { await load() } + setSort() }) const goods_change = computed(() => { @@ -457,8 +501,6 @@ return order_status.value == 0 && !has_supply_inquiry.value }) - const lastRow = computed(() => (idx) => order_status.value == 0 && !has_supply_inquiry.value && goodsList.value.length == (idx + 1)) - const customer_search = ref('') const enableCustomerEdit = ref(false) const handleCustomerEdit = () => { @@ -535,24 +577,7 @@ order_note.value = order.data.note order_subject.value = order.data.subject goodsList.value = [] - goodsList.value.push({ - id: 0, - brand_info: {id: 0,name: ''}, - code: '', - new_code: '', - name: '', - b_name: '', - brand: 0, - price: 0, - sell_price: 0, - weight: 0.000, - volumn: 0.000, - amount: 1, - type: 'other', - seller: '待定', - seller_id: 0, - note: '' - }) + setSort() goodsHash.value = md5(JSON.stringify([])) const { data:member } = await memberInfo(+order.data.user_id) if(member.data.id) { @@ -609,26 +634,25 @@ } } - // const baseItem = { - // brand_info: {id: 0,name: ''}, - // code: '', - // new_code: '', - // name: '', - // b_name: '', - // brand: 0, - // price: 0, - // sell_price: 0, - // weight: 0.000, - // volumn: 0.000, - // amount: 1, - // type: 'other', - // seller: '待定', - // seller_id: 0, - // note: '' - // } - // const brandInfo = ref({}) - // const product_code = ref('') - // const edit_data = ref(baseItem) + const baseItem = { + id: 0, + brand_info: {id: 0,name: ''}, + code: '', + short_code: '', + new_code: '', + name: '', + b_name: '', + brand: 0, + price: 0, + sell_price: 0, + weight: 0.000, + volumn: 0.000, + amount: 1, + type: 'other', + seller: '待定', + seller_id: 0, + note: '', + } let new_product = reactive({ id: 0, @@ -645,14 +669,15 @@ add_time: '', }) + const edit_data = ref([Object.assign({},baseItem)]) const edit_row = ref(0) const centerDialogVisible = ref(false) const handleRowEdit = (row,column,evt) => { if(order_status.value > 0) { return } - let idx = goodsList.value.filter((_,i) => i < goodsList.value.length - 1).findIndex((item) => item.id == row.id && item.code == row.code) - if(idx <= -1) { + let idx = goodsList.value.findIndex((item) => item.id == row.id && item.code == row.code) + if(idx < 0) { return } edit_row.value = idx @@ -694,7 +719,7 @@ weight, volume, type: 'product', - amount: parseInt(new_product.amount) ? parseInt(new_product.amount) : 1, + amount: parseInt(new_product.amount) ? +new_product.amount : 1, note: new_product.note, seller: '预订产品', seller_id: 0, @@ -706,33 +731,6 @@ if(new_product.sell_price > 0 && new_product.sell_price != product_data.sell_price) { product_data.sell_price = new_product.sell_price } - // if(goodsList.value[edit_row.value].id == product_data.id) { - // Object.assign(goodsList.value[edit_row.value],product_data) - // } else { - // let idx = goodsList.value.findIndex(item => item.id == product_data.id) - // if(idx < 0) { - // Object.assign(goodsList.value[edit_row.value],product_data) - // } else { - // MessageBox.confirm('当前商品已存在,是否合并?', '商品已存在',{ - // confirmButtonText: '合并', - // cancelButtonText: '取消', - // type: 'warning', - // }).then(() => { - // goodsList.value[idx]['amount'] += +product_data.amount - // goodsList.value.splice(edit_row.value,1) - // ElMessage({ - // message: '商品合并成功!', - // type: 'success', - // }) - // }) - // .catch(() => { - // ElMessage({ - // message: '商品合并已取消', - // type: 'info', - // }) - // }) - // } - // } } else { const {code,name,brand_info,price,sell_price,amount,note} = new_product product_data = { @@ -746,9 +744,9 @@ price, sell_price, weight: 0.000, - volume: 0.000, + volumn: 0.000, type:'other', - amount: parseInt(amount) ? parseInt(amount) : 1, + amount: parseInt(amount) ? +amount : 1, note, seller: '待定', seller_id: 0 @@ -781,13 +779,13 @@ }) } } - // Object.assign(goodsList.value[edit_row.value],add_data) + setSort() centerDialogVisible.value = false } const submit_product = async () => { - let row = goodsList.value[goodsList.value.length-1] - if(row.brand_info.id && row.brand != row.brand_info.id) { + let row = edit_data.value[0] + if(row.brand_info?.id && row.brand != row.brand_info?.id) { row.brand = row.brand_info.id row.b_name = row.brand_info.name } @@ -819,6 +817,10 @@ if(data.data && data.data.bid) { const {bid:id,code,short_code,cn_name,en_name,brand,b_name,price,dealer_price,order_price: sell_price,weight,volume,add_time} = data.data let product_data = { + brand_info: { + id: brand, + name: b_name + }, id, name: cn_name ? cn_name : en_name, code, @@ -836,27 +838,28 @@ seller_id: 0, add_time } - goodsList.value[goodsList.value.length-1] = Object.assign(goodsList.value[goodsList.value.length-1],product_data) + edit_data.value[0] = Object.assign({},product_data) } } } const pushRow = (row) => { if(row.type != 'other') { - let index = goodsList.value.filter((_,idx) => idx < goodsList.value.length-1).findIndex(item => item.id == row.id && item.type == row.type) + let index = goodsList.value.findIndex(item => item.id == row.id && item.type == row.type) if(index != -1) { - goodsList.value[index]['amount'] += row['amount'] + goodsList.value[index]['amount'] += +row['amount'] } else { - goodsList.value.splice(goodsList.value.length-1,0,row) + goodsList.value.push(row) } } else { - let index = goodsList.value.filter((_,idx) => idx < goodsList.value.length-1).findIndex(item => item.code == row.code && item.brand == row.brand && item.type == 'other') + let index = goodsList.value.findIndex(item => item.code == row.code && item.brand == row.brand && item.type == 'other') if(index != -1) { - goodsList.value[index]['amount'] += row['amount'] + goodsList.value[index]['amount'] += +row['amount'] } else { - goodsList.value.splice(goodsList.value.length-1,0,row) + goodsList.value.push(row) } } + setSort() } const reloadData = async (item) => { @@ -876,7 +879,7 @@ weight, volume, type: 'product', - amount: parseInt(item.amount) ? parseInt(item.amount) : 1, + amount: parseInt(item.amount) ? +item.amount : 1, note: item.note, seller: '预订产品', seller_id: 0, @@ -897,6 +900,7 @@ const reloadRow = async (idx) => { let item = goodsList.value[idx] Object.assign(goodsList.value[idx],await reloadData(item)) + setSort() } const refresh = async () => { @@ -907,55 +911,23 @@ } let data_arr = goods_data.map(item => ({brand: item.brand,code: item.code})) const { data:res } = await hasFocusBatch(data_arr) + for(let item of res.data) { + let idx = res.data.findIndex(it => it.brand == item.brand && it.code == item.code) + res.data[idx].focus = item.has_focus + } goodsList.value.forEach((item,idx) => { Object.assign(item,goods_data[idx]) }) - // for(let item of res.data) { - // let idx = goods_data.findIndex(it => it.brand == item.brand && it.code == item.code) - // goods_data[idx].focus = item.has_focus - // } - // let goods_hash = md5(JSON.stringify(goods_data)) - // if(goodsHash.value != goods_hash) { - // goodsList.value = goods_data - // } + setSort() loading.value = false } - const clearInput = () => { - goodsList.value[goodsList.value.length-1] = { - id: 0, - brand_info: {id: 0,name: ''}, - code: '', - new_code: '', - name: '', - b_name: '', - brand: 0, - price: 0, - sell_price: 0, - weight: 0.000, - volumn: 0.000, - amount: 1, - type: 'other', - seller: '待定', - seller_id: 0, - note: '' - } - } - - const moveUp = (index,row) => { - goodsList.value.splice(index-1,0,row) - goodsList.value.splice(index+1,1) - } - - const moveDown = (index,row) => { - goodsList.value.splice(index,1) - goodsList.value.splice(index+1,0,row) - } + const clearInput = () => edit_data.value = [Object.assign({}, baseItem)] const saveGoods = async () => { - await addInquiryGoods(order_id.value,goodsList.value.slice(0,-1)) + await addInquiryGoods(order_id.value,goodsList.value) await addLog(props.orderId,`${user_store.userName}(${user_store.userId})`,'修改商品',JSON.stringify(goodsList.value)) - goodsHash.value = md5(JSON.stringify(goodsList.value.slice(0,-1))) + goodsHash.value = md5(JSON.stringify(goodsList.value)) ElMessage({ message: "成功修改订单商品!", type: 'success', @@ -1066,6 +1038,38 @@ focusInfo.value.new_code = null focusDialogVisible.value = true } + + // 拖拽排序相关测试 + const goodsTableRef = ref(null); + let sortableInstance = null; + function setSort() { + nextTick(() => { + const tbody = goodsTableRef.value?.$el.querySelector(".el-table__body-wrapper tbody"); + if (!tbody) { + console.warn("tbody 不存在,拖拽初始化失败"); + return; + } + // 销毁旧实例 + if (sortableInstance) { + sortableInstance.destroy(); + } + // 创建新的拖拽实例 + sortableInstance = Sortable.create(tbody, { + handle: ".allowDrag", // 指定拖拽区域 + animation: 150, + onEnd: (evt) => { + const movedItem = goodsList.value.splice(evt.oldIndex, 1)[0]; + goodsList.value.splice(evt.newIndex, 0, movedItem); + }, + }); + }); + } + + // function handleSort() { + // if (sortableInstance) { + // sortableInstance.sort(goodsList.value.map(f => f.id)); + // } + // }