Parcourir la source

add 回收书单页面

haveyou il y a 1 an
Parent
commit
d381fe67ee
31 fichiers modifiés avec 2523 ajouts et 6 suppressions
  1. 58 0
      src/components/CommonPage/EleInput.vue
  2. 75 0
      src/components/CommonPage/InputNumberRange.vue
  3. 5 6
      src/components/CommonPage/ProSearch2.vue
  4. 11 0
      src/components/ProForm/components/pro-form-item.vue
  5. 10 0
      src/styles/index.scss
  6. 241 0
      src/views/recycle/bookTypes/index.vue
  7. 339 0
      src/views/recycle/booklist/index.vue
  8. 45 0
      src/views/recycle/components/book-info.vue
  9. 32 0
      src/views/recycle/components/book-other-info.vue
  10. 77 0
      src/views/recycle/components/book-search.vue
  11. 29 0
      src/views/recycle/components/book-stock.vue
  12. 97 0
      src/views/recycle/components/set-params.vue
  13. 65 0
      src/views/recycle/globalParameter/components/has-add-recycle-booklist.vue
  14. 65 0
      src/views/recycle/globalParameter/components/not-add-recycle-booklist.vue
  15. 19 0
      src/views/recycle/globalParameter/index.vue
  16. 14 0
      src/views/recycle/independentParameter/index.vue
  17. 216 0
      src/views/recycle/orderAlert/index.vue
  18. 36 0
      src/views/recycle/orderSetting/components/auto-audit-settings.vue
  19. 76 0
      src/views/recycle/orderSetting/components/auto-cancel-order.vue
  20. 51 0
      src/views/recycle/orderSetting/components/not-supported-area.vue
  21. 51 0
      src/views/recycle/orderSetting/components/not-supported-returned.vue
  22. 104 0
      src/views/recycle/orderSetting/components/recycle-alert-params.vue
  23. 72 0
      src/views/recycle/orderSetting/components/recycle-order-settings.vue
  24. 70 0
      src/views/recycle/orderSetting/components/restore-order-settings.vue
  25. 49 0
      src/views/recycle/orderSetting/index.vue
  26. 106 0
      src/views/recycle/remindArea/components/page-edit.vue
  27. 74 0
      src/views/recycle/remindArea/components/page-search.vue
  28. 155 0
      src/views/recycle/remindArea/index.vue
  29. 106 0
      src/views/recycle/remindBooks/components/page-edit.vue
  30. 74 0
      src/views/recycle/remindBooks/components/page-search.vue
  31. 101 0
      src/views/recycle/remindBooks/index.vue

+ 58 - 0
src/components/CommonPage/EleInput.vue

@@ -0,0 +1,58 @@
+<template>
+  <div class="flex items-center">
+    <template v-if="isText">
+      <ele-text>{{ inputValue || '-' }}</ele-text>
+      <ele-text v-if="suffixStr" class="ml-1">{{ suffixStr }}</ele-text>
+    </template>
+
+    <el-input
+      v-else
+      ref="inputRef"
+      v-bind="$attrs"
+      v-model="inputValue"
+      @input="handleInput"
+      style="max-width: 200px"
+    >
+      <template #append v-if="suffixStr">{{ suffixStr }}</template>
+    </el-input>
+    <el-button type="success" plain link class="ml-10" @click="handleModify">
+      {{ isText ? '[修改]' : '[确定]' }}
+    </el-button>
+  </div>
+</template>
+
+<script setup>
+  const props = defineProps({
+    modelValue: {
+      type: [String, Number]
+    },
+    suffixStr: {
+      type: String,
+      default: ''
+    }
+  });
+  const inputValue = ref(props.modelValue);
+  watch(
+    () => props.modelValue,
+    () => {
+      inputValue.value = props.modelValue;
+    },
+    { immediate: true }
+  );
+
+  const emit = defineEmits(['update:modelValue', 'toggle']);
+  const inputRef = ref(null);
+  function handleInput(val) {
+    console.log(val, 'input');
+    emit('update:modelValue', val);
+  }
+
+  const isText = ref(true);
+  function handleModify() {
+    isText.value = !isText.value;
+    if (!isText.value) {
+      inputValue.value = props.modelValue;
+      inputRef.value?.focus();
+    }
+  }
+</script>

+ 75 - 0
src/components/CommonPage/InputNumberRange.vue

@@ -0,0 +1,75 @@
+<template>
+  <div class="input-number-range flex items-center">
+    <el-input-number
+      v-model="form.minValue"
+      class="flex-1"
+      placeholder="最小"
+      :controls="false"
+      :max="form.maxValue"
+      v-bind="minAttrs"
+      @change="handleNumberChange"
+    />
+    <ele-text>{{ separator }}</ele-text>
+    <el-input-number
+      v-model="form.maxValue"
+      class="flex-1"
+      placeholder="最大"
+      :controls="false"
+      :min="form.minValue"
+      v-bind="maxAttrs"
+      @change="handleNumberChange"
+    />
+  </div>
+</template>
+
+<script setup>
+  const emit = defineEmits(['update:modelValue', 'change']);
+
+  const props = defineProps({
+    modelValue: {
+      type: Array,
+      default: () => []
+    },
+    separator: {
+      type: String,
+      default: '到'
+    },
+    minAttrs: {
+      type: Object,
+      default: () => ({})
+    },
+    maxAttrs: {
+      type: Object,
+      default: () => ({})
+    }
+  });
+  const form = reactive({
+    minValue: props.modelValue[0] || void 0,
+    maxValue: props.modelValue[1] || void 0
+  });
+
+  function handleNumberChange() {
+    emit('update:modelValue', [form.minValue, form.maxValue]);
+    emit('change', {
+      value: [form.minValue, form.maxValue],
+      min: form.minValue,
+      max: form.maxValue
+    });
+  }
+</script>
+
+<style lang="scss">
+  .input-number-range {
+    border: 1px solid #d9d9d9;
+    border-radius: 6px;
+    .el-input-number .el-input__inner {
+      text-align: left;
+    }
+    .el-input-number .el-input .el-input__wrapper.is-focus,
+    .el-input-number .el-input .el-input__wrapper {
+      border: none !important;
+      box-shadow: none !important;
+      padding-right: 10px;
+    }
+  }
+</style>

+ 5 - 6
src/components/CommonPage/ProSearch2.vue

@@ -11,17 +11,16 @@
     :footer="true"
     :footer-props="{ labelWidth: '0px' }"
     :footer-col-props="{
-      span: gridSpan,
-      offset:
-        offset || (gridNumber - (items.length % gridNumber) - 1) * gridSpan
+      span: 4,
+      offset: 0,
     }"
   >
     <template #footer>
-      <div class="flex-1 flex items-center justify-end">
-        <el-button style="width: 80px" type="primary" @click="search"
+      <div class="flex-1 flex items-center">
+        <el-button style="width: 90px" type="primary" @click="search"
           >查询</el-button
         >
-        <el-button style="width: 80px" type="info" @click="reset"
+        <el-button style="width: 90px" type="info" @click="reset"
           >重置</el-button
         >
       </div>

+ 11 - 0
src/components/ProForm/components/pro-form-item.vue

@@ -1210,6 +1210,16 @@
         <slot :name="item.slots?.[name]" v-bind="slotProps || {}"></slot>
       </template>
     </EleText>
+
+    <InputNumberRange
+      v-else-if="item.type === 'inputNumberRange'"
+      class="ele-fluid"
+      v-bind="item.props || {}"
+      :modelValue="model[item.prop]"
+      @update:modelValue="updateValue"
+    >
+    </InputNumberRange>
+
     <slot
       v-else-if="item.type"
       :name="item.type"
@@ -1228,6 +1238,7 @@
   import RegionsSelect from '@/components/RegionsSelect/index.vue';
   import ImageUpload from '@/components/ImageUpload/index.vue';
   import FileUpload from '@/components/FileUpload/index.vue';
+  import InputNumberRange from '@/components/CommonPage/InputNumberRange.vue';
   import {
     defaultTypes,
     uploadTypes,

+ 10 - 0
src/styles/index.scss

@@ -264,3 +264,13 @@ html.disabled-transition :not(.view-transition-trigger) * {
         font-size: 14px;
     }
 }
+
+
+.common-section{
+    padding: 12px 30px;
+    background-color: #fcfbfa;
+    border-radius: 6px;
+    .el-form-item{
+        margin-bottom: 10px;
+    }
+}

+ 241 - 0
src/views/recycle/bookTypes/index.vue

@@ -0,0 +1,241 @@
+<template>
+  <ele-page flex-table>
+    <book-search @search="reload"></book-search>
+
+    <common-table
+      ref="pageRef"
+      :pageConfig="pageConfig"
+      :columns="columns"
+      :tools="false"
+    >
+      <template #toolbar>
+        <el-radio-group @change="handleStatusChange" v-model="useStatus">
+          <el-radio-button label="全部" value="0" />
+          <el-radio-button
+            :label="item.dictLabel"
+            :value="item.dictValue"
+            v-for="item in bookTagDicts"
+          />
+        </el-radio-group>
+
+        <span class="ml-8"></span>
+        <el-button
+          type="success"
+          plain
+          v-permission="'recycle:bookTypes:batchAddBooklist'"
+          @click="handleOptBooklist()"
+        >
+          加入回收书单
+        </el-button>
+        <el-button
+          type="warning"
+          plain
+          v-permission="'recycle:bookTypes:batchRemoveBlacklist'"
+          @click="handleOptBlacklist()"
+        >
+          移除黑名单
+        </el-button>
+        <el-button
+          type="danger"
+          plain
+          v-permission="'recycle:bookTypes:batchAddBlacklist'"
+          @click="handleOptBlacklist()"
+        >
+          加黑名单
+        </el-button>
+
+        <el-button
+          type="warning"
+          plain
+          v-permission="'recycle:bookTypes:batchPauseRecycle'"
+          @click="handleOptRecycle()"
+        >
+          暂停回收
+        </el-button>
+
+        <el-button
+          type="success"
+          plain
+          v-permission="'recycle:bookTypes:batchAddSocial'"
+          @click="handleOptType(1)"
+        >
+          加社科库
+        </el-button>
+        <el-button
+          color="#192bbe"
+          plain
+          v-permission="'recycle:bookTypes:batchAddTeach'"
+          @click="handleOptType(2)"
+        >
+          加教材库
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          v-permission="'recycle:bookTypes:exprot'"
+          @click="handleExportExcel()"
+        >
+          导出Excel
+        </el-button>
+      </template>
+
+      <template #cover="{ row }">
+        <el-image
+          style="width: 90px; height: 120px; border-radius: 4px"
+          fit="cover"
+          :src="row.cover"
+        />
+      </template>
+      <template #baseInfo="{ row }">
+        <div class="flex justify-start items-center">
+          <div style="flex: 2">
+            <book-info :row="row"></book-info>
+          </div>
+          <div style="flex: 1.5; margin-left: 15px">
+            <book-other-info :row="row"></book-other-info>
+          </div>
+        </div>
+      </template>
+
+      <template #action="{ row }">
+        <el-button
+          type="danger"
+          link
+          v-permission="'recycle:bookTypes:delete'"
+          @click="handleDelete(row)"
+        >
+          [删除]
+        </el-button>
+        <el-button
+          color="#192bbe"
+          plain
+          link
+          v-permission="'recycle:bookTypes:modifyType'"
+          @click="handleModifyType(row)"
+        >
+          [修改类型]
+        </el-button>
+      </template>
+    </common-table>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import CommonTable from '@/components/CommonPage/CommonTable.vue';
+  import bookSearch from '@/views/recycle/components/book-search.vue';
+  import bookInfo from '@/views/recycle/components/book-info.vue';
+  import bookOtherInfo from '@/views/recycle/components/book-other-info.vue';
+  import { useDictData } from '@/utils/use-dict-data';
+
+  defineOptions({ name: 'bookTypes' });
+  const [useStatusDicts, bookTagDicts] = useDictData([
+    'use_status',
+    'book_tag_ku'
+  ]);
+
+  const useStatus = ref('0');
+  function handleStatusChange(value) {
+    pageRef.value.reload({ useStatus: value });
+  }
+
+  /** 表格列配置 */
+  const columns = ref([
+    {
+      type: 'selection',
+      columnKey: 'selection',
+      width: 50,
+      align: 'center',
+      fixed: 'left'
+    },
+    {
+      label: '图片',
+      prop: 'cover',
+      width: 120,
+      slot: 'cover'
+    },
+    {
+      label: '信息',
+      prop: 'baseInfo',
+      width: 540,
+      slot: 'baseInfo'
+    },
+    { label: '回收折扣', prop: 'discount' },
+    { label: '回收价格', prop: 'price' },
+    { label: '最大回收量', prop: 'maxRecycledAmount' },
+    { label: '当前剩余回收量', prop: 'remainingRecycledAmount' },
+    { label: '所属类型', prop: 'bookTag' },
+    { label: '售价', prop: 'salesPrice' },
+    { label: '销量', prop: 'salesVolume' },
+    {
+      columnKey: 'action',
+      label: '操作',
+      width: 120,
+      slot: 'action',
+      fixed: 'right'
+    }
+  ]);
+
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '/book/bookInfo/list',
+    exportUrl: '/book/bookInfo/export',
+    fileName: '图书类型管理',
+    cacheKey: 'bookTypesTable'
+  });
+
+  //刷新表格
+  function reload(where) {
+    pageRef.value?.reload(where);
+  }
+
+  //导出excel
+  function handleExportExcel() {
+    pageRef.value?.exportData('图书类型管理');
+  }
+
+  //回收书单操作
+  function handleOptBooklist(row) {
+    let selections = row ? [row] : pageRef.value?.getSelections();
+    let ids = selections.map((item) => item.id).join(',');
+    let url = `/book/bookInfo/removeById/${ids}`;
+    let title = row ? '确认移除回收书单?' : '确认加入回收书单?';
+    pageRef.value?.operatBatch({ title, method: 'post', url, row });
+  }
+  //黑名单操作
+  function handleOptBlacklist(row) {
+    let selections = row ? [row] : pageRef.value?.getSelections();
+    let ids = selections.map((item) => item.id).join(',');
+    let url = `/book/bookInfo/removeBlacklist/${ids}`;
+    let title = row ? '确认移除黑名单?' : '确认加入黑名单?';
+    pageRef.value?.operatBatch({ title, method: 'post', url, row });
+  }
+  //回收操作
+  function handleOptRecycle(row) {
+    let selections = row ? [row] : pageRef.value?.getSelections();
+    let ids = selections.map((item) => item.id).join(',');
+    let url = `/book/bookInfo/recycle/${ids}`;
+    let title = '确认回收?';
+    pageRef.value?.operatBatch({ title, method: 'post', url, row });
+  }
+  //类型操作
+  function handleOptType(type) {
+    let selections = pageRef.value?.getSelections();
+    let ids = selections.map((item) => item.id).join(',');
+    let url = `/book/bookInfo/changeType/${ids}`;
+    let title = type == 1 ? '确认加社科库?' : '确认加教材库?';
+    pageRef.value?.operatBatch({ title, method: 'post', url, row });
+  }
+
+  //删除
+  function handleDelete(row) {
+    pageRef.value?.messageBoxConfirm({
+      message: '确定删除吗?',
+      fetch: () => request.get('/common/exportrecord/deleteRecord?id=' + row.id)
+    });
+  }
+  //修改类型
+  function handleModifyType(row) {}
+</script>

+ 339 - 0
src/views/recycle/booklist/index.vue

@@ -0,0 +1,339 @@
+<template>
+  <ele-page flex-table>
+    <book-search @search="reload"></book-search>
+
+    <common-table
+      ref="pageRef"
+      :pageConfig="pageConfig"
+      :columns="columns"
+      :tools="false"
+    >
+      <template #toolbar>
+        <el-radio-group @change="handleStatusChange" v-model="useStatus">
+          <el-radio-button label="全部" value="0" />
+          <el-radio-button label="已加入回收书单(正在回收)" value="1" />
+          <el-radio-button label="已加入回收书单(暂停回收)" value="2" />
+          <el-radio-button label="未加入回收书单" value="3" />
+          <el-radio-button label="黑名单" value="4" />
+        </el-radio-group>
+
+        <span class="ml-8"></span>
+        <el-button
+          type="success"
+          plain
+          v-permission="'recycle:booklist:batchRemoveBooklist'"
+          @click="handleOptBooklist()"
+        >
+          移除回收书单
+        </el-button>
+        <el-button
+          type="danger"
+          plain
+          v-permission="'recycle:booklist:batchAddBooklist'"
+          @click="handleOptBooklist()"
+        >
+          加入回收书单
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          v-permission="'recycle:booklist:batchRemoveBlacklist'"
+          @click="handleOptBlacklist()"
+        >
+          批量移除黑名单
+        </el-button>
+        <el-button
+          type="danger"
+          plain
+          v-permission="'recycle:booklist:batchAddBlacklist'"
+          @click="handleOptBlacklist()"
+        >
+          批量加黑名单
+        </el-button>
+
+        <el-button
+          type="warning"
+          plain
+          v-permission="'recycle:booklist:batchPauseRecycle'"
+          @click="handleOptRecycle()"
+        >
+          暂停回收
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          v-permission="'recycle:booklist:batchStartRecycle'"
+          @click="handleOptRecycle()"
+        >
+          开启回收
+        </el-button>
+        <el-button
+          type="primary"
+          plain
+          v-permission="'recycle:booklist:batchAddDiscount'"
+          @click="handleAddDiscount()"
+        >
+          指定折扣加回收书单
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          v-permission="'recycle:booklist:batchAddSocial'"
+          @click="handleOptType(1)"
+        >
+          加社科库
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          v-permission="'recycle:booklist:batchAddTeach'"
+          @click="handleOptType(2)"
+        >
+          加教材库
+        </el-button>
+      </template>
+
+      <template #cover="{ row }">
+        <el-image
+          style="width: 90px; height: 120px; border-radius: 4px"
+          fit="cover"
+          :src="row.cover"
+        />
+      </template>
+      <template #baseInfo="{ row }">
+        <div class="flex justify-start items-center">
+          <div style="flex: 2">
+            <book-info :row="row"></book-info>
+          </div>
+          <div style="flex: 1.5; margin-left: 15px">
+            <book-other-info :row="row"></book-other-info>
+          </div>
+        </div>
+      </template>
+      <template #stock="{ row }">
+        <book-stock :row="row"></book-stock>
+      </template>
+
+      <template #action="{ row }">
+        <el-button
+          type="primary"
+          link
+          v-permission="'recycle:booklist:updateBook'"
+          @click="handleUpdateBook(row)"
+        >
+          [编辑]
+        </el-button>
+        <el-button
+          color="#192bbe"
+          plain
+          link
+          v-permission="'recycle:booklist:setParams'"
+          @click="handleSetParams(row)"
+        >
+          [设置独立参数]
+        </el-button>
+        <el-button
+          type="warning"
+          link
+          v-permission="'recycle:booklist:addBlacklist'"
+          @click="handleOptBlacklist(row)"
+        >
+          [加入黑名单]
+        </el-button>
+        <el-button
+          type="success"
+          link
+          v-permission="'recycle:booklist:removeBlacklist'"
+          @click="handleOptBlacklist(row)"
+        >
+          [移除黑名单]
+        </el-button>
+        <el-button
+          type="danger"
+          link
+          v-permission="'recycle:booklist:pauseRecycle'"
+          @click="handleOptRecycle(row)"
+        >
+          [暂停回收]
+        </el-button>
+        <el-button
+          type="success"
+          link
+          v-permission="'recycle:booklist:startRecycle'"
+          @click="handleOptRecycle(row)"
+        >
+          [开启回收]
+        </el-button>
+        <el-button
+          type="success"
+          link
+          v-permission="'recycle:booklist:removeBooklist'"
+          @click="handleOptBooklist(row)"
+        >
+          [移除回收书单]
+        </el-button>
+        <el-button
+          type="danger"
+          link
+          v-permission="'recycle:booklist:addBooklist'"
+          @click="handleOptBooklist(row)"
+        >
+          [加入回收书单]
+        </el-button>
+      </template>
+    </common-table>
+
+    <books-edit ref="editRef"></books-edit>
+    <set-params ref="paramsRef"></set-params>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import CommonTable from '@/components/CommonPage/CommonTable.vue';
+  import booksEdit from '@/views/data/books/components/books-edit.vue';
+  import bookSearch from '@/views/recycle/components/book-search.vue';
+  import bookInfo from '@/views/recycle/components/book-info.vue';
+  import bookOtherInfo from '@/views/recycle/components/book-other-info.vue';
+  import bookStock from '@/views/recycle/components/book-stock.vue';
+  import setParams from '@/views/recycle/components/set-params.vue';
+  import { useDictData } from '@/utils/use-dict-data';
+
+  defineOptions({ name: 'recycleBooklist' });
+  const [useStatusDicts] = useDictData(['use_status']);
+
+  const useStatus = ref('0');
+  function handleStatusChange(value) {
+    pageRef.value.reload({ useStatus: value });
+  }
+
+  /** 表格列配置 */
+  const columns = ref([
+    {
+      type: 'selection',
+      columnKey: 'selection',
+      width: 50,
+      align: 'center',
+      fixed: 'left'
+    },
+    {
+      label: '图片',
+      prop: 'cover',
+      width: 120,
+      slot: 'cover'
+    },
+    {
+      label: '信息',
+      prop: 'baseInfo',
+      width: 540,
+      slot: 'baseInfo'
+    },
+    {
+      label: '回收折扣',
+      prop: 'discount',
+      sortable: true,
+      columnKey: 'discount'
+    },
+    { label: '回收价格', prop: 'price', sortable: true, columnKey: 'price' },
+    {
+      label: '最大回收量',
+      prop: 'maxRecycledAmount',
+      sortable: true,
+      columnKey: 'maxRecycledAmount'
+    },
+    {
+      label: '总回收数量',
+      prop: 'totalRecycledAmount',
+      sortable: true,
+      columnKey: 'totalRecycledAmount'
+    },
+    {
+      label: '当前剩余回收量',
+      prop: 'remainingRecycledAmount',
+      sortable: true,
+      columnKey: 'remainingRecycledAmount'
+    },
+    {
+      label: '销量',
+      prop: 'salesVolume',
+      sortable: true,
+      columnKey: 'salesVolume'
+    },
+    {
+      label: '库存',
+      prop: 'stock',
+      sortable: true,
+      columnKey: 'stock',
+      slot: 'stock'
+    },
+    {
+      columnKey: 'action',
+      label: '操作',
+      width: 150,
+      slot: 'action',
+      fixed: 'right'
+    }
+  ]);
+
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '/book/bookInfo/list',
+    fileName: '回收书单管理',
+    cacheKey: 'recycleBooklistTable'
+  });
+
+  //刷新表格
+  function reload(where) {
+    pageRef.value?.reload(where);
+  }
+
+  //编辑
+  const editRef = ref(null);
+  function handleUpdateBook(row) {
+    editRef.value?.handleOpen(row);
+  }
+  //设置参数
+  const paramsRef = ref(null);
+  function handleSetParams(row) {
+    paramsRef.value?.handleOpen(row);
+  }
+
+  //回收书单操作
+  function handleOptBooklist(row) {
+    let selections = row ? [row] : pageRef.value?.getSelections();
+    let ids = selections.map((item) => item.id).join(',');
+    let url = `/book/bookInfo/removeById/${ids}`;
+    let title = row ? '确认移除回收书单?' : '确认加入回收书单?';
+    pageRef.value?.operatBatch({ title, method: 'post', url, row });
+  }
+  //黑名单操作
+  function handleOptBlacklist(row) {
+    let selections = row ? [row] : pageRef.value?.getSelections();
+    let ids = selections.map((item) => item.id).join(',');
+    let url = `/book/bookInfo/removeBlacklist/${ids}`;
+    let title = row ? '确认移除黑名单?' : '确认加入黑名单?';
+    pageRef.value?.operatBatch({ title, method: 'post', url, row });
+  }
+  //回收操作
+  function handleOptRecycle(row) {
+    let selections = row ? [row] : pageRef.value?.getSelections();
+    let ids = selections.map((item) => item.id).join(',');
+    let url = `/book/bookInfo/recycle/${ids}`;
+    let title = '确认回收?';
+    pageRef.value?.operatBatch({ title, method: 'post', url, row });
+  }
+  //类型操作
+  function handleOptType(type) {
+    let selections = pageRef.value?.getSelections();
+    let ids = selections.map((item) => item.id).join(',');
+    let url = `/book/bookInfo/changeType/${ids}`;
+    let title = type == 1 ? '确认加社科库?' : '确认加教材库?';
+    pageRef.value?.operatBatch({ title, method: 'post', url, row });
+  }
+  //指定折扣
+  function handleAddDiscount(){
+    
+  }
+</script>

+ 45 - 0
src/views/recycle/components/book-info.vue

@@ -0,0 +1,45 @@
+<template>
+  <div class="recycle-order-number flex flex-col items-start">
+    <div class="common-text">
+      <el-text>书名:</el-text>
+      <el-text>{{ row.bookName }}</el-text>
+    </div>
+    <div class="common-text">
+      <el-text>作 者:</el-text>
+      <el-text>{{ row.author || '-' }} </el-text>
+    </div>
+    <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.bookTagName || '-' }}</el-text>
+    </div>
+    <div class="common-text">
+      <el-text>出版社:</el-text>
+      <el-text>{{ row.publish || '-' }}</el-text>
+    </div>
+    <div class="common-text">
+      <el-text>出版时间:</el-text>
+      <el-text>{{ publishDate }} </el-text>
+    </div>
+  </div>
+</template>
+
+<script setup>
+  import { dayjs } from 'element-plus';
+
+  const props = defineProps({
+    row: {
+      type: Object,
+      default: () => {}
+    }
+  });
+
+  const publishDate = computed(() => {
+    return props.row.pubDate
+      ? dayjs(props.row.pubDate).format('YYYY-MM-DD')
+      : '-';
+  });
+</script>

+ 32 - 0
src/views/recycle/components/book-other-info.vue

@@ -0,0 +1,32 @@
+<template>
+  <div class="recycle-order-number flex flex-col items-start">
+    <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.bookFormat }}</el-text>
+    </div>
+    <div class="common-text">
+      <el-text>回收状态:</el-text>
+      <el-text>暂停回收</el-text>
+    </div>
+    <div class="common-text">
+      <el-text>所属类型:</el-text>
+      <el-text>{{ row.bookTagName || '-' }}</el-text>
+    </div>
+    <div class="common-text">
+      <el-text>(已回收数量:200当前库存:75)</el-text>
+    </div>
+  </div>
+</template>
+
+<script setup>
+  const props = defineProps({
+    row: {
+      type: Object,
+      default: () => {}
+    }
+  });
+</script>

+ 77 - 0
src/views/recycle/components/book-search.vue

@@ -0,0 +1,77 @@
+<!-- 搜索表单 -->
+<template>
+  <ele-card :body-style="{ paddingBottom: '8px' }">
+    <ProSearch
+      :items="formItems"
+      ref="searchRef"
+      @search="search"
+      :initKeys="initKeys"
+    ></ProSearch>
+  </ele-card>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits } from 'vue';
+  import ProSearch from '@/components/CommonPage/ProSearch2.vue';
+
+  let { proxy } = getCurrentInstance();
+  const emit = defineEmits(['search']);
+
+  const formItems = reactive([
+    { type: 'input', label: '书名', prop: 'bookName' },
+    { type: 'input', label: 'ISBN', prop: 'isbn' },
+    { type: 'input', label: '作者', prop: 'author' },
+    { type: 'input', label: '出版社', prop: 'publisher' },
+    {
+      type: 'date',
+      label: '出版时间',
+      prop: 'publicationTime',
+      props: { format: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD' }
+    },
+    {
+      type: 'inputNumberRange',
+      label: '定价',
+      prop: 'price',
+      keys: ['minPrice', 'maxPrice'],
+      props: {
+        onChange: (val) => {
+          searchRef.value?.setData({ minPrice: val.min, maxPrice: val.max });
+        }
+      }
+    },
+    {
+      type: 'inputNumberRange',
+      label: '回收折扣',
+      prop: 'recoveryDiscount',
+      keys: ['minRecoveryDiscount', 'maxRecoveryDiscount'],
+      props: {
+        minAttrs: { min: 0 },
+        maxAttrs: { max: 1 },
+        onChange: (val) => {
+          searchRef.value?.setData({ minRecoveryDiscount: val.min, maxRecoveryDiscount: val.max });
+        }
+      }
+    },
+  ]);
+
+  const initKeys = reactive({
+    bookName: '',
+    isbn: '',
+    author: '',
+    publisher: '',
+    publicationTime: '',
+    minPrice: void 0,
+    maxPrice: void 0,
+    minRecoveryDiscount: void 0,
+    maxRecoveryDiscount: void 0
+  });
+
+  const searchRef = ref(null);
+  /** 搜索 */
+  const search = (data) => {
+    let params = JSON.parse(JSON.stringify(data));
+    delete params.price;
+    delete params.recoveryDiscount
+    emit('search', params);
+  };
+</script>

+ 29 - 0
src/views/recycle/components/book-stock.vue

@@ -0,0 +1,29 @@
+<template>
+  <div class="recycle-order-number flex flex-col items-start">
+    <div class="common-text">
+      <el-text>中等:</el-text>
+      <el-text></el-text>
+    </div>
+    <div class="common-text">
+      <el-text>良好:</el-text>
+      <el-text></el-text>
+    </div>
+    <div class="common-text">
+      <el-text>次品:</el-text>
+      <el-text></el-text>
+    </div>
+    <div class="common-text">
+      <el-text>合计:</el-text>
+      <el-text></el-text>
+    </div>
+  </div>
+</template>
+
+<script setup>
+  const props = defineProps({
+    row: {
+      type: Object,
+      default: () => {}
+    }
+  });
+</script>

+ 97 - 0
src/views/recycle/components/set-params.vue

@@ -0,0 +1,97 @@
+<!-- 编辑弹窗 -->
+<template>
+  <ele-modal
+    form
+    :width="560"
+    v-model="visible"
+    title="设置独立参数"
+    @open="handleOpen"
+  >
+    <SimpleForm
+      :items="items"
+      labelWidth="140px"
+      ref="formRef"
+      :initKeys="form"
+    ></SimpleForm>
+    <template #footer>
+      <el-button @click="handleCancel">关闭</el-button>
+      <el-button type="primary" @click="handleSumbit">确定</el-button>
+    </template>
+  </ele-modal>
+</template>
+
+<script setup>
+  import { ref, reactive, nextTick } from 'vue';
+  import { Flag, ChatDotSquare } from '@element-plus/icons-vue';
+  import orderTimeline from '@/views/recycleOrder/components/order-timeline.vue';
+  import SimpleForm from '@/components/CommonPage/SimpleForm.vue';
+  import validators from '@/utils/validators';
+
+  /** 弹窗是否打开 */
+  const visible = defineModel({ type: Boolean });
+
+  /** 关闭弹窗 */
+  const handleCancel = () => {
+    visible.value = false;
+    nextTick(() => {
+      formRef.value?.resetForm();
+    });
+  };
+
+  const form = reactive({
+    maxCount: '',
+    discount: '0.01',
+    number: '',
+    status: '1'
+  });
+  /** 弹窗打开事件 */
+  const handleOpen = () => {
+    visible.value = true;
+    nextTick(() => {
+      formRef.value?.assignFields(form);
+    });
+  };
+
+  const items = reactive([
+    {
+      label: '回收折扣',
+      prop: 'discount',
+      type: 'input',
+      required: true,
+      rules: [validators.decimalRange]
+    },
+    {
+      label: '最大回收数量',
+      prop: 'maxCount',
+      type: 'input',
+      required: true,
+      rules: [validators.nonNegativeInteger]
+    },
+    {
+      label: '单个订单回收数量',
+      prop: 'number',
+      type: 'input',
+      required: true,
+      rules: [validators.nonNegativeInteger]
+    },
+    {
+      label: '状态',
+      prop: 'status',
+      type: 'dictRadio',
+      props: { code: 'discount_status' },
+      required: true
+    }
+  ]);
+
+  const formRef = ref();
+  const handleSumbit = () => {
+    formRef.value?.submitForm().then((data) => {
+      visible.value = false;
+      console.log(data);
+    });
+  };
+
+  defineExpose({
+    handleOpen
+  });
+</script>

+ 65 - 0
src/views/recycle/globalParameter/components/has-add-recycle-booklist.vue

@@ -0,0 +1,65 @@
+<template>
+  <el-form :model="form" class="common-form" label-width="auto" :rules="rules">
+    <el-form-item label="回收折扣:" prop="dayOrderNum">
+      <ele-input
+        v-model="form.dayOrderNum"
+        placeholder="请输入"
+        clearable
+        suffixStr="折"
+      />
+    </el-form-item>
+    <el-form-item label="最大回收量:" prop="dayOrderTotal">
+      <ele-input
+        v-model="form.dayOrderTotal"
+        placeholder="请输入"
+        suffixStr="本"
+        clearable
+      />
+    </el-form-item>
+    <el-form-item label="单个订单回收数量:" prop="mobile">
+      <ele-input
+        v-model="form.mobile"
+        placeholder="请输入"
+        clearable
+        suffixStr="本"
+      />
+    </el-form-item>
+    <el-form-item>
+      <el-button type="success" style="width: 100px" plain @click="onSubmit"
+        >保存</el-button
+      >
+    </el-form-item>
+  </el-form>
+</template>
+
+<script lang="ts" setup>
+  import { reactive } from 'vue';
+  import EleInput from '@/components/CommonPage/EleInput.vue';
+
+  const form = reactive({
+    dayOrderNum: '',
+    dayOrderTotal: '',
+    mobile: ''
+  });
+
+  const rules = reactive({
+    dayOrderNum: [
+      {
+        required: true,
+        message: '请输入每人每日申请恢复订单限量',
+        trigger: 'blur'
+      }
+    ],
+    dayOrderTotal: [
+      {
+        required: true,
+        message: '请输入每日申请恢复订单总限量',
+        trigger: 'blur'
+      }
+    ]
+  });
+
+  const onSubmit = () => {
+    console.log('submit!');
+  };
+</script>

+ 65 - 0
src/views/recycle/globalParameter/components/not-add-recycle-booklist.vue

@@ -0,0 +1,65 @@
+<template>
+  <el-form :model="form" class="common-form" label-width="auto" :rules="rules">
+    <el-form-item label="回收折扣:" prop="dayOrderNum">
+      <ele-input
+        v-model="form.dayOrderNum"
+        placeholder="请输入"
+        clearable
+        suffixStr="折"
+      />
+    </el-form-item>
+    <el-form-item label="最大回收量:" prop="dayOrderTotal">
+      <ele-input
+        v-model="form.dayOrderTotal"
+        placeholder="请输入"
+        suffixStr="本"
+        clearable
+      />
+    </el-form-item>
+    <el-form-item label="单个订单回收数量:" prop="mobile">
+      <ele-input
+        v-model="form.mobile"
+        placeholder="请输入"
+        clearable
+        suffixStr="本"
+      />
+    </el-form-item>
+    <el-form-item>
+      <el-button type="success" style="width: 100px" plain @click="onSubmit"
+        >保存</el-button
+      >
+    </el-form-item>
+  </el-form>
+</template>
+
+<script lang="ts" setup>
+  import { reactive } from 'vue';
+  import EleInput from '@/components/CommonPage/EleInput.vue';
+
+  const form = reactive({
+    dayOrderNum: '',
+    dayOrderTotal: '',
+    mobile: ''
+  });
+
+  const rules = reactive({
+    dayOrderNum: [
+      {
+        required: true,
+        message: '请输入每人每日申请恢复订单限量',
+        trigger: 'blur'
+      }
+    ],
+    dayOrderTotal: [
+      {
+        required: true,
+        message: '请输入每日申请恢复订单总限量',
+        trigger: 'blur'
+      }
+    ],
+  });
+
+  const onSubmit = () => {
+    console.log('submit!');
+  };
+</script>

+ 19 - 0
src/views/recycle/globalParameter/index.vue

@@ -0,0 +1,19 @@
+<template>
+  <ele-page flex-table>
+    <ele-card flex-table>
+      <div class="common-section mb-4">
+        <div class="common-title mb-4">未加入回收书单全局参数设置</div>
+        <not-add-recycle-booklist />
+      </div>
+      <div class="common-section mb-4">
+        <div class="common-title mb-4">已加入回收书单全局参数设置</div>
+        <has-add-recycle-booklist />
+      </div>
+    </ele-card>
+  </ele-page>
+</template>
+
+<script setup>
+  import notAddRecycleBooklist from '@/views/recycle/globalParameter/components/not-add-recycle-booklist.vue';
+  import hasAddRecycleBooklist from '@/views/recycle/globalParameter/components/has-add-recycle-booklist.vue';
+</script>

+ 14 - 0
src/views/recycle/independentParameter/index.vue

@@ -0,0 +1,14 @@
+<template>
+  <ele-page flex-table>
+    <ele-card flex-table>
+      <div class="common-section mb-4">
+        <div class="common-title mb-4">已加入回收书单全局参数设置</div>
+        <has-add-recycle-booklist />
+      </div>
+    </ele-card>
+  </ele-page>
+</template>
+
+<script setup>
+  import hasAddRecycleBooklist from '@/views/recycle/globalParameter/components/has-add-recycle-booklist.vue';
+</script>

+ 216 - 0
src/views/recycle/orderAlert/index.vue

@@ -0,0 +1,216 @@
+<template>
+  <order-page ref="pageRef" :pageConfig="pageConfig">
+    <template #toolbar>
+      <ele-check-card v-model="checked" :items="items" :row="{ gutter: 12 }">
+        <template #item="{ item }">
+          <div style="padding: 18px" class="flex-col items-center">
+            <ele-text size="md">{{ item.title }}</ele-text>
+            <ele-count-up :end-val="item.content" style="font-size:26px" />
+          </div>
+        </template>
+      </ele-check-card>
+
+      <el-button
+        type="warning"
+        plain
+        v-permission="'recycleOrder:awaitDelivery:batchAudit'"
+        @click="handleBatchAudit"
+      >
+        批量初审
+      </el-button>
+      <el-button
+        type="success"
+        plain
+        v-permission="'recycleOrder:awaitDelivery:batchReceive'"
+        @click="handleBatchReceive()"
+      >
+        批量确认收货
+      </el-button>
+    </template>
+
+    <template #action="{ row }">
+      <div>
+        <el-button
+          type="success"
+          link
+          v-permission="'recycleOrder:awaitDelivery:detail'"
+          @click="toOrderDetail(row)"
+        >
+          [订单详情]
+        </el-button>
+        <el-button
+          type="warning"
+          link
+          v-permission="'recycleOrder:awaitDelivery:log'"
+          @click="openOrderLog(row)"
+        >
+          [订单日志]
+        </el-button>
+        <el-button
+          type="danger"
+          link
+          v-permission="'recycleOrder:awaitDelivery:cancel'"
+          @click="cancelOrder(row)"
+        >
+          [取消订单]
+        </el-button>
+        <el-button
+          type="primary"
+          link
+          v-permission="'recycleOrder:awaitDelivery:fallback'"
+          @click="fallbackOrder(row)"
+        >
+          [回退状态]
+        </el-button>
+        <el-button
+          type="warning"
+          link
+          v-permission="'recycleOrder:awaitDelivery:userTag'"
+          @click="openEditUserTag(row)"
+        >
+          [用户标签]
+        </el-button>
+        <el-button
+          type="success"
+          link
+          v-permission="'recycleOrder:awaitDelivery:receive'"
+          @click="handleBatchReceive(row)"
+        >
+          [确认收货]
+        </el-button>
+        <el-button
+          type="danger"
+          link
+          v-permission="'recycleOrder:awaitDelivery:interception'"
+          @click="applyForInterception(row)"
+        >
+          [申请拦截退回]
+        </el-button>
+      </div>
+    </template>
+
+    <order-log ref="orderLogRef" />
+    <userBindTag ref="userTagRef" />
+  </order-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import { ElMessageBox } from 'element-plus/es';
+  import { EleMessage } from 'ele-admin-plus/es';
+  import { DownloadOutlined } from '@/components/icons';
+  import OrderPage from '@/views/recycleOrder/components/order-page.vue';
+  import { useDictData } from '@/utils/use-dict-data';
+  import { useRouter } from 'vue-router';
+
+  //订单日志
+  import orderLog from '@/views/recycleOrder/components/order-log.vue';
+  //用户标签
+  import userBindTag from '@/views/recycleOrder/components/user-bind-tag.vue';
+
+  defineOptions({ name: 'recycleOrderawaitDelivery' });
+
+  let router = useRouter();
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '',
+    exportUrl: '',
+    fileName: '待签收订单',
+    cacheKey: 'awaitDeliveryTable'
+  });
+
+  //批量初审
+  function handleBatchAudit() {
+    pageRef.value?.operatBatch({
+      title: '确认批量审核?',
+      url: '/recycleOrder/batchAudit'
+    });
+  }
+
+  //批量取消订单
+  function handleBatchReceive(row) {
+    pageRef.value?.operatBatch({
+      title: '确认收货?',
+      row,
+      url: '/recycleOrder/batchAudit'
+    });
+  }
+
+  //订单详情
+  function toOrderDetail(row) {
+    router.push({ path: '/recycleOrder/detail', query: { id: row.postId } });
+  }
+
+  //订单日志
+  const orderLogRef = ref(null);
+  function openOrderLog(row) {
+    console.log(row, orderLogRef.value, 'row');
+
+    orderLogRef.value?.handleOpen(row);
+  }
+
+  //用户绑定标签
+  const userTagRef = ref(null);
+  function openEditUserTag(row) {
+    userTagRef.value?.handleOpen(row);
+  }
+
+  function messageBoxConfirm({ message, url, row }) {
+    ElMessageBox.confirm(message, '提示', {
+      confirmButtonText: '确定',
+      cancelButtonText: '关闭',
+      type: 'warning'
+    }).then(() => {
+      console.log(row, 'row');
+    });
+  }
+
+  //取消订单
+  function cancelOrder(row) {
+    messageBoxConfirm({ message: '确认取消?', url: '', row });
+  }
+  //回退状态
+  function fallbackOrder(row) {
+    messageBoxConfirm({ message: '确认回退状态?', url: '', row });
+  }
+  //确认收货
+  function materialPickup(row) {
+    messageBoxConfirm({ message: '确认收货?', url: '', row });
+  }
+  //申请拦截退回
+  function applyForInterception(row) {
+    messageBoxConfirm({ message: '确认申请拦截退回?', url: '', row });
+  }
+
+  // 选中值
+  const checked = ref();
+  // 数据
+  const items = ref([
+    {
+      value: 1,
+      title: '已揽件-物流异常',
+      content: 12,
+      col: { md: 3, style: { marginBottom: '12px', width: '180px' } }
+    },
+    {
+      value: 2,
+      title: '已签收-收货超时',
+      content: 5,
+      col: { md: 3, style: { marginBottom: '12px', width: '180px' } }
+    },
+    {
+      value: 3,
+      title: '已收货-审核超时',
+      content: 12,
+      col: { md: 3, style: { marginBottom: '12px', width: '180px' } }
+    },
+    {
+      value: 4,
+      title: '已到仓-收货超时',
+      content: 12,
+      col: { md: 3, style: { marginBottom: '12px', width: '180px' } }
+    }
+  ]);
+</script>

+ 36 - 0
src/views/recycle/orderSetting/components/auto-audit-settings.vue

@@ -0,0 +1,36 @@
+<template>
+  <el-form :model="form" class="common-form" label-width="auto">
+    <el-form-item label="" prop="maxMoney">
+      <div class="flex w-full">
+        <ele-text>自动初审最大金额 </ele-text>
+        <el-input
+          v-model="form.maxMoney"
+          placeholder="请输入"
+          style="width: 120px; margin: 0 10px"
+        ></el-input>
+        <ele-text>元</ele-text>
+        <el-button
+          type="success"
+          style="width: 100px; margin-left: 20px"
+          plain
+          @click="onSubmit"
+          >保存</el-button
+        >
+      </div>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script lang="ts" setup>
+  import { reactive } from 'vue';
+  import EleInput from '@/components/CommonPage/EleInput.vue';
+  import request from '@/utils/request';
+
+  const form = reactive({
+    maxMoney: ''
+  });
+
+  const onSubmit = () => {
+    console.log('submit!');
+  };
+</script>

+ 76 - 0
src/views/recycle/orderSetting/components/auto-cancel-order.vue

@@ -0,0 +1,76 @@
+<template>
+  <el-form :model="form" class="common-form" label-width="auto" :rules="rules">
+    <el-form-item label="已扫码-待提交:" prop="dayOrderNum">
+      <div class="flex items-center">
+        <el-checkbox v-model="form.checked1" label="开启" />
+        <ele-text class="ml-6">
+          待提交状态的订单,在距离最后一次扫码
+          <el-input
+            v-model="form.dayOrderNum"
+            placeholder="请输入"
+            clearable
+            style="width: 100px"
+          />
+          小时后,系统自动取消订单。
+        </ele-text>
+        <ele-text type="info" class="ml-6">取消后不可恢复订单</ele-text>
+      </div>
+    </el-form-item>
+    <el-form-item label=" 已初审-待上门取件:" prop="dayOrderTotal">
+      <div class="flex items-center">
+        <el-checkbox v-model="form.checked2" label="开启" />
+        <ele-text class="ml-6">
+          待上门取件的订单,路由信息
+          <el-input
+            v-model="form.dayOrderTotal"
+            placeholder="请输入"
+            clearable
+            style="width: 100px"
+          />
+          天未更新时,系统自动取消回收订单。
+        </ele-text>
+        <ele-text type="info" class="ml-6">取消后3个月内可恢复订单</ele-text>
+      </div>
+    </el-form-item>
+
+    <el-form-item>
+      <el-button type="success" style="width: 100px" plain @click="onSubmit"
+        >保存</el-button
+      >
+    </el-form-item>
+  </el-form>
+</template>
+
+<script lang="ts" setup>
+  import { reactive } from 'vue';
+  import EleInput from '@/components/CommonPage/EleInput.vue';
+
+  const form = reactive({
+    dayOrderNum: '',
+    dayOrderTotal: '',
+    mobile: '',
+    checked1: true,
+    checked2: false
+  });
+
+  const rules = reactive({
+    dayOrderNum: [
+      {
+        required: true,
+        message: '请输入每人每日申请恢复订单限量',
+        trigger: 'blur'
+      }
+    ],
+    dayOrderTotal: [
+      {
+        required: true,
+        message: '请输入每日申请恢复订单总限量',
+        trigger: 'blur'
+      }
+    ],
+  });
+
+  const onSubmit = () => {
+    console.log('submit!');
+  };
+</script>

+ 51 - 0
src/views/recycle/orderSetting/components/not-supported-area.vue

@@ -0,0 +1,51 @@
+<template>
+  <el-form :model="form" class="common-form" label-width="auto">
+    <el-form-item label="省份:" prop="area">
+      <div class="flex w-full">
+        <el-select
+          v-model="form.area"
+          multiple
+          placeholder="请选择"
+          filterable
+          style="width: 70%"
+        >
+          <el-option
+            v-for="item in options"
+            :key="item.value"
+            :label="item.district"
+            :value="item.id"
+          />
+        </el-select>
+        <el-button
+          type="success"
+          style="width: 100px; margin-left: 20px"
+          plain
+          @click="onSubmit"
+          >保存</el-button
+        >
+      </div>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script lang="ts" setup>
+  import { reactive } from 'vue';
+  import EleInput from '@/components/CommonPage/EleInput.vue';
+  import request from '@/utils/request';
+
+  const form = reactive({
+    area: []
+  });
+
+  const options = ref([]);
+  function getProviceList(id = 1) {
+    request.get(`/baseinfo/districtInfo/findInfo/${id}`).then((res) => {
+      options.value = res.data.data;
+    });
+  }
+  getProviceList();
+
+  const onSubmit = () => {
+    console.log('submit!');
+  };
+</script>

+ 51 - 0
src/views/recycle/orderSetting/components/not-supported-returned.vue

@@ -0,0 +1,51 @@
+<template>
+  <el-form :model="form" class="common-form" label-width="auto">
+    <el-form-item label="省份:" prop="area">
+      <div class="flex w-full">
+        <el-select
+          v-model="form.area"
+          multiple
+          placeholder="请选择"
+          filterable
+          style="width: 70%"
+        >
+          <el-option
+            v-for="item in options"
+            :key="item.value"
+            :label="item.district"
+            :value="item.id"
+          />
+        </el-select>
+        <el-button
+          type="success"
+          style="width: 100px; margin-left: 20px"
+          plain
+          @click="onSubmit"
+          >保存</el-button
+        >
+      </div>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script lang="ts" setup>
+  import { reactive } from 'vue';
+  import EleInput from '@/components/CommonPage/EleInput.vue';
+  import request from '@/utils/request';
+
+  const form = reactive({
+    area: []
+  });
+
+  const options = ref([]);
+  function getProviceList(id = 1) {
+    request.get(`/baseinfo/districtInfo/findInfo/${id}`).then((res) => {
+      options.value = res.data.data;
+    });
+  }
+  getProviceList();
+
+  const onSubmit = () => {
+    console.log('submit!');
+  };
+</script>

+ 104 - 0
src/views/recycle/orderSetting/components/recycle-alert-params.vue

@@ -0,0 +1,104 @@
+<template>
+  <el-form :model="form" class="common-form" label-width="auto" :rules="rules">
+    <el-form-item label=" 已揽件-物流异常:" prop="dayOrderNum">
+      <div class="flex items-center">
+        <el-checkbox v-model="form.checked1" label="开启" />
+        <ele-text class="ml-6">
+          已揽件状态的订单,路由信息
+          <el-input
+            v-model="form.dayOrderNum"
+            placeholder="请输入"
+            clearable
+            style="width: 100px"
+          />
+          天未更新
+        </ele-text>
+      </div>
+    </el-form-item>
+    <el-form-item label="已签收-收货超时:" prop="dayOrderTotal">
+      <div class="flex items-center">
+        <el-checkbox v-model="form.checked2" label="开启" />
+        <ele-text class="ml-6">
+          已签收状态
+          <el-input
+            v-model="form.dayOrderTotal"
+            placeholder="请输入"
+            clearable
+            style="width: 100px"
+          />
+          小时仍未确认收货
+        </ele-text>
+      </div>
+    </el-form-item>
+    <el-form-item label="已收货-审核超时:" prop="dayOrderTotal">
+      <div class="flex items-center">
+        <el-checkbox v-model="form.checked2" label="开启" />
+        <ele-text class="ml-6">
+          已收货状态
+          <el-input
+            v-model="form.dayOrderTotal"
+            placeholder="请输入"
+            clearable
+            style="width: 100px"
+          />
+          小时仍未审核完成
+        </ele-text>
+      </div>
+    </el-form-item>
+    <el-form-item label="已到仓-收货超时:" prop="dayOrderTotal">
+      <div class="flex items-center">
+        <el-checkbox v-model="form.checked2" label="开启" />
+        <ele-text class="ml-6">
+          已到仓状态
+          <el-input
+            v-model="form.dayOrderTotal"
+            placeholder="请输入"
+            clearable
+            style="width: 100px"
+          />
+          小时仍未确认收货
+        </ele-text>
+      </div>
+    </el-form-item>
+
+    <el-form-item>
+      <el-button type="success" style="width: 100px" plain @click="onSubmit"
+        >保存</el-button
+      >
+    </el-form-item>
+  </el-form>
+</template>
+
+<script lang="ts" setup>
+  import { reactive } from 'vue';
+  import EleInput from '@/components/CommonPage/EleInput.vue';
+
+  const form = reactive({
+    dayOrderNum: '',
+    dayOrderTotal: '',
+    mobile: '',
+    checked1: true,
+    checked2: false
+  });
+
+  const rules = reactive({
+    dayOrderNum: [
+      {
+        required: true,
+        message: '请输入每人每日申请恢复订单限量',
+        trigger: 'blur'
+      }
+    ],
+    dayOrderTotal: [
+      {
+        required: true,
+        message: '请输入每日申请恢复订单总限量',
+        trigger: 'blur'
+      }
+    ]
+  });
+
+  const onSubmit = () => {
+    console.log('submit!');
+  };
+</script>

+ 72 - 0
src/views/recycle/orderSetting/components/recycle-order-settings.vue

@@ -0,0 +1,72 @@
+<template>
+  <el-form :model="form" class="common-form" label-width="auto" :rules="rules">
+    <el-form-item label="单个订单最少回收本数:" prop="dayOrderNum">
+      <ele-input
+        v-model="form.dayOrderNum"
+        placeholder="请输入"
+        clearable
+        suffixStr="本"
+      />
+    </el-form-item>
+    <el-form-item label="单个订单最多回收本数:" prop="dayOrderTotal">
+      <ele-input
+        v-model="form.dayOrderTotal"
+        placeholder="请输入"
+        suffixStr="本"
+        clearable
+      />
+    </el-form-item>
+    <el-form-item label="单个订单最少预估金额:" prop="mobile">
+      <ele-input
+        v-model="form.mobile"
+        placeholder="请输入"
+        clearable
+        suffixStr="元"
+      />
+    </el-form-item>
+    <el-form-item>
+      <el-button type="success" style="width: 100px" plain @click="onSubmit"
+        >保存</el-button
+      >
+    </el-form-item>
+  </el-form>
+</template>
+
+<script lang="ts" setup>
+  import { reactive } from 'vue';
+  import EleInput from '@/components/CommonPage/EleInput.vue';
+
+  const form = reactive({
+    dayOrderNum: '',
+    dayOrderTotal: '',
+    mobile: ''
+  });
+
+  const rules = reactive({
+    dayOrderNum: [
+      {
+        required: true,
+        message: '请输入每人每日申请恢复订单限量',
+        trigger: 'blur'
+      }
+    ],
+    dayOrderTotal: [
+      {
+        required: true,
+        message: '请输入每日申请恢复订单总限量',
+        trigger: 'blur'
+      }
+    ],
+    mobile: [
+      {
+        required: true,
+        message: '请输入预留手机号',
+        trigger: 'blur'
+      }
+    ]
+  });
+
+  const onSubmit = () => {
+    console.log('submit!');
+  };
+</script>

+ 70 - 0
src/views/recycle/orderSetting/components/restore-order-settings.vue

@@ -0,0 +1,70 @@
+<template>
+  <el-form :model="form" class="common-form" label-width="auto" :rules="rules">
+    <el-form-item label="每人每日申请恢复订单限量:" prop="dayOrderNum">
+      <ele-input
+        v-model="form.dayOrderNum"
+        placeholder="请输入"
+        clearable
+        suffixStr="次"
+      />
+    </el-form-item>
+    <el-form-item label="每日申请恢复订单总限量:" prop="dayOrderTotal">
+      <ele-input
+        v-model="form.dayOrderTotal"
+        placeholder="请输入"
+        suffixStr="次"
+        clearable
+      />
+    </el-form-item>
+    <el-form-item label="预留手机号:" prop="mobile">
+      <ele-input v-model="form.mobile" placeholder="请输入" clearable />
+    </el-form-item>
+    <el-form-item>
+      <el-button type="success" style="width:100px" plain @click="onSubmit">保存</el-button>
+    </el-form-item>
+  </el-form>
+</template>
+
+<script lang="ts" setup>
+  import { reactive } from 'vue';
+  import EleInput from '@/components/CommonPage/EleInput.vue';
+
+  const form = reactive({
+    dayOrderNum: '',
+    dayOrderTotal: '',
+    mobile: ''
+  });
+
+  const rules = reactive({
+    dayOrderNum: [
+      {
+        required: true,
+        message: '请输入每人每日申请恢复订单限量',
+        trigger: 'blur'
+      }
+    ],
+    dayOrderTotal: [
+      {
+        required: true,
+        message: '请输入每日申请恢复订单总限量',
+        trigger: 'blur'
+      }
+    ],
+    mobile: [
+      {
+        required: true,
+        message: '请输入预留手机号',
+        trigger: 'blur'
+      },
+      {
+        pattern: /^1[3456789]\d{9}$/,
+        message: '手机号格式不正确',
+        trigger: ['blur']
+      }
+    ]
+  });
+
+  const onSubmit = () => {
+    console.log('submit!');
+  };
+</script>

+ 49 - 0
src/views/recycle/orderSetting/index.vue

@@ -0,0 +1,49 @@
+<template>
+  <ele-page flex-table>
+    <ele-card flex-table>
+      <div class="common-section mb-4">
+        <div class="common-title mb-4">自动初审设置</div>
+        <auto-audit-settings />
+      </div>
+      <div class="common-section mb-4">
+        <div class="common-title mb-4">不支持退回地区</div>
+        <not-supported-returned />
+      </div>
+      <div class="common-section mb-4">
+        <div class="common-title mb-4">不支持下单地区</div>
+        <not-supported-area />
+      </div>
+      <div class="common-section mb-4">
+        <div class="common-title mb-4 flex items-center"
+          >回收预警参数设置
+          <ele-text type="info" class="ml-4"
+            >开启后达到以下条件,在“回收订单预警”页面进行预警,最大输入数值为1000</ele-text
+          >
+        </div>
+        <recycle-alert-params />
+      </div>
+      <div class="common-section mb-4">
+        <div class="common-title mb-4">回收订单设置</div>
+        <recycle-order-settings />
+      </div>
+      <div class="common-section mb-4">
+        <div class="common-title mb-4">自动取消订单设置</div>
+        <auto-cancel-order />
+      </div>
+      <div class="common-section">
+        <div class="common-title mb-4">客服申请恢复订单限制</div>
+        <restore-order-settings />
+      </div>
+    </ele-card>
+  </ele-page>
+</template>
+
+<script setup>
+  import restoreOrderSettings from '@/views/recycle/orderSetting/components/restore-order-settings.vue';
+  import autoCancelOrder from '@/views/recycle/orderSetting/components/auto-cancel-order.vue';
+  import recycleOrderSettings from '@/views/recycle/orderSetting/components/recycle-order-settings.vue';
+  import recycleAlertParams from '@/views/recycle/orderSetting/components/recycle-alert-params.vue';
+  import notSupportedArea from '@/views/recycle/orderSetting/components/not-supported-area.vue';
+  import notSupportedReturned from '@/views/recycle/orderSetting/components/not-supported-returned.vue';
+  import autoAuditSettings from '@/views/recycle/orderSetting/components/auto-audit-settings.vue';
+</script>

+ 106 - 0
src/views/recycle/remindArea/components/page-edit.vue

@@ -0,0 +1,106 @@
+<!-- 搜索表单 -->
+<template>
+  <simple-form-modal
+    :title="title"
+    :items="formItems"
+    ref="editRef"
+    :baseUrl="baseUrl"
+    @success="(data) => emit('success', data)"
+  ></simple-form-modal>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits, getCurrentInstance } from 'vue';
+  import { useFormData } from '@/utils/use-form-data';
+  import SimpleFormModal from '@/components/CommonPage/SimpleFormModal.vue';
+  const { proxy } = getCurrentInstance();
+
+  //获取省市
+  const provinceList = ref([]);
+  const cityList = ref([]);
+  const title = ref('新增高校');
+  const emit = defineEmits(['success']);
+
+  const formItems = computed(() => {
+    return [
+      { type: 'input', label: '学校名称', prop: 'schoolName', required: true },
+      {
+        type: 'select',
+        label: '省份',
+        prop: 'provinceId',
+        required: true,
+        options: provinceList.value.map((d) => {
+          return { label: d.district, value: d.id };
+        }),
+        props: {
+          filterable: true,
+          onChange: (val) => {
+            getProviceList(val).then((res) => {
+              cityList.value = res.data.data;
+            });
+          }
+        }
+      },
+      {
+        type: 'select',
+        label: '所在市',
+        prop: 'cityId',
+        required: true,
+        options: cityList.value.map((d) => {
+          return { label: d.district, value: d.id };
+        }),
+        props: {
+          filterable: true
+        }
+      },
+      {
+        type: 'dictSelect',
+        label: '办学层次',
+        prop: 'schoolLevel',
+        props: { code: 'school_level' },
+        required: true
+      },
+      {
+        type: 'input',
+        label: '主管部门',
+        prop: 'departmentName',
+        required: true
+      },
+      {
+        type: 'dictSelect',
+        label: '标记',
+        prop: 'schoolTag',
+        props: { code: 'school_tag' },
+        required: true
+      }
+    ];
+  });
+  //默认值
+  const baseUrl = reactive({
+    add: '/baseinfo/schoolInfo/save',
+    update: '/baseinfo/schoolInfo/edit'
+  });
+  const formData = ref({ schoolTag: '1' });
+
+  const editRef = ref(null);
+
+  function handleOpen(data = {}) {
+    title.value = data && data.id ? '编辑高校' : '新增高校';
+    formData.value = Object.assign(formData.value, data || {});
+    getProviceList().then((res) => {
+      provinceList.value = res.data.data;
+    });
+    if (data && data.provinceId) {
+      getProviceList(data.provinceId).then((res) => {
+        cityList.value = res.data.data;
+      });
+    }
+    editRef.value?.handleOpen(formData.value);
+  }
+
+  function getProviceList(id = 1) {
+    return proxy.$http.get(`/baseinfo/districtInfo/findInfo/${id}`);
+  }
+
+  defineExpose({ handleOpen });
+</script>

+ 74 - 0
src/views/recycle/remindArea/components/page-search.vue

@@ -0,0 +1,74 @@
+<!-- 搜索表单 -->
+<template>
+  <ele-card :body-style="{ paddingBottom: '8px' }">
+    <ProSearch
+      :items="formItems"
+      ref="searchRef"
+      @search="search"
+      :initKeys="initKeys"
+    ></ProSearch>
+  </ele-card>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits } from 'vue';
+  import ProSearch from '@/components/CommonPage/ProSearch2.vue';
+
+  let { proxy } = getCurrentInstance();
+  const emit = defineEmits(['search']);
+  const godownList = ref([]);
+
+  const formItems = computed(() => {
+    return [
+      { type: 'input', label: '关键字', prop: 'keywords' },
+      {
+        type: 'select',
+        label: '收货仓库',
+        prop: 'godownId',
+        options: godownList.value.map((d) => {
+          return { label: d.godownName, value: d.id };
+        }),
+        props: {
+          filterable: true
+        }
+      },
+      {
+        type: 'datetimerange',
+        label: '建单时间',
+        prop: 'time',
+        props: {
+          format: 'YYYY-MM-DD HH:mm:ss',
+          valueFormat: 'YYYY-MM-DD HH:mm:ss',
+          onChange: (value) => {
+            initKeys.startTime = value ? value[0] : '';
+            initKeys.endTime = value ? value[1] : '';
+            searchRef.value?.setData(initKeys);
+          }
+        },
+        colProps: {
+          span: 6
+        }
+      }
+    ];
+  });
+
+  function getStoreList(name = '') {
+    return proxy.$http.post(`/baseinfo/godown/searchGodown?name=${name}`);
+  }
+  getStoreList().then((res) => {
+    godownList.value = res.data.data;
+  });
+
+  const initKeys = reactive({
+    keywords: '',
+    godownId: '',
+    startTime: '',
+    endTime: ''
+  });
+
+  const searchRef = ref(null);
+  /** 搜索 */
+  const search = (data) => {
+    emit('search', { ...data });
+  };
+</script>

+ 155 - 0
src/views/recycle/remindArea/index.vue

@@ -0,0 +1,155 @@
+<template>
+  <ele-page flex-table>
+    <page-search @search="reload"></page-search>
+
+    <common-table ref="pageRef" :pageConfig="pageConfig" :columns="columns">
+      <template #toolbar>
+        <el-button
+          type="primary"
+          plain
+          :icon="PlusOutlined"
+          v-permission="'recycle:remindArea:add'"
+          @click="handleUpdate()"
+        >
+          新增
+        </el-button>
+        <el-button
+          type="danger"
+          plain
+          :icon="DeleteOutlined"
+          v-permission="'recycle:remindArea:batchDelete'"
+          @click="handleBatchDelete()"
+        >
+          批量删除
+        </el-button>
+      </template>
+
+      <template #action="{ row }">
+        <div>
+          <el-button
+            type="primary"
+            link
+            v-permission="'recycle:remindArea:update'"
+            @click="handleUpdate(row)"
+          >
+            编辑
+          </el-button>
+          <el-button
+            type="danger"
+            link
+            v-permission="'recycle:remindArea:delete'"
+            @click="handleBatchDelete(row)"
+          >
+            删除
+          </el-button>
+          <el-button
+            :type="row.schoolTag == 2 ? 'success' : 'warning'"
+            link
+            v-permission="'recycle:remindArea:changeStatus'"
+            @click="handleChangeStatus(row)"
+          >
+            {{ row.schoolTag == 2 ? '启用' : '停用' }}
+          </el-button>
+        </div>
+      </template>
+    </common-table>
+
+    <page-edit ref="editRef" @success="reload()"></page-edit>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import { ElMessageBox } from 'element-plus/es';
+  import { EleMessage } from 'ele-admin-plus/es';
+  import { PlusOutlined, DeleteOutlined } from '@/components/icons';
+  import CommonTable from '@/components/CommonPage/CommonTable.vue';
+  import pageSearch from './components/page-search.vue';
+  import pageEdit from './components/page-edit.vue';
+  import { useDictData } from '@/utils/use-dict-data';
+  import { useRouter } from 'vue-router';
+  import request from '@/utils/request';
+
+  defineOptions({ name: 'remindArea' });
+  const [schoolLevelDicts] = useDictData(['school_level']);
+
+  /** 表格列配置 */
+  const columns = ref([
+    {
+      type: 'selection',
+      columnKey: 'selection',
+      width: 50,
+      align: 'center',
+      fixed: 'left'
+    },
+    {
+      label: '提醒地区',
+      prop: 'schoolName',
+      align: 'center',
+      minWidth: 140
+    },
+    { label: '推送人', prop: 'provinceName', align: 'center' },
+    {
+      label: '状态',
+      prop: 'schoolLevel',
+      align: 'center',
+      formatter: (row) =>
+        schoolLevelDicts.value.find((d) => d.dictValue == row.schoolLevel)
+          ?.dictLabel
+    },
+    { label: '需提醒仓库', prop: 'cityName', align: 'center' },
+    { label: '添加时间', prop: 'createTime', align: 'center' },
+    {
+      columnKey: 'action',
+      label: '操作',
+      width: 240,
+      align: 'center',
+      slot: 'action'
+    }
+  ]);
+
+  let router = useRouter();
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '/baseinfo/schoolInfo/list',
+    exportUrl: '/baseinfo/schoolInfo/export',
+    fileName: '审核提醒地区',
+    cacheKey: 'remindAreaTable'
+  });
+
+  //刷新表格
+  function reload(where) {
+    pageRef.value?.reload(where);
+  }
+
+  //批量删除
+  function handleBatchDelete(row) {
+    let selections = row ? [row] : pageRef.value?.getSelections();
+    let ids = selections.map((item) => item.id).join(',');
+    let url = `/baseinfo/schoolInfo/removeById/${ids}`;
+    pageRef.value?.operatBatch({
+      title: '确认删除?',
+      method: 'post',
+      url,
+      row
+    });
+  }
+  //启用停用
+  function handleChangeStatus(row) {
+    let message = row.useStatus == 1 ? '确认停用?' : '确认启用?';
+    let data = JSON.parse(JSON.stringify(row));
+    data.useStatus = row.useStatus == 1 ? 0 : 1;
+    pageRef.value?.messageBoxConfirm({
+      message,
+      fetch: () => request.post('/baseinfo/godown/update', data)
+    });
+  }
+
+  //编辑页面
+  const editRef = ref(null);
+  function handleUpdate(row) {
+    editRef.value?.handleOpen(row);
+  }
+</script>

+ 106 - 0
src/views/recycle/remindBooks/components/page-edit.vue

@@ -0,0 +1,106 @@
+<!-- 搜索表单 -->
+<template>
+  <simple-form-modal
+    :title="title"
+    :items="formItems"
+    ref="editRef"
+    :baseUrl="baseUrl"
+    @success="(data) => emit('success', data)"
+  ></simple-form-modal>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits, getCurrentInstance } from 'vue';
+  import { useFormData } from '@/utils/use-form-data';
+  import SimpleFormModal from '@/components/CommonPage/SimpleFormModal.vue';
+  const { proxy } = getCurrentInstance();
+
+  //获取省市
+  const provinceList = ref([]);
+  const cityList = ref([]);
+  const title = ref('新增高校');
+  const emit = defineEmits(['success']);
+
+  const formItems = computed(() => {
+    return [
+      { type: 'input', label: '学校名称', prop: 'schoolName', required: true },
+      {
+        type: 'select',
+        label: '省份',
+        prop: 'provinceId',
+        required: true,
+        options: provinceList.value.map((d) => {
+          return { label: d.district, value: d.id };
+        }),
+        props: {
+          filterable: true,
+          onChange: (val) => {
+            getProviceList(val).then((res) => {
+              cityList.value = res.data.data;
+            });
+          }
+        }
+      },
+      {
+        type: 'select',
+        label: '所在市',
+        prop: 'cityId',
+        required: true,
+        options: cityList.value.map((d) => {
+          return { label: d.district, value: d.id };
+        }),
+        props: {
+          filterable: true
+        }
+      },
+      {
+        type: 'dictSelect',
+        label: '办学层次',
+        prop: 'schoolLevel',
+        props: { code: 'school_level' },
+        required: true
+      },
+      {
+        type: 'input',
+        label: '主管部门',
+        prop: 'departmentName',
+        required: true
+      },
+      {
+        type: 'dictSelect',
+        label: '标记',
+        prop: 'schoolTag',
+        props: { code: 'school_tag' },
+        required: true
+      }
+    ];
+  });
+  //默认值
+  const baseUrl = reactive({
+    add: '/baseinfo/schoolInfo/save',
+    update: '/baseinfo/schoolInfo/edit'
+  });
+  const formData = ref({ schoolTag: '1' });
+
+  const editRef = ref(null);
+
+  function handleOpen(data = {}) {
+    title.value = data && data.id ? '编辑高校' : '新增高校';
+    formData.value = Object.assign(formData.value, data || {});
+    getProviceList().then((res) => {
+      provinceList.value = res.data.data;
+    });
+    if (data && data.provinceId) {
+      getProviceList(data.provinceId).then((res) => {
+        cityList.value = res.data.data;
+      });
+    }
+    editRef.value?.handleOpen(formData.value);
+  }
+
+  function getProviceList(id = 1) {
+    return proxy.$http.get(`/baseinfo/districtInfo/findInfo/${id}`);
+  }
+
+  defineExpose({ handleOpen });
+</script>

+ 74 - 0
src/views/recycle/remindBooks/components/page-search.vue

@@ -0,0 +1,74 @@
+<!-- 搜索表单 -->
+<template>
+  <ele-card :body-style="{ paddingBottom: '8px' }">
+    <ProSearch
+      :items="formItems"
+      ref="searchRef"
+      @search="search"
+      :initKeys="initKeys"
+    ></ProSearch>
+  </ele-card>
+</template>
+
+<script setup>
+  import { reactive, ref, defineEmits } from 'vue';
+  import ProSearch from '@/components/CommonPage/ProSearch2.vue';
+
+  let { proxy } = getCurrentInstance();
+  const emit = defineEmits(['search']);
+  const godownList = ref([]);
+
+  const formItems = computed(() => {
+    return [
+      { type: 'input', label: 'ISBN', prop: 'isbn' },
+      {
+        type: 'select',
+        label: '收货仓库',
+        prop: 'godownId',
+        options: godownList.value.map((d) => {
+          return { label: d.godownName, value: d.id };
+        }),
+        props: {
+          filterable: true
+        }
+      },
+      {
+        type: 'datetimerange',
+        label: '建单时间',
+        prop: 'time',
+        props: {
+          format: 'YYYY-MM-DD HH:mm:ss',
+          valueFormat: 'YYYY-MM-DD HH:mm:ss',
+          onChange: (value) => {
+            initKeys.startTime = value ? value[0] : '';
+            initKeys.endTime = value ? value[1] : '';
+            searchRef.value?.setData(initKeys);
+          }
+        },
+        colProps: {
+          span: 6
+        }
+      }
+    ];
+  });
+
+  function getStoreList(name = '') {
+    return proxy.$http.post(`/baseinfo/godown/searchGodown?name=${name}`);
+  }
+  getStoreList().then((res) => {
+    godownList.value = res.data.data;
+  });
+
+  const initKeys = reactive({
+    isbn: '',
+    godownId: '',
+    startTime: '',
+    endTime: ''
+  });
+
+  const searchRef = ref(null);
+  /** 搜索 */
+  const search = (data) => {
+    emit('search', { ...data });
+  };
+</script>

+ 101 - 0
src/views/recycle/remindBooks/index.vue

@@ -0,0 +1,101 @@
+<template>
+  <ele-page flex-table>
+    <page-search @search="reload"></page-search>
+
+    <common-table ref="pageRef" :pageConfig="pageConfig" :columns="columns">
+      <template #toolbar>
+        <el-button
+          type="primary"
+          plain
+          :icon="PlusOutlined"
+          v-permission="'recycle:remindArea:add'"
+          @click="handleUpdate()"
+        >
+          新增
+        </el-button>
+        <el-button
+          type="danger"
+          plain
+          :icon="DeleteOutlined"
+          v-permission="'recycle:remindArea:batchDelete'"
+          @click="handleBatchDelete()"
+        >
+          批量删除
+        </el-button>
+      </template>
+
+      <template #action="{ row }">
+        <el-button
+          type="danger"
+          link
+          v-permission="'recycle:remindArea:delete'"
+          @click="handleBatchDelete(row)"
+        >
+          删除
+        </el-button>
+      </template>
+    </common-table>
+
+    <page-edit ref="editRef" @success="reload()"></page-edit>
+  </ele-page>
+</template>
+
+<script setup>
+  import { ref, reactive } from 'vue';
+  import { ElMessageBox } from 'element-plus/es';
+  import { EleMessage } from 'ele-admin-plus/es';
+  import { PlusOutlined, DeleteOutlined } from '@/components/icons';
+  import CommonTable from '@/components/CommonPage/CommonTable.vue';
+  import pageSearch from './components/page-search.vue';
+  import pageEdit from './components/page-edit.vue';
+  import { useDictData } from '@/utils/use-dict-data';
+  import { useRouter } from 'vue-router';
+  import request from '@/utils/request';
+
+  defineOptions({ name: 'remindBooks' });
+  const [schoolLevelDicts] = useDictData(['school_level']);
+
+  /** 表格列配置 */
+  const columns = ref([
+    { type: 'selection', columnKey: 'selection', width: 50, fixed: 'left' },
+    { label: '图片', prop: 'picture', width: 140 },
+    { label: 'isbn', prop: 'schoolName' },
+    { label: '书名', prop: 'provinceName' },
+    { label: '作者', prop: 'provinceName' },
+    { label: '出版社', prop: 'provinceName' },
+    { label: '出版时间', prop: 'provinceName' },
+    { label: '定价', prop: 'provinceName' },
+    { label: '需提醒仓库', prop: 'cityName' },
+    { label: '添加时间', prop: 'createTime' },
+    { columnKey: 'action', label: '操作', width: 120, slot: 'action' }
+  ]);
+
+  let router = useRouter();
+  /** 页面组件实例 */
+  const pageRef = ref(null);
+
+  const pageConfig = reactive({
+    pageUrl: '/baseinfo/schoolInfo/list',
+    exportUrl: '/baseinfo/schoolInfo/export',
+    fileName: '审核提醒书籍',
+    cacheKey: 'remindBooksTable'
+  });
+
+  //刷新表格
+  function reload(where) {
+    pageRef.value?.reload(where);
+  }
+
+  //批量删除
+  function handleBatchDelete(row) {
+    let selections = row ? [row] : pageRef.value?.getSelections();
+    let ids = selections.map((item) => item.id).join(',');
+    let url = `/baseinfo/schoolInfo/removeById/${ids}`;
+    pageRef.value?.operatBatch({
+      title: '确认删除?',
+      method: 'post',
+      url,
+      row
+    });
+  }
+</script>