Browse Source

fix 仓库区域设置&图书上传图片等

haveyou 1 year ago
parent
commit
b2328b6295

+ 1 - 1
src/components/CommonPage/CommonTable.vue

@@ -63,7 +63,7 @@
   /** 表格数据源 */
   const datasource = ({ pages, where, orders }) => {
     let initKeys = props.pageConfig.params || {};
-    return queryPage({ ...where, ...orders, ...pages, ...initKeys });
+    return queryPage({ ...initKeys, ...where, ...orders, ...pages });
   };
 
   /** 搜索 */

+ 11 - 0
src/styles/index.scss

@@ -124,6 +124,16 @@ body {
   }
 }
 
+//上传组件样式
+.upload-image {
+  margin-right: 10px;
+
+  .el-upload {
+    width: 100px;
+    height: 100px;
+  }
+}
+
 //表单下编辑器样式
 .simple-form {
   .tox-tinymce {
@@ -148,6 +158,7 @@ body {
   .el-text {
     align-self: flex-start;
   }
+
   //toolbar的状态选择
   .ele-toolbar-body {
     .el-radio-group {

+ 57 - 0
src/views/data/books/components/book-base-info.vue

@@ -0,0 +1,57 @@
+<template>
+  <div class="recycle-order-number flex flex-col items-start ml-6">
+    <div class="common-text cursor-pointer">
+      <el-text type="primary" @click="handleClick(row)">{{
+        row.bookName
+      }}</el-text>
+    </div>
+    <div class="flex justify-between items-start">
+      <div class="flex flex-col items-start">
+        <div class="common-text">
+          <el-text>ISBN:</el-text>
+          <el-text>{{ row.isbn }}</el-text>
+        </div>
+        <div class="common-text">
+          <el-text>作 者:</el-text>
+          <el-text>{{ row.author || '-' }} </el-text>
+        </div>
+        <div class="common-text">
+          <el-text>出版社:</el-text>
+          <el-text>{{ row.publish || '-' }}</el-text>
+        </div>
+      </div>
+      <div class="flex flex-col items-start ml-20">
+        <div class="common-text">
+          <el-text>定价:</el-text>
+          <el-text>¥ {{ row.price }}</el-text>
+        </div>
+        <div class="common-text">
+          <el-text>出版时间:</el-text>
+          <el-text
+            >{{ row.pubDate ? dayjs(row.pubDate).format('YYYY-MM-DD') : '-' }}
+          </el-text>
+        </div>
+        <div class="common-text">
+          <el-text>分类:</el-text>
+          <el-text>{{ row.bookTagName || '-' }}</el-text>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+  import { dayjs } from 'element-plus';
+  const emit = defineEmits(['click']);
+
+  const props = defineProps({
+    row: {
+      type: Object,
+      default: () => {}
+    }
+  });
+
+  function handleClick(row) {
+    emit('click', row);
+  }
+</script>

+ 0 - 0
src/views/data/books/components/book-export-log.vue


+ 0 - 0
src/views/data/books/components/book-import-log.vue


+ 141 - 0
src/views/data/books/components/upload-image.vue

@@ -0,0 +1,141 @@
+<!-- 编辑弹窗 -->
+<template>
+  <ele-modal :width="940" v-model="visible" title="上传图片">
+    <el-form :model="form" label-width="auto">
+      <el-form-item>
+        <div class="flex justify-between items-center w-full">
+          <div class="flex items-center flex-1">
+            <el-checkbox v-model="checkAll" @change="handleCheckAllChange">
+              全选
+            </el-checkbox>
+
+            <el-text style="margin: 0 30px"
+              >共有{{ form.images.length }}条</el-text
+            >
+
+            <el-radio-group v-model="radio">
+              <el-radio :value="1">相同文件名覆盖</el-radio>
+              <el-radio :value="2">相同文件名忽略</el-radio>
+            </el-radio-group>
+          </div>
+          <div>
+            <el-button type="danger" @click="handleBatchDelete">删除</el-button>
+            <el-button type="primary" @click="handleSubmit">提交</el-button>
+          </div>
+        </div>
+      </el-form-item>
+      <el-form-item>
+        <el-checkbox-group v-model="checkList" class="flex flex-wrap">
+          <el-upload
+            class="upload-image"
+            ref="uploadRef"
+            v-model:file-list="form.images"
+            action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
+            list-type="picture-card"
+            :auto-upload="false"
+            :show-file-list="false"
+            multiple
+          >
+            <div class="flex flex-col items-center">
+              <el-icon :size="24"><Plus /></el-icon>
+              <el-text type="info" style="margin-top: 20px">上传图片</el-text>
+            </div>
+          </el-upload>
+          <div
+            class="flex flex-wrap pos-relative image-item"
+            v-for="item in form.images"
+          >
+            <el-checkbox :value="item.uid" class="checkbox-item"></el-checkbox>
+            <el-image
+              style="width: 98px; height: 98px"
+              :src="item.url"
+              fit="cover"
+            />
+          </div>
+        </el-checkbox-group>
+      </el-form-item>
+    </el-form>
+  </ele-modal>
+</template>
+
+<script setup>
+  import { ref, reactive, nextTick } from 'vue';
+  import ImageUpload from '@/components/ImageUpload/index.vue';
+  import { Plus } from '@element-plus/icons-vue';
+  import request from '@/utils/request';
+  import { ElMessage } from 'element-plus';
+
+  const form = reactive({
+    images: [],
+    radio: 1
+  });
+  /** 弹窗是否打开 */
+  const visible = defineModel({ type: Boolean });
+  const radio = ref(1);
+  /** 关闭弹窗 */
+  const handleCancel = () => {
+    visible.value = false;
+  };
+
+  //选择的文件
+  const checkList = ref([]);
+
+  /** 弹窗打开事件 */
+  const handleOpen = () => {
+    visible.value = true;
+    nextTick(() => {
+      checkAll.value = false;
+      checkList.value = [];
+      form.images = [];
+    });
+  };
+
+  const uploadRef = ref(null);
+  //批量删除
+  function handleBatchDelete() {
+    let checkFiles = form.images.filter((item) =>
+      checkList.value.includes(item.uid)
+    );
+    checkFiles.forEach((file) => {
+      uploadRef.value?.handleRemove(file);
+    });
+  }
+
+  const checkAll = ref(false);
+  function handleCheckAllChange() {
+    checkList.value = checkAll.value ? form.images.map((item) => item.uid) : [];
+  }
+
+  function handleSubmit() {
+    const formData = new FormData();
+    form.images.forEach((file) => {
+      formData.append('files', file.raw); //文件
+    });
+
+    request.post('/common/uploads', formData).then((res) => {
+      if (res.data.code === 200) {
+        visible.value = false;
+        ElMessage.success('上传成功');
+      }
+    });
+  }
+
+  defineExpose({
+    handleOpen
+  });
+</script>
+
+<style lang="scss">
+  .image-item {
+    margin-right: 10px;
+    margin-bottom: 10px;
+    position: relative;
+    border-radius: 6px;
+    border: 1px solid #e4e7ed;
+    .checkbox-item {
+      position: absolute;
+      top: -8px;
+      left: 0;
+    }
+  }
+</style>

+ 61 - 52
src/views/data/books/index.vue

@@ -38,7 +38,34 @@
           @click="handleExportExcel"
           :icon="DownloadOutlined"
         >
-          导出图书明细
+          查询结果导出
+        </el-button>
+        <el-button
+          type="primary"
+          plain
+          v-permission="'data:books:uploadImage'"
+          @click="handleUploadImage"
+          :icon="CloudUploadOutlined"
+        >
+          上传图片
+        </el-button>
+        <el-button
+          type="info"
+          plain
+          v-permission="'data:books:importLog'"
+          @click="handleImportLog"
+          :icon="LogOutlined"
+        >
+          导入记录
+        </el-button>
+        <el-button
+          type="info"
+          plain
+          v-permission="'data:books:exportLog'"
+          @click="handleExportLog"
+          :icon="LogOutlined"
+        >
+          导出记录
         </el-button>
       </template>
       <template #cover="{ row }">
@@ -50,43 +77,26 @@
       </template>
 
       <template #baseInfo="{ row }">
-        <div class="base-info flex flex-col items-start">
-          <div class="common-text">
-            <el-text>书 名:</el-text>
-            <el-text type="success">{{ row.bookName || '-' }}</el-text>
-          </div>
-          <div class="common-text">
-            <el-text>条 码:</el-text>
-            <el-text>{{ row.isbn || '-' }}</el-text>
-          </div>
-          <div class="common-text">
-            <el-text>作 者:</el-text>
-            <el-text>{{ row.author || '-' }} </el-text>
-          </div>
-          <div class="common-text">
-            <el-text>出版社:</el-text>
-            <el-text>{{ row.publish || '-' }}</el-text>
-          </div>
-        </div>
+        <book-base-info :row="row" @click="handleUpdate"></book-base-info>
       </template>
 
       <template #action="{ row }">
         <div>
           <el-button
-            type="primary"
+            type="warning"
             link
             v-permission="'data:books:changeLogs'"
             @click="handleChangeLogs(row)"
           >
-            变动记录
+            [变动记录]
           </el-button>
           <el-button
-            type="primary"
+            type="success"
             link
             v-permission="'data:books:update'"
             @click="handleUpdate(row)"
           >
-            编辑
+            [编辑]
           </el-button>
         </div>
       </template>
@@ -94,6 +104,7 @@
     <books-edit ref="editRef" @success="reload()"></books-edit>
     <books-import ref="importRef" v-model="showImport"></books-import>
     <books-change-log ref="changeLogRef"></books-change-log>
+    <upload-image ref="uploadImageRef"></upload-image>
   </ele-page>
 </template>
 
@@ -103,18 +114,24 @@
     PlusOutlined,
     DeleteOutlined,
     DownloadOutlined,
-    UploadOutlined
+    UploadOutlined,
+    LogOutlined,
+    CloudUploadOutlined
   } from '@/components/icons';
   import { dayjs } from 'element-plus';
   import CommonTable from '@/components/CommonPage/CommonTable.vue';
   import booksEdit from '@/views/data/books/components/books-edit.vue';
   import booksSearch from '@/views/data/books/components/books-search.vue';
-  import booksImport from '@/views/data/books/components/books-import.vue'
-  import booksChangeLog from '@/views/data/books/components/books-change-log.vue'
+  import booksImport from '@/views/data/books/components/books-import.vue';
+  import booksChangeLog from '@/views/data/books/components/books-change-log.vue';
+  import bookBaseInfo from '@/views/data/books/components/book-base-info.vue';
+  import uploadImage from '@/views/data/books/components/upload-image.vue';
   import { useDictData } from '@/utils/use-dict-data';
 
   defineOptions({ name: 'recycleOrderCancelled' });
 
+  const [perCheckDicts] = useDictData(['is_common_yes']);
+
   /** 表格列配置 */
   const columns = ref([
     {
@@ -128,45 +145,26 @@
       label: '图片',
       prop: 'cover',
       slot: 'cover',
-      align: 'center',
-      minWidth: 100
+      align: 'center'
     },
     {
       label: '基础信息',
       prop: 'baseInfo',
       slot: 'baseInfo',
       align: 'center',
-      minWidth: 300
-    },
-    {
-      label: '定价',
-      prop: 'price',
-      formatter: (row) => (row.price ? '¥ ' + row.price : '-'),
-      align: 'center'
-    },
-    {
-      label: '出版时间',
-      prop: 'pubDate',
-      align: 'center',
-      minWidth: 120,
-      formatter: (row) => dayjs(row.pubDate).format('YYYY-MM-DD')
-    },
-    {
-      label: '分类标签',
-      prop: 'tag',
-      formatter: (row) => '教材',
-      align: 'center'
+      minWidth: 320
     },
     {
       label: '人工核实',
-      prop: 'peo',
-      formatter: (row) => '是',
+      prop: 'perCheck',
+      formatter: (row) =>
+        perCheckDicts.value.find((d) => d.dictValue == row.perCheck)?.dictLabel,
       align: 'center'
     },
     {
       columnKey: 'action',
       label: '操作',
-      width: 180,
+      width: 200,
       align: 'center',
       slot: 'action'
     }
@@ -202,7 +200,7 @@
   function handleBatchDelete(row) {
     let selections = row ? [row] : pageRef.value?.getSelections();
     let ids = selections.map((item) => item.id).join(',');
-    console.log(ids,selections)
+    console.log(ids, selections);
     let url = `/book/bookInfo/removeById/${ids}`;
     pageRef.value?.operatBatch({
       title: '确认删除?',
@@ -224,4 +222,15 @@
     changeLogRef.value?.handleOpen(row);
   }
 
+  //上传图片
+  const uploadImageRef = ref(null);
+  function handleUploadImage() {
+    uploadImageRef.value?.handleOpen();
+  }
+
+  //导出记录
+  function handleExportLog() {}
+  //导入记录
+  function handleImportLog() {}
+
 </script>

+ 216 - 10
src/views/recycleLogistics/warehouse/components/area-setting.vue

@@ -3,10 +3,86 @@
   <ele-modal
     form
     :width="1080"
+    :bodyStyle="{ 'min-height': '400px' }"
     v-model="visible"
     title="仓库区域设置"
     @open="handleOpen"
   >
+    <div class="flex flex-col" v-loading="loading">
+      <div class="flex" v-for="dq in areaList" :key="dq.code">
+        <el-checkbox
+          :label="dq.name"
+          :indeterminate="isIndeterminateShow(dq)"
+          style="min-width: 100px"
+          @change="(value) => handleDqChange(value, dq)"
+        ></el-checkbox>
+
+        <div v-for="item in dq.children" class="mr-6 flex items-center">
+          <el-checkbox
+            @change="(value) => handleParentChange(value, item)"
+            :data-id="item.id"
+            v-model="item.otherSelected"
+            style="margin-right: 5px"
+            :true-value="1"
+            :false-value="0"
+            v-if="item.otherSelected == 1"
+            disabled
+          ></el-checkbox>
+          <el-checkbox
+            @change="(value) => handleParentChange(value, item)"
+            :data-id="item.id"
+            v-model="item.mySelected"
+            style="margin-right: 5px"
+            :true-value="1"
+            :false-value="0"
+            v-else
+          ></el-checkbox>
+          <ele-popover
+            :width="400"
+            trigger="click"
+            :title="item.district"
+            :showArrow="false"
+            :disabled="isPopoverDisabled(item)"
+          >
+            <template #reference>
+              <div
+                class="flex items-center cursor-pointer"
+                :class="{ 'disabled-popover': isPopoverDisabled(item) }"
+              >
+                <el-text :type="item.mySelected == 1 ? 'primary' : ''">{{
+                  item.district
+                }}</el-text>
+                <el-text type="warning" v-if="isShowAll(item)">(全)</el-text>
+                <el-icon><CaretBottom /></el-icon>
+              </div>
+            </template>
+            <template v-for="child in item.childInfo">
+              <el-checkbox
+                @change="(value) => handleChildChange(value, item, child)"
+                :data-id="child.id"
+                :label="child.district"
+                v-model="child.otherSelected"
+                :true-value="1"
+                :false-value="0"
+                v-if="child.otherSelected == 1"
+                disabled
+              ></el-checkbox>
+              <el-checkbox
+                v-else
+                @change="(value) => handleChildChange(value, item, child)"
+                :data-id="child.id"
+                v-model="child.mySelected"
+                :label="child.district"
+                :true-value="1"
+                :false-value="0"
+              ></el-checkbox>
+            </template>
+          </ele-popover>
+        </div>
+      </div>
+    </div>
+    <el-text type="danger">灰色地区表示已经添加到其他仓库中,请先在其他仓库中去掉勾选后,再重新选择</el-text>
+
     <template #footer>
       <el-button @click="handleCancel">关闭</el-button>
       <el-button type="primary" @click="handleSubmit">确定</el-button>
@@ -17,6 +93,7 @@
 <script setup>
   import { ref, reactive, nextTick } from 'vue';
   import request from '@/utils/request';
+  import { CaretBottom, CaretTop } from '@element-plus/icons-vue';
 
   /** 弹窗是否打开 */
   const visible = defineModel({ type: Boolean });
@@ -26,26 +103,142 @@
     visible.value = false;
   };
 
+  //计算是否禁用
+  const isPopoverDisabled = computed(() => (item) => {
+    let checked = item.childInfo.every((i) => i.otherSelected == 1);
+    return checked;
+  });
+
+  //计算是否显示全
+  const isShowAll = computed(() => (item) => {
+    let checked = item.childInfo.every((i) => i.mySelected == 1);
+    return checked;
+  });
+  //计算大区是否全选
+  const isIndeterminateShow = computed(() => (dq) => {
+    let len = dq.children.length;
+    let length = dq.children.filter((i) => i.mySelected == 1).length;
+
+    return length > 0 && length < len;
+  });
+
   /** 弹窗打开事件 */
   const handleOpen = (row) => {
     visible.value = true;
     nextTick(() => {
-        getAreaInfo();
+      row && getAreaInfo(row.id);
     });
   };
 
-  /** 提交 */
-  const handleSubmit = () => {
-    visible.value = false;
-  };
+  let formdata = reactive({
+    godownId: '',
+    selectendList: [{ provinceId: '', cityId: '' }]
+  });
 
   //获取区域基础数据信息
-  const getAreaInfo = () => {
-    request.get('/system/area/list').then((res) => {
-      console.log(res, '区域基础数据信息');
+  let dqList = ref([
+    { name: '华东', code: 'hd' },
+    { name: '华北', code: 'hb' },
+    { name: '华中', code: 'hz' },
+    { name: '华南', code: 'hn' },
+    { name: '东北', code: 'db' },
+    { name: '西北', code: 'xb' },
+    { name: '西南', code: 'xn' },
+    { name: '港澳台', code: 'gat' },
+    { name: '海外', code: 'hw' }
+  ]);
+  const areaList = ref([]);
+  const loading = ref(false);
+  const getAreaInfo = (godownId) => {
+    formdata.godownId = godownId;
+    loading.value = true;
+    request
+      .get(`/baseinfo/godown/getGodownAreaList/${godownId}`)
+      .then((res) => {
+        if (res.data.code == 200) {
+          areaList.value.length = 0;
+          dqList.value.forEach((item) => {
+            item.checked = false;
+            item.children = res.data.data[item.code];
+            areaList.value.push(item);
+          });
+        }
+      })
+      .finally(() => (loading.value = false));
+  };
+
+  //区域checkbox改变事件
+  const handleDqChange = (value, dq) => {
+    if (value == 1) {
+      dq.children.forEach((item) => {
+        if (item.otherSelected != 1) {
+          item.mySelected = 1;
+          item.childInfo.forEach((i) => {
+            if (i.otherSelected != 1) {
+              i.mySelected = 1;
+            }
+          });
+        }
+      });
+    } else if (value == 0) {
+      dq.children.forEach((item) => {
+        if (item.otherSelected != 1) {
+          item.mySelected = 0;
+          item.childInfo.forEach((i) => {
+            if (i.otherSelected != 1) {
+              i.mySelected = 1;
+            }
+          });
+        }
+      });
+    }
+  };
+
+  //父级checkbox改变事件
+  const handleParentChange = (value, item) => {
+    if (value == 1) {
+      item.childInfo.forEach((i) => {
+        i.mySelected = 1;
+      });
+    } else if (value == 0) {
+      item.childInfo.forEach((i) => {
+        i.mySelected = 0;
+      });
+    }
+  };
+  //子级checkbox改变事件
+  const handleChildChange = (value, item, child) => {
+    let checked = item.childInfo.some((i) => i.mySelected == 1);
+    item.mySelected = checked ? 1 : 0;
+  };
+
+  //格式化选中数据
+  const formatterSelected = () => {
+    let arr = [];
+    areaList.value.forEach((item) => {
+      item.children.forEach((i) => {
+        i.childInfo.forEach((j) => {
+          if (j.mySelected == 1 && j.otherSelected != 1) {
+            arr.push({
+              provinceId: i.id,
+              cityId: j.id
+            });
+          }
+        });
+      });
     });
-    request.get('/system/area/pagelist').then((res) => {
-      console.log(res, '区域基础数据信息');
+    return arr;
+  };
+
+  /** 提交 */
+  const handleSubmit = () => {
+    formdata.selectendList = formatterSelected();
+    console.log(formdata);
+    let data = JSON.parse(JSON.stringify(formdata));
+    request.post(`/baseinfo/godown/setGodownAreaInfo`, data).then((res) => {
+      if (res.data.code == 200) {
+        visible.value = false;
+      }
     });
   };
 
@@ -53,3 +246,16 @@
     handleOpen
   });
 </script>
+
+<style lang="scss">
+  .disabled-popover {
+    cursor: not-allowed;
+    .el-text{
+        color: #909399;
+    }
+    .el-icon{
+        color: #909399;
+        fill: #909399;
+    }
+  }
+</style>

+ 2 - 2
src/views/recycleLogistics/warehouse/components/warehouse-edit.vue

@@ -121,8 +121,8 @@
   });
   //默认值
   const baseUrl = reactive({
-    add: '/system/info/add',
-    update: '/system/info/update'
+    add: '/baseinfo/godown/add',
+    update: '/baseinfo/godown/update'
   });
   const formData = ref({
     useStatus: '1',

+ 7 - 7
src/views/recycleLogistics/warehouse/index.vue

@@ -114,8 +114,8 @@
   const [useStatusDicts] = useDictData(['use_status']);
 
   const useStatus = ref('1');
-  function handleStatusChange() {
-    pageRef.value.reload({ useStatus: useStatus.value });
+  function handleStatusChange(value) {
+    pageRef.value.reload({ useStatus: value });
   }
 
   /** 表格列配置 */
@@ -185,8 +185,8 @@
   const pageRef = ref(null);
 
   const pageConfig = reactive({
-    pageUrl: '/system/info/pagelist',
-    exportUrl: '/system/info/export',
+    pageUrl: '/baseinfo/godown/pagelist',
+    exportUrl: '/baseinfo/godown/export',
     fileName: '仓库管理',
     cacheKey: 'warehouseTable',
     params: { useStatus: 1 }
@@ -208,7 +208,7 @@
     })
       .then(() => {
         data[key] = value;
-        request.post('/system/info/update', data).then((res) => {
+        request.post('/baseinfo/godown/update', data).then((res) => {
           if (res.data.code === 200) {
             EleMessage.success('操作成功');
             reload();
@@ -226,7 +226,7 @@
   function handleBatchDelete(row) {
     let selections = row ? [row] : pageRef.value?.getSelections();
     let ids = selections.map((item) => item.id).join(',');
-    let url = `/system/info/delete/${ids}`;
+    let url = `/baseinfo/godown/delete`;
     pageRef.value?.operatBatch({
       title: '确认删除?',
       method: 'delete',
@@ -246,7 +246,7 @@
     data.useStatus = row.useStatus == 1 ? 0 : 1;
     pageRef.value?.messageBoxConfirm({
       message,
-      fetch: () => request.post('/system/info/update', data)
+      fetch: () => request.post('/baseinfo/godown/update', data)
     });
   }
 

+ 1 - 1
src/views/recycleOrder/detail/order-base-info.vue

@@ -86,7 +86,7 @@
     { label: '订单编号', prop: 'orderNumber' },
     { label: '订单来源', prop: 'orderSource' },
     { label: '用户', prop: 'user' },
-    { label: '预书款', prop: 'estimatedPayment' },
+    { label: '预书款', prop: 'estimatedPayment' },
     { label: '审核书款', prop: 'reviewedPayment' },
     { label: '下单时间', prop: 'orderTime' },
     { label: '交易状态', prop: 'transactionStatus' }

+ 2 - 2
src/views/recycleOrder/detail/order-book-list.vue

@@ -51,10 +51,10 @@
           </div>
           <div class="common-text flex">
             <el-text>回收折扣:</el-text>
-            <el-text>¥ 0.35</el-text>
+            <el-text>¥ 0.35</el-text>
           </div>
           <div class="common-text flex">
-            <el-text>预估金额:</el-text>
+            <el-text>预估金额:</el-text>
             <el-text>¥ 1.61</el-text>
           </div>
           <div class="common-text flex">