| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718 |
- <script setup lang="tsx">
- import { onMounted, reactive, ref } from 'vue'
- import { ContentWrap } from '@/components/ContentWrap'
- import {
- ElInput,
- FormInstance,
- // ElSwitch,
- ElTabPane,
- ElTabs,
- ElForm,
- ElFormItem,
- ElMessage,
- ElSelect,
- ElOption,
- ElTableColumn,
- ElTable,
- ElDrawer
- } from 'element-plus'
- import { useRoute, useRouter } from 'vue-router'
- import { goodsData, attrsValue } from '@/api/goods/types'
- import { AttrBaseItem } from '@/api/goods/types'
- import { UpImgButtom } from '@/components/UpFile'
- import { outData } from '@/api/erp/types'
- import {
- getStoreList,
- getStoreUser,
- getOutGood,
- storePutLoss,
- getLossType,
- getStoreGood,
- warePutLoss
- } from '@/api/erp'
- const pageTitle = ref('添加')
- const { params } = useRoute()
- const { push } = useRouter()
- const actinoTabIndex = ref(1)
- const selfBuild = reactive<outData>({
- type: 1,
- store_id: '',
- wid: '',
- create_admin_id: '',
- up_store_id: '',
- up_wid: '',
- product_list: []
- })
- const hzBuild = reactive<outData>({
- create_admin_id: '',
- store_id: '',
- up_store_id: '',
- product_list: []
- })
- const formData = reactive<goodsData & { attrs_value: attrsValue[]; keyword: string[] }>({
- // bar_code: '',
- product_type: 0,
- store_id: '',
- id: 0,
- store_name: '',
- video_open: 0,
- video_link: '',
- slider_image: [],
- image: [],
- store_info: '',
- keyword: [],
- cate_id: [],
- sales: 0,
- ficti: 0,
- spec_type: 0,
- is_show: 1,
- limit_num: 0,
- is_limit: 0,
- limit_type: 0,
- is_police: 0,
- shelf_life: 0,
- attrs: [],
- attrs_value: [], // 初始化为空数组
- sort: 0,
- description: '',
- show_type: 0,
- is_verify: 0,
- pay_qudou: 0,
- is_vip_product: 0,
- is_weigh: 0,
- specs: [],
- cost: 0
- })
- const attrs_value = reactive<
- attrsValue & {
- image: string[]
- }
- >({
- suk: '默认',
- image: [],
- stock: 0,
- detail: {},
- price: 0,
- ot_price: 0,
- cost: 0
- })
- const rules = reactive({
- create_admin_id: [{ required: true, message: '请选择创建人', trigger: 'change' }],
- wid: [{ required: true, message: '请选择仓库', trigger: 'change' }],
- store_id: [{ required: true, message: '请选择门店', trigger: 'change' }],
- })
- const formRef = ref<FormInstance>()
- const formRefs = ref<FormInstance>()
- const checkGoodss = ref<any[]>([])
- /**
- * 保存表单数据
- * 此函数在用户提交表单时被触发,它首先验证表单数据的有效性,如果有效则处理数据并调用相应的API进行保存
- * @param {FormInstance | undefined} formEl - 表单实例,用于表单验证和获取表单数据
- * @returns {Promise<Array>} - 返回一个空数组,当前函数没有实际返回值,但为了保持接口一致性,返回了空数组
- */
- const save = async (formEl: FormInstance | undefined) => {
- // 检查表单实例是否存在,如果不存在则返回空数组
- if (!formEl) return []
- // 验证表单数据,如果验证失败,则显示错误消息并中断保存流程
- const valid = await formEl.validate((valid, fields) => {
- if (valid) {
- } else {
- for (const key in fields) {
- ElMessage.error(fields[key][0].message)
- return
- }
- console.log('error submit!', fields)
- }
- })
- if (valid) {
- if (actinoTabIndex.value == 1) {
- let ok = true
- let good: any[] = []
- try {
- checkGoods.value.forEach((item) => {
- if (item.type == '') {
- ok = false
- return ElMessage.error('请选择报损理由')
- }
- if (!item.pur_number) {
- ok = false
- return ElMessage.error('请输入报损数量')
- }
- const choose = lossesType.value.find((e) => e.value == item.type)
- item.typeValue = choose.lable
- good.push(item)
- })
- if (!ok) {
- return
- }
- const res = await warePutLoss(0,{
- info: good,
- create_admin_id: selfBuild.create_admin_id,
- wid: selfBuild.wid,
- type: 'loss'
- })
- if (res.status == 200) {
- ElMessage.success('提交成功')
- }
- } catch (error) {
- console.log(error, 'error')
- }
- } else if (actinoTabIndex.value == 2) {
- let ok = true
- let good: any[] = []
- try {
- checkGoodss.value.forEach((item) => {
- if (item.typeValue == '' || item.type == '') {
- ok = false
- return ElMessage.error('请选择报损理由')
- }
- if (!item.pur_number) {
- ok = false
- return ElMessage.error('请输入报损数量')
- }
- const choose = lossesType.value.find((e) => e.value == item.type)
- item.typeValue = choose.lable
- item.suk = item.specs[0].name
- good.push(item)
- })
- if (!ok) {
- return
- }
- const res = await storePutLoss({
- info: good,
- create_admin_id: hzBuild.create_admin_id,
- store_id: hzBuild.store_id,
- type: 'loss'
- })
- if (res.status == 200) {
- ElMessage.success('提交成功')
- }
- } catch (error) {
- console.log(error, 'error')
- }
- }
- }
- }
- const loadingData = ref(false)
- const lossesType = ref<any[]>([])
- onMounted(async () => {
- //加载商品规格
- // ruleList()
- const res = await getLossType({ page: 1, limit: 100 })
- lossesType.value = res.data.map((item) => {
- return {
- value: item.type,
- label: item.name
- }
- })
- if (params.type == 'add') {
- pageTitle.value = '添加报损'
- }
- })
- const backList = () => {
- push('/erp/losses')
- }
- const storeLoading = ref(false)
- const storeOptions = ref<any[]>([])
- const getStore = async (query = '', id = '') => {
- try {
- storeLoading.value = true
- const res = await getStoreList({ page: 1, limit: 1000, name: query, id, store: 1 })
- if (res) {
- storeOptions.value = res.data.data.map((item) => {
- return {
- value: item.id,
- label: item.name
- }
- })
- } else {
- return []
- }
- } catch (error) {
- console.log(error)
- } finally {
- storeLoading.value = false
- }
- }
- let attrBase = reactive<AttrBaseItem[]>([
- {
- img: [], //图片
- bar_code: '', //产品编号
- price: 0, //售价
- num: 0,
- is_default: 0,
- price_1: 0,
- price_2: 0,
- price_3: 0,
- name: '',
- is_del: 0,
- rate: 0
- }
- ])
- const selectPic = ref<string[]>([]) //选中的图片
- const selectPicIndex = ref(0) //上传图片选择对象
- const selectPicObj = ref('header') //上传图片类型
- /**
- * 根据不同的图片选择对象类型,更新相应的图片数组
- * @param {string[]} pic - 要更新的图片数组
- */
- const changePic = (pic: string[]) => {
- console.log(pic, 'pic')
- // 根据选中的图片对象类型,更新对应的图片数组
- switch (selectPicObj.value) {
- case 'header':
- // 更新产品属性列表中的图片数组
- attrBase[selectPicIndex.value].img = pic
- break
- case 'attrBase':
- // 更新基础属性中的图片数组
- attrBase[0].img = pic
- break
- case 'banner':
- // 更新表单数据中的图片数组
- formData.image = pic
- break
- case 'attrOne':
- // 更新单规格的图片数组
- attrs_value.image = pic
- break
- default:
- // 其他情况不做处理
- break
- }
- }
- const widOptions = ref<any[]>([])
- const adminOptions = ref<any[]>([])
- const wareLoading = ref(false)
- const adminLoading = ref(false)
- const checkGoods = ref<any[]>([])
- const getWid = async (query = '', id = '') => {
- try {
- wareLoading.value = true
- const res = await getStoreList({ page: 1, limit: 1000, name: query, id, type: 3 })
- if (res) {
- widOptions.value = res.data.data.map((item) => {
- return {
- value: item.id,
- label: item.name
- }
- })
- } else {
- return []
- }
- } catch (error) {
- console.log(error)
- } finally {
- wareLoading.value = false
- }
- }
- const getAdmin = async () => {
- console.log(actinoTabIndex.value, 'actinoTabIndex')
- let id: any = 0
- if (actinoTabIndex.value == 1) {
- id = selfBuild.wid
- } else if (actinoTabIndex.value == 2) {
- id = hzBuild.store_id
- }
- const res = await getStoreUser({ page: 1, limit: 20, relation_id: id })
- // adminOptions.value = res.data.list
- if (res) {
- adminOptions.value = res.data.map((item) => {
- return {
- value: item.id,
- label: item.real_name
- }
- })
- } else {
- return []
- }
- }
- const fristCheck = ref([])
- const changeSw = () => {
- selfBuild.create_admin_id = ''
- }
- const handleSelectionChange = (e) => {
- fristCheck.value = e
- }
- // const
- // const handleSelectionChanges = (e) => {
- // fristChecks.value = e
- // }
- const handleCurrentChange = (e: number) => {
- getPurgood(e, '')
- }
- const cancelClick = () => {
- dialogVisible.value = false
- }
- const unique = (arr) => {
- return arr.filter((item, index, arr) => arr.findIndex((t) => t.id === item.id) === index)
- }
- const confirmClick = () => {
- // 关闭弹窗
- dialogVisible.value = false
- //合并选中去重
- fristCheck.value = fristCheck.value.map((item) => {
- Object.assign(item, { pur_number: '', weight: '' })
- return item
- })
- if (actinoTabIndex.value == 1) {
- checkGoods.value = unique(checkGoods.value.concat(fristCheck.value))
- } else if (actinoTabIndex.value == 2) {
- checkGoodss.value = unique(checkGoodss.value.concat(fristCheck.value))
- }
- }
- const goods = ref([])
- const count = ref(0)
- const keyword = ref('')
- const currentPage = ref(0)
- const pageSize = ref(10)
- const dialogVisible = ref(false)
- const getPurgood = async (page = 1, key = '') => {
- if (key == 're') {
- keyword.value = ''
- }
- let qData: {
- key: string
- page: number
- limit: number
- store_id?: any
- wid?: any
- type: any
- up_wid?: any
- } = {
- type: '',
- store_id: '',
- wid: '',
- key: keyword.value,
- page: page,
- limit: 10,
- up_wid: ''
- }
- if (actinoTabIndex.value == 1) {
- if (!selfBuild.wid) {
- return ElMessage.error('请选仓库')
- }
- qData.up_wid = selfBuild.wid
- qData.type = 0
- const res = await getOutGood(qData)
- goods.value = res.data.data
- count.value = res.data.count
- dialogVisible.value = true
- } else if (actinoTabIndex.value == 2) {
- if (!hzBuild.store_id) {
- return ElMessage.error('请选门店')
- }
- qData.store_id = hzBuild.store_id
- // const res = await getProduct(qData)
- const res = await getStoreGood(qData)
- goods.value = res.data.data
- count.value = res.data.count
- dialogVisible.value = true
- }
- }
- const delCheckGoods = (row) => {
- console.log(row)
- let set1 = new Set(checkGoods.value)
- let set2 = new Set([row])
- checkGoods.value = Array.from(set1.difference(set2))
- }
- const delCheckGoodss = (row) => {
- console.log(row)
- let set1 = new Set(checkGoodss.value)
- let set2 = new Set([row])
- checkGoodss.value = Array.from(set1.difference(set2))
- }
- </script>
- <template>
- <ContentWrap
- :title="pageTitle"
- class="!min-h-[calc(100vh-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height)-var(--app-content-padding))]"
- >
- <template #header>
- <BaseButton size="small" @click="backList"> 返回列表 </BaseButton>
- </template>
- <ElTabs v-model="actinoTabIndex" type="border-card">
- <ElTabPane label="仓库报损" :name="1">
- <ElForm
- v-loading="loadingData"
- ref="formRef"
- :model="selfBuild"
- :rules="rules"
- label-width="100px"
- >
- <ElFormItem label="仓库" prop="wid">
- <ElSelect
- filterable
- remote
- reserve-keyword
- v-model="selfBuild.wid"
- :remote-method="getWid"
- :loading="wareLoading"
- remote-show-suffix
- placeholder="请选择仓库"
- @change="changeSw"
- >
- <ElOption
- v-for="item in widOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </ElSelect>
- </ElFormItem>
- <ElFormItem label="创建人员" prop="create_admin_id" v-if="selfBuild.wid">
- <ElSelect
- filterable
- remote
- reserve-keyword
- :disabled="params.type == 'edit'"
- v-model="selfBuild.create_admin_id"
- :remote-method="getAdmin"
- :loading="adminLoading"
- remote-show-suffix
- placeholder="请选择创建人员"
- >
- <ElOption
- v-for="item in adminOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </ElSelect>
- </ElFormItem>
- <ElFormItem label="报损商品">
- <BaseButton type="primary" style="margin-bottom: 20px" @click="getPurgood(1, '')">
- 选择商品
- </BaseButton>
- <ElTable
- header-cell-class-name="bg-gray-100!"
- :data="checkGoods"
- class="w-100%"
- :border="true"
- stripe
- >
- <ElTableColumn prop="product_id" label="ID"> </ElTableColumn>
- <ElTableColumn prop="product_name" label="名称"> </ElTableColumn>
- <ElTableColumn prop="suk" label="单位"></ElTableColumn>
- <ElTableColumn prop="product_num" label="库存"></ElTableColumn>
- <ElTableColumn prop="pur_number" label="报损原因" min-width="220px">
- <template #header> <span>报损原因</span><span class="text-red">*</span> </template>
- <template #default="{ row }">
- <ElSelect
- v-model="row.type"
- class="m-2"
- placeholder="请选择报损原因"
- size="large"
- style="width: 200px"
- >
- <ElOption
- v-for="item in lossesType"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </ElSelect>
- </template>
- </ElTableColumn>
- <ElTableColumn prop="pur_number" label="报损数量">
- <template #header> <span>报损数量</span><span class="text-red">*</span> </template>
- <template #default="{ row }">
- <ElInput type="number" v-model="row.pur_number" />
- </template>
- </ElTableColumn>
- <ElTableColumn prop="action" label="操作">
- <template #default="{ row }">
- <!-- <div type="text">{{ row.specs.num || 0 }}</div> -->
- <BaseButton link size="small" type="primary" @click="delCheckGoods(row)"
- >删除</BaseButton
- >
- </template></ElTableColumn
- >
- </ElTable>
- </ElFormItem>
- </ElForm>
- </ElTabPane>
- <ElTabPane label="门店报损" :name="2">
- <ElForm
- v-loading="loadingData"
- ref="formRefs"
- :model="hzBuild"
- :rules="rules"
- label-width="100px"
- >
- <ElFormItem label="门店" prop="store_id">
- <ElSelect
- filterable
- remote
- reserve-keyword
- :disabled="params.type == 'edit'"
- v-model="hzBuild.store_id"
- :remote-method="getStore"
- :loading="storeLoading"
- remote-show-suffix
- placeholder="请选择门店"
- @change="changeSw"
- >
- <ElOption
- v-for="item in storeOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </ElSelect>
- </ElFormItem>
- <ElFormItem label="创建人员" prop="create_admin_id" v-if="hzBuild.store_id">
- <ElSelect
- filterable
- remote
- reserve-keyword
- :disabled="params.type == 'edit'"
- v-model="hzBuild.create_admin_id"
- :remote-method="getAdmin"
- :loading="adminLoading"
- remote-show-suffix
- placeholder="请选择创建人员"
- >
- <ElOption
- v-for="item in adminOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </ElSelect>
- </ElFormItem>
- <ElFormItem label="报损商品">
- <BaseButton type="primary" style="margin-bottom: 20px" @click="getPurgood(1, '')">
- 添加商品
- </BaseButton>
- <ElTable
- header-cell-class-name="bg-gray-100!"
- :data="checkGoodss"
- class="w-100%"
- :border="true"
- stripe
- >
- <ElTableColumn prop="id" label="ID"> </ElTableColumn>
- <ElTableColumn prop="store_name" label="名称"> </ElTableColumn>
- <ElTableColumn prop="specs[0].name" label="单位"></ElTableColumn>
- <ElTableColumn prop="stock" label="库存"></ElTableColumn>
- <ElTableColumn prop="pur_number" label="报损原因" min-width="220px">
- <template #header> <span>报损原因</span><span class="text-red">*</span> </template>
- <template #default="{ row }">
- <ElSelect
- v-model="row.type"
- class="m-2"
- placeholder="请选择报损原因"
- size="large"
- style="width: 200px"
- >
- <ElOption
- v-for="item in lossesType"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </ElSelect>
- </template>
- </ElTableColumn>
- <ElTableColumn prop="pur_number" label="报损数量">
- <template #header> <span>报损数量</span><span class="text-red">*</span> </template>
- <template #default="{ row }">
- <ElInput type="number" v-model="row.pur_number" />
- </template>
- </ElTableColumn>
- <ElTableColumn prop="action" label="操作">
- <template #default="{ row }">
- <!-- <div type="text">{{ row.specs.num || 0 }}</div> -->
- <BaseButton link size="small" type="primary" @click="delCheckGoodss(row)"
- >删除</BaseButton
- >
- </template></ElTableColumn
- >
- </ElTable>
- </ElFormItem>
- </ElForm>
- </ElTabPane>
- </ElTabs>
- <ElDrawer v-model="dialogVisible" title="选择商品" size="700px">
- <div class="mb5">
- <ElInput v-model="keyword" style="width: 200px" placeholder="输入商品名称搜索" />
- <BaseButton type="primary" class="ml2" @click="getPurgood(1, '')"> 搜索 </BaseButton>
- <BaseButton @click="getPurgood(1, 're')"> 重置 </BaseButton>
- </div>
- <ElTable
- header-cell-class-name="bg-gray-100!"
- :data="goods"
- class="w-100%"
- :border="true"
- stripe
- @selection-change="handleSelectionChange"
- >
- <template v-if="actinoTabIndex == 1">
- <ElTableColumn type="selection" width="55" />
- <ElTableColumn prop="product_name" label="名称"> </ElTableColumn>
- <ElTableColumn prop="suk" label="单位"></ElTableColumn>
- <ElTableColumn prop="product_num" label="库存"></ElTableColumn>
- </template>
- <template v-if="actinoTabIndex == 2">
- <ElTableColumn type="selection" width="55" />
- <ElTableColumn prop="store_name" label="名称"> </ElTableColumn>
- <ElTableColumn prop="specs[0].name" label="单位"></ElTableColumn>
- <ElTableColumn prop="stock" label="库存"></ElTableColumn>
- </template>
- </ElTable>
- <div style="height: 20px"></div>
- <ElPagination
- v-model:current-page="currentPage"
- v-model:page-size="pageSize"
- :page-sizes="[2, 3, 4, 5]"
- layout="total, prev, pager, next, jumper"
- :total="count"
- @current-change="handleCurrentChange"
- />
- <template #footer>
- <div style="flex: auto">
- <BaseButton @click="cancelClick">取消</BaseButton>
- <BaseButton type="primary" @click="confirmClick">确认</BaseButton>
- </div>
- </template>
- </ElDrawer>
- <UpImgButtom
- class="pos-absolute left-[-200px]"
- ref="upImageButtomRef"
- v-model="selectPic"
- @change="changePic"
- />
- </ContentWrap>
- <div
- class="text-center border-t-1px border-solid border-gray-200 py-10px mt-10px position-sticky bottom-0 left-0 right-0 bg-white"
- >
- <!-- <BaseButton v-if="params.type == 'edit'" @click="save(formRef)"> 保存 </BaseButton> -->
- <BaseButton v-if="params.type == 'add' && actinoTabIndex == 1" @click="save(formRef)">
- 保存</BaseButton
- >
- <BaseButton v-if="params.type == 'add' && actinoTabIndex == 2" @click="save(formRefs)">
- 保存</BaseButton
- >
- </div>
- </template>
|