Browse Source

Merge branch 'master' of http://36.137.93.232:3000/hf/byte-sailing-new

cz 2 years ago
parent
commit
5c60ebc9ff

BIN
src/assets/shibei.png


+ 552 - 0
src/components/byTable/index copy.vue

@@ -0,0 +1,552 @@
+<template>
+  <div class="header-actions" v-if="getActionList.length != 0">
+    <div class="overflow-box">
+      <el-button
+        v-for="(item, index) in getActionList"
+        :key="index"
+        :type="item.type || 'primary'"
+        :plain="item.plain || false"
+        v-bind="getHeaderActions(item)"
+        @click="item.action"
+        :disabled="item.disabled || false"
+      >
+        {{ item.text }}
+      </el-button>
+    </div>
+  </div>
+  <div class="table-list-container by-table">
+    <!-- v-if="!hideHeader" -->
+    <header v-if="false" class="header">
+      <h2>{{ title }}</h2>
+    </header>
+    <div class="by-search" v-if="!hideSearch">
+      <div style="display: flex">
+        <div
+          class="by-dropdown"
+          v-for="(i,index) in selectConfigCopy"
+          :key="i.prop"
+          style="margin-right: 10px"
+        >
+          <div class="by-dropdown-title">
+            {{ i.label || i.labelCopy
+            }}<i
+              style="margin-left: 5px"
+              class="iconfont icon-iconm_xialan1"
+            ></i>
+          </div>
+          <ul class="by-dropdown-lists">
+            <li
+              @click="searchItemSelct('all', i,index)"
+              v-if="i.isShowAll === false ? i.isShowAll : true"
+            >
+              全部
+            </li>
+            <li
+              v-for="j in i.data"
+              :key="j.value"
+              @click="searchItemSelct(j, i)"
+            >
+              {{ j.label }}
+            </li>
+          </ul>
+        </div>
+      </div>
+
+      <div style="display: flex">
+        <el-input
+          placeholder="请输入关键字"
+          suffix-icon="search"
+          size="mini"
+          v-model="keywrod"
+          @keyup.enter="searchFn"
+        >
+        </el-input>
+        <el-button
+          type="primary"
+          style="margin-left: 10px"
+          size="default"
+          @click="searchFn"
+          >搜索</el-button
+        >
+
+        <div class="more-icon"><i class="el-icon-wind-power"></i></div>
+        <div class="more-icon">
+          <i class="el-icon-notebook-2"></i>
+        </div>
+      </div>
+    </div>
+
+    <component :is="containerTag">
+      <div class="filter-form-container">
+        <slot />
+      </div>
+
+      <el-table
+        ref="hocElTable"
+        v-loading="loading"
+        :data="source"
+        v-if="!hideTable"
+        style="width: 100%"
+        v-bind="$attrs"
+        v-on="tableEvents"
+        row-key="id"
+        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
+      >
+        <el-table-column
+          v-for="(item, index) in config"
+          :key="index"
+          v-bind="getAttrsValue(item)"
+          :type="item.type || ''"
+          :selectable="
+            (rowData, rowIndex) => isSelectable(rowData, rowIndex, item)
+          "
+        >
+          <template #default="scope" v-if="!item.type">
+            <slot
+              :name="item.attrs.slot"
+              :item="scope.row"
+              v-if="item.attrs.slot"
+            >
+              插槽占位符
+            </slot>
+            <div v-else-if="isFunction(getValue(scope, item))">
+              <component
+                :is="renderTypeList[getMatchRenderFunction(item)].target"
+                :cell-list="getValue(scope, item)()"
+                :row="scope.row"
+                :parent="getParent"
+                @click="
+                  ($event) => {
+                    handleNativeClick(getAttrsValue(item), $event, item);
+                  }
+                "
+              />
+            </div>
+            <div v-else>
+              {{ getValue(scope, item) }}
+            </div>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <el-row
+        v-if="!hidePagination"
+        class="table-pagination"
+        justify="end"
+        type="flex"
+      >
+        <el-pagination
+          background
+          layout="total, sizes, prev, pager, next, jumper"
+          :current-page="getPagination.pageNum"
+          :page-size="getPagination.pageSize"
+          :total="getPagination.total"
+          @size-change="handleSizeChange"
+          @current-change="handlePageChange"
+        />
+      </el-row>
+    </component>
+  </div>
+</template>
+  
+  <script>
+import { isFunction as isFn, isBoolean } from "./type";
+import ElementsMapping from "./ElementsMapping";
+import ComponentsMapping from "./ComponentsMapping";
+import { computed, defineComponent, getCurrentInstance, ref } from "vue";
+import expand from "./expand";
+export default defineComponent({
+  name: "Table",
+  components: {
+    ElementsMapping,
+    ComponentsMapping,
+  },
+  props: {
+    hideSearch: {
+      type: Boolean,
+      default: false,
+    },
+    hideTable: {
+      type: Boolean,
+      default: false,
+    },
+    //顶部搜索下拉配置
+    selectConfig: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    // 获取表格元数据时携带的参数
+    filterParams: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    // 表格加载 loading
+    loading: {
+      type: Boolean,
+      default: false,
+    },
+    // 表格名称
+    title: {
+      type: String,
+      default: "",
+    },
+    // 表格元数据
+    source: {
+      type: Array,
+      required: true,
+      default() {
+        return [];
+      },
+    },
+    searchConfig: {
+      type: Object,
+      default() {
+        return {
+          keyword: "",
+        };
+      },
+    },
+    // 指定外层容器的渲染组件
+    containerTag: {
+      type: String,
+      default: "div",
+    },
+    // 是否隐藏表头
+    hideHeader: {
+      type: Boolean,
+      default: false,
+    },
+    // 是否隐藏分页
+    hidePagination: {
+      type: Boolean,
+      default: false,
+    },
+    // 分页配置
+    pagination: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    // 表格配置文件
+    config: {
+      type: Array,
+      default() {
+        return [];
+      },
+    },
+    // 表头右上方的按钮组
+    actionList: {
+      type: Array,
+      default() {
+        return [{ text: "", action: () => {} }];
+      },
+    },
+    // element table 原生事件
+    tableEvents: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+    searchKey: {
+      type: String,
+      default: "keyword",
+    },
+    // 是否显示过滤的全部选项
+    // isShowAll: {
+    //   type: Boolean,
+    //   default: true,
+    // },
+  },
+  setup(props) {
+    const { proxy } = getCurrentInstance();
+    const keywrod = ref("");
+    const selectConfigCopy = computed(() => {
+      return props.selectConfig.map((item) => {
+        if(!item.labelCopy) item.labelCopy = {...item}.label;
+        return item;
+      });
+    });
+    console.log(selectConfigCopy);
+    const getAttrsValue = (item) => {
+      const { attrs } = item;
+      const result = {
+        ...attrs,
+      };
+      delete result.prop;
+      return result;
+    };
+    const renderTypeList = ref({
+      render: {},
+      renderHTML: {
+        target: "elements-mapping",
+      },
+      renderComponent: {
+        target: "components-mapping",
+      },
+    });
+    const getParent = computed(() => {
+      return proxy.$parent;
+    });
+    const getPagination = computed(() => {
+      const params = {
+        pageNum: 1,
+        pageSize: 10,
+        total: 0,
+      };
+      return Object.assign({}, params, props.pagination);
+    });
+    const getActionList = computed(() => {
+      return props.actionList
+        .slice()
+        .reverse()
+        .filter((it) => it.text);
+    });
+    const getValue = (scope, configItem) => {
+      const prop = configItem.attrs.prop;
+      const renderName = getMatchRenderFunction(configItem);
+      const renderObj = renderTypeList.value[renderName];
+      if (renderObj && isFunction(configItem[renderName])) {
+        return renderObj.target
+          ? getRenderValue(scope, configItem, {
+              name: renderName,
+              type: "bind",
+            })
+          : getRenderValue(scope, configItem);
+      }
+      return scope.row[prop];
+    };
+    const getRenderValue = (
+      scope,
+      item,
+      fn = { name: "render", type: "call" }
+    ) => {
+      const prop = item.attrs.prop;
+      const propValue = prop && scope.row[prop];
+      scope.row.$index = scope.$index;
+      const args = propValue !== undefined ? propValue : scope.row;
+
+      return item[fn.name][fn.type](getParent.value, args);
+    };
+    // 匹配 render 开头的函数
+    const getMatchRenderFunction = (obj) => {
+      return Object.keys(obj).find((key) => {
+        const matchRender = key.match(/^render.*/);
+        return matchRender && matchRender[0];
+      });
+    };
+    const isFunction = (fn) => {
+      return isFn(fn);
+    };
+    const searchFn = (val) => {
+      console.log(props);
+      proxy.$emit(
+        "getList",
+        Object.assign(props.filterParams, { [props.searchKey]: keywrod.value })
+      );
+    };
+    const handlePageChange = (val) => {
+      proxy.$emit(
+        "getList",
+        Object.assign(props.filterParams, { pageNum: val })
+      );
+    };
+    const handleSizeChange = (val) => {
+      proxy.$emit(
+        "getList",
+        Object.assign(props.filterParams, { pageSize: val })
+      );
+    };
+    const getHeaderActions = (item) => {
+      return {
+        ...item.attrs,
+      };
+    };
+    const stopBubbles = (e) => {
+      const event = e || window.event;
+      if (event && event.stopPropagation) {
+        event.stopPropagation();
+      } else {
+        event.cancelBubble = true;
+      }
+    };
+    const handleNativeClick = ({ isBubble }, e, item) => {
+      // 考虑到单元格内渲染了组件,并且组件自身可能含有点击事件,故添加了阻止冒泡机制
+      // 若指定 isBubble 为 false,则当前单元格恢复冒泡机制
+      if (isBoolean(isBubble) && !isBubble) return;
+      stopBubbles(e);
+    };
+    //下拉搜索相关
+
+    const searchItemSelct = (item, i,index) => {
+      if (item == "all") {
+        console.log(props.selectConfig)
+        i.label = {...props.selectConfig[index]}.labelCopy
+        proxy.$emit(
+          "getList",
+          Object.assign(props.filterParams, { [i.prop]: "" })
+        );
+        return;
+      }
+      i.label = item.label;
+      console.log(item, i);
+      proxy.$emit(
+        "getList",
+        Object.assign(props.filterParams, { [i.prop]: item.value })
+      );
+    };
+
+    const isSelectable = (row, index, item) => {
+      if (item.type === "selection") {
+        if (item.attrs && item.attrs.checkAtt) {
+          if (row[item.attrs.checkAtt]) {
+            return row[item.attrs.checkAtt];
+          }
+        } else {
+          return true;
+        }
+      }
+    };
+
+    return {
+      getParent,
+      getPagination,
+      renderTypeList,
+      getActionList,
+      getAttrsValue,
+      getValue,
+      getRenderValue,
+      getMatchRenderFunction,
+      isFunction,
+      handlePageChange,
+      handleSizeChange,
+      getHeaderActions,
+      stopBubbles,
+      handleNativeClick,
+      keywrod,
+      searchFn,
+      searchItemSelct,
+      selectConfigCopy,
+      isSelectable,
+    };
+  },
+});
+</script>
+  <style>
+.table-list-container th {
+  color: #333 !important;
+}
+.by-table td .el-button + .el-button {
+  margin-left: 0 !important;
+}
+.by-table td .el-button {
+  background: none !important;
+  margin: 0 !important;
+  padding: 8px 6px !important;
+}
+</style>
+  <style lang="scss" scoped>
+.by-search {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 10px;
+}
+.by-dropdown {
+  position: relative;
+  text-align: left;
+  height: 32px;
+  z-index: 100;
+  padding: 0 10px;
+  transition: all 0.5s ease;
+  cursor: pointer;
+  line-height: 32px;
+  .by-dropdown-title {
+    font-size: 14px;
+    background-color: #fff;
+  }
+  ul {
+    position: absolute;
+    left: 0;
+    
+    top: 32px;
+    padding: 0;
+    margin: 0;
+    z-index: 100;
+    display: none;
+    white-space: nowrap;
+    li {
+      list-style: none;
+      font-size: 12px;
+      height: 30px;
+      padding: 0 10px;
+    }
+    li:hover {
+      background-color: #eff6ff;
+      color: #0084ff;
+    }
+  }
+}
+
+.by-dropdown::before {
+  display: block;
+  width: 1px;
+  content: " ";
+  position: absolute;
+  height: 14px;
+  top: 8px;
+  background-color: #ddd;
+  right: 0;
+  z-index: 101;
+}
+
+.by-dropdown:hover {
+  background: #ffffff;
+
+  border-radius: 2px 2px 2px 2px;
+  opacity: 1;
+  ul {
+    background: #ffffff;
+    box-shadow: 0px 2px 16px 1px rgba(0, 0, 0, 0.06);
+    border-radius: 2px 2px 2px 2px;
+    opacity: 1;
+    display: block;
+    text-align: left;
+  }
+}
+.header-actions {
+  flex: 1;
+  overflow-x: auto;
+  padding: 20px;
+  background: #fff;
+  margin-bottom: 20px;
+  .overflow-box {
+    :deep() .el-button:nth-child(1) {
+      margin-left: 10px;
+    }
+  }
+}
+.table-list-container {
+  background: #fff;
+  padding: 13px 20px 20px;
+  .table-pagination {
+    padding-top: 20px;
+  }
+  .header {
+    display: flex;
+    padding-bottom: 20px;
+  }
+  .el-table {
+    :deep() th {
+      font-size: 14px;
+    }
+    :deep() td {
+      font-size: 14px;
+    }
+  }
+}
+</style>

+ 2 - 4
src/main.js

@@ -44,7 +44,7 @@ import {
   selectDictLabels
 } from '@/utils/ruoyi'
 
-import { dictDataEcho, dictValueLabel, moneyFormat, calculationWeek,getDict } from '@/utils/util'
+import { dictDataEcho, dictValueLabel, moneyFormat, calculationWeek, getDict, getPdf } from '@/utils/util'
 
 // 分页组件
 import Pagination from '@/components/Pagination'
@@ -80,9 +80,7 @@ app.config.globalProperties.dictValueLabel = dictValueLabel
 app.config.globalProperties.moneyFormat = moneyFormat
 app.config.globalProperties.calculationWeek = calculationWeek
 app.config.globalProperties.getDict = getDict
-
-
-
+app.config.globalProperties.getPdf = getPdf
 
 
 // 全局组件挂载

+ 94 - 6
src/utils/util.js

@@ -1,10 +1,8 @@
 import moment from "moment";
-
-import {
-  post,
-  get
-} from "@/utils/request";
+import { post, get } from "@/utils/request";
 import Cookies from "js-cookie";
+import html2canvas from 'html2canvas'
+import JsPDF from 'jspdf'
 
 //根据value值回显字典label值
 export function dictDataEcho(value, arr) {
@@ -103,4 +101,94 @@ export function calculationWeek(val, format) {
   let index = new Date(moment(val, format).format("yyyy-MM-DD")).getDay();
   let week = weekArrayList[index];
   return week;
-}
+}
+
+export function getPdf(title) {
+  // pdfDom 这个就是你vue页面中定义的ID  比如<div id="pdfDom">  这个也要避下雷
+  const element = document.getElementById("pdfDom");
+  window.pageYoffset = 0;
+  document.documentElement.scrollTop = 0;
+  document.body.scrollTop = 0;
+  setTimeout(() => {
+    // const nowDate = new Date();
+    // const date = {
+    //   year: nowDate.getFullYear(),
+    //   month: nowDate.getMonth() + 1,
+    //   date: nowDate.getDate(),
+    //   hours: nowDate.getHours(),
+    //   minutes: nowDate.getMinutes(),
+    //   seconds: nowDate.getSeconds(),
+    // };
+    // const newMonth = date.month > 10 ? date.month : "0" + date.month;
+    // const newDay = date.date > 10 ? date.date : "0" + date.date;
+    // const newMinutes = date.minutes < 10 ? "0" + date.minutes : date.minutes;
+    // const newSeconds = date.seconds < 10 ? "0" + date.seconds : date.seconds;
+    // const value = date.year + newMonth + newDay + date.hours + newMinutes + newSeconds;
+    let id = "";
+    //创建一个画布    ---  增加导出的pdf水印 !!
+    let can = document.createElement("canvas");
+    //设置画布的长宽
+    can.width = 400;
+    can.height = 500;
+    let cans = can.getContext("2d");
+    //旋转角度
+    cans.rotate((-15 * Math.PI) / 180);
+    cans.font = "18px Vedana";
+    //设置填充绘画的颜色、渐变或者模式
+    cans.fillStyle = "rgba(200, 200, 200, 0.40)";
+    //设置文本内容的当前对齐方式
+    cans.textAlign = "left";
+    //设置在绘制文本时使用的当前文本基线
+    cans.textBaseline = "Middle";
+    //在画布上绘制填色的文本(输出的文本,开始绘制文本的X坐标位置,开始绘制文本的Y坐标位置)
+    //cans.fillText(value, can.width / 8, can.height / 2)
+    let div = document.createElement("div");
+    div.id = id;
+    div.style.pointerEvents = "none";
+    div.style.top = "2000px";
+    div.style.left = "-2000px";
+    div.style.position = "fixed";
+    div.style.zIndex = "100000";
+    div.style.width = document.getElementById("pdfDom").scrollHeight + "px";
+    div.style.height = document.getElementById("pdfDom").scrollHeight + "px";
+    div.style.background = "url(" + can.toDataURL("image/png") + ") left top repeat";
+    document.getElementById("pdfDom").appendChild(div); // 到页面中
+    html2canvas(element, {
+      allowTaint: true,
+      useCORS: true, // 需要注意,element的 高度 宽度一定要在这里定义一下,不然会存在只下载了当前你能看到的页面   避雷避雷!!!
+      scale: 2, // 提升画面质量,但是会增加文件大小
+      height: document.getElementById("pdfDom").scrollHeight,
+      windowHeight: document.getElementById("pdfDom").scrollHeight,
+    }).then(function (canvas) {
+      var contentWidth = canvas.width;
+      var contentHeight = canvas.height;
+      // 一页pdf显示html页面生成的canvas高度;
+      var pageHeight = (contentWidth * 841.89) / 592.28;
+      // 未生成pdf的html页面高度
+      var leftHeight = contentHeight;
+      // 页面偏移
+      var position = 0;
+      // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
+      var imgWidth = 595.28;
+      var imgHeight = (592.28 / contentWidth) * contentHeight;
+      var pageData = canvas.toDataURL("image/jpeg", 1.0);
+      var pdf = new JsPDF("", "pt", "a4");
+      // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
+      // 当内容未超过pdf一页显示的范围,无需分页
+      if (leftHeight < pageHeight) {
+        pdf.addImage(pageData, "JPEG", 0, 0, imgWidth, imgHeight);
+      } else {
+        while (leftHeight > 0) {
+          pdf.addImage(pageData, "JPEG", 0, position, imgWidth, imgHeight);
+          leftHeight -= pageHeight;
+          position -= 841.89;
+          // 避免添加空白页
+          if (leftHeight > 0) {
+            pdf.addPage();
+          }
+        }
+      }
+      pdf.save(title + ".pdf");
+    });
+  }, 1000);
+}

+ 5 - 2
src/views/finance/fundManage/flow/index.vue

@@ -25,7 +25,7 @@
       </byTable>
     </div>
 
-    <el-dialog :title="modalType == 'add' ? '添加账户' : '编辑账户'" v-if="dialogVisible" v-model="dialogVisible" width="600" v-loading="loadingDialog">
+    <el-dialog :title="modalType == 'add' ? '添加流水' : '编辑流水'" v-if="dialogVisible" v-model="dialogVisible" width="600" v-loading="loadingDialog">
       <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit">
         <template #transactionTime>
           <div>
@@ -81,6 +81,7 @@ import byTable from "@/components/byTable/index";
 import byForm from "@/components/byForm/index";
 import useUserStore from "@/store/modules/user";
 import { ElMessage, ElMessageBox } from "element-plus";
+import moment from "moment";
 
 const { proxy } = getCurrentInstance();
 const accountCurrency = ref([]);
@@ -372,7 +373,9 @@ const rules = ref({
 });
 const openModal = (val) => {
   modalType.value = val;
-  formData.data = {};
+  formData.data = {
+    transactionTime: moment().format("yyyy-MM-DD HH:mm:ss")
+  };
   loadingDialog.value = false;
   dialogVisible.value = true;
 };

+ 41 - 0
src/views/process/processConfig/endBtn.vue

@@ -0,0 +1,41 @@
+<template>
+    <div class="end-btn">
+        <div class="icon">
+            <div class="fan"></div>
+        </div>
+        <div class="text">结束</div>
+    </div>
+</template>
+<style lang="scss">
+    .end-btn{
+        height: 90px;
+        width: 150px;
+        background: #fff;
+        text-align: center;
+        box-shadow: 0px 2px 10px 1px rgba(51,51,51,0.1);
+        border-radius: 10px 10px 10px 10px;
+        padding: 10px 0;
+        .icon {
+            height: 40px;
+            width: 40px;
+            background: #FF655B;
+            border-radius: 20px;
+            margin: 0 auto;
+            padding: 12px;
+            //画一个三角形
+            .fan {
+                height: 16px;
+                height: 16px;
+                border-radius: 2px;
+                background: #fff;
+                
+            }
+            
+        }
+        .text{
+            color: #333;
+            font-size: 14px;
+            margin-top: 10px; 
+        }
+    }
+</style>

+ 69 - 0
src/views/process/processConfig/handleBtn.vue

@@ -0,0 +1,69 @@
+<template>
+    <div class="handle-btn">
+        <div class="icon-box">
+            <div class="icon">
+                <i class="iconfont icon-icomx_banli"></i>
+            </div>
+            <div class="icon-text">办理</div>
+        </div>
+        <div class="title">{{title || '待配置'}}</div>
+    </div>
+</template>
+<script setup>
+    import { defineProps, inject, ref } from 'vue'
+    
+    let title = ref('')
+    let getNode = inject('getNode')
+    const node = getNode()
+    console.log(node)
+    node.on('change:data', ({current}) => {
+        title.value = current.title
+    })
+
+</script>
+<style lang="scss">
+    .handle-btn{
+        height: 90px;
+        width: 150px;
+        background: #fff;
+        text-align: center;
+        box-shadow: 0px 2px 10px 1px rgba(51,51,51,0.1);
+        border-radius: 10px 10px 10px 10px;
+        padding: 10px;
+        .title {
+            width: 100%;
+            height: 40px;
+            line-height: 40px;
+            padding: 0 20px;
+            text-align: left;
+            background: #eee;
+            border-radius: 10px;
+            margin-top: 10px;
+            //文字一行多余省略
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+        }
+        .icon-box{
+            display: flex;
+            height: 20px;
+            line-height: 20px;
+            color: #333;
+            font-size: 14px;
+            .icon{
+                height: 20px;
+                width: 20px;
+                border-radius: 10px;
+                background: #FF9315;
+                color: #fff;
+                i{
+                    color: #fff;
+                    font-size: 12px;
+                }
+            }
+            .icon-text{
+                margin-left:10px;
+            }
+        }
+    }
+</style>

+ 57 - 0
src/views/process/processConfig/startBtn.vue

@@ -0,0 +1,57 @@
+<template>
+    <div class="start-btn"  @click="formTableChange">
+        <div class="icon">
+            <div class="sanjiao"></div>
+        </div>
+        <div class="text">开始{{title}}</div>
+    </div>
+</template>
+<script setup>
+    import { defineProps, inject, ref } from 'vue'
+    
+    let title = ref('')
+    let getNode = inject('getNode')
+    const node = getNode()
+    console.log(node)
+    node.on('change:data', ({current}) => {
+        title.value = current.title
+    })
+
+</script>
+<style lang="scss">
+    .start-btn{
+        height: 90px;
+        width: 150px;
+        background: #fff;
+        text-align: center;
+        box-shadow: 0px 2px 10px 1px rgba(51,51,51,0.1);
+        border-radius: 10px 10px 10px 10px;
+        padding: 10px 0;
+        .icon {
+            height: 40px;
+            width: 40px;
+            background: #39C55A;
+            border-radius: 20px;
+            margin: 0 auto;
+            //画一个三角形
+            .sanjiao {
+                width: 0;
+                height: 0;
+                border-left: 10px solid transparent;
+                border-right: 10px solid transparent;
+                border-bottom: 10px solid #fff;
+                margin: 0 auto;
+                position: relative;
+                top: 15px;
+                left: 2px;
+                transform: rotate(90deg);
+            }
+            
+        }
+        .text{
+            color: #333;
+            font-size: 14px;
+            margin-top: 10px; 
+        }
+    }
+</style>

+ 67 - 28
src/views/purchaseManage/purchaseManage/handoverSlip/index.vue

@@ -33,7 +33,7 @@
               <el-table-column prop="productCode" label="物品编码" width="140" />
               <el-table-column prop="productName" label="物品名称" min-width="220" />
               <el-table-column prop="productUnit" label="单位" width="100" />
-              <el-table-column prop="productUnit" label="待处理数量" width="120" />
+              <el-table-column prop="expendQuantity" label="待处理数量" width="120" />
               <el-table-column label="转生产数量" width="160">
                 <template #default="{ row, $index }">
                   <div style="width: 100%">
@@ -46,8 +46,8 @@
               <el-table-column label="完工期限" width="160">
                 <template #default="{ row, $index }">
                   <div style="width: 100%">
-                    <el-form-item :prop="'list.' + $index + '.quantity'" :rules="rules.quantity" :inline-message="true">
-                      <el-date-picker v-model="row.quantity" type="date" placeholder="请选择完工期限" value-format="YYYY-MM-DD" />
+                    <el-form-item :prop="'list.' + $index + '.time'" :rules="rules.time" :inline-message="true">
+                      <el-date-picker v-model="row.time" type="date" placeholder="请选择完工期限" value-format="YYYY-MM-DD" :disabled="true" />
                     </el-form-item>
                   </div>
                 </template>
@@ -94,7 +94,7 @@ const config = computed(() => {
     {
       attrs: {
         label: "外销合同编号",
-        prop: "subscribeCode",
+        prop: "contractCode",
       },
     },
     {
@@ -106,13 +106,13 @@ const config = computed(() => {
     {
       attrs: {
         label: "业务员",
-        prop: "subscribeCode",
+        prop: "userName",
       },
     },
     {
       attrs: {
         label: "版本号",
-        prop: "subscribeCode",
+        prop: "contractVersion",
       },
     },
     {
@@ -136,13 +136,13 @@ const config = computed(() => {
     {
       attrs: {
         label: "待处理数量",
-        prop: "count",
+        prop: "expendQuantity",
       },
     },
     {
       attrs: {
         label: "详情",
-        prop: "count",
+        prop: "remark",
       },
     },
     {
@@ -184,7 +184,7 @@ const config = computed(() => {
 const getList = async (req) => {
   sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
   loading.value = true;
-  proxy.post("/subscribeDetail/page", sourceList.value.pagination).then((message) => {
+  proxy.post("/contractProduct/page", sourceList.value.pagination).then((message) => {
     console.log(message);
     sourceList.value.data = message.rows;
     sourceList.value.pagination.total = message.total;
@@ -225,25 +225,27 @@ const formOption = reactive({
   rules: [],
 });
 const formData = reactive({
-  data: {},
+  data: {
+    list: [],
+  },
 });
 const formConfig = computed(() => {
   return [
-    {
-      label: "基本信息",
-    },
-    {
-      type: "select",
-      prop: "warehouseId",
-      label: "工单类型",
-      data: [],
-    },
-    {
-      type: "input",
-      prop: "remark",
-      label: "备注",
-      itemType: "textarea",
-    },
+    // {
+    //   label: "基本信息",
+    // },
+    // {
+    //   type: "select",
+    //   prop: "warehouseId",
+    //   label: "工单类型",
+    //   data: [],
+    // },
+    // {
+    //   type: "input",
+    //   prop: "remark",
+    //   label: "备注",
+    //   itemType: "textarea",
+    // },
     {
       type: "slot",
       slotName: "details",
@@ -252,15 +254,49 @@ const formConfig = computed(() => {
   ];
 });
 const rules = ref({
-  warehouseId: [{ required: true, message: "请选择仓库", trigger: "change" }],
+  quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
 });
 const transferToProduction = (row) => {
-  console.log(selectData.value, row);
+  if (row && row.id) {
+    formData.data = {
+      list: [
+        {
+          sourceId: "1",
+          source: "1",
+          productId: row.productId,
+          productCode: row.productCode,
+          productName: row.productName,
+          productUnit: row.productUnit,
+          expendQuantity: row.expendQuantity,
+          quantity: undefined,
+        },
+      ],
+    };
+  } else {
+    formData.data = {
+      list: selectData.value.map((item) => {
+        return {
+          sourceId: "1",
+          source: "1",
+          productId: item.productId,
+          productCode: item.productCode,
+          productName: item.productName,
+          productUnit: item.productUnit,
+          expendQuantity: item.expendQuantity,
+          quantity: undefined,
+        };
+      }),
+    };
+  }
+  dialogVisible.value = true;
 };
 const submitForm = () => {
   submit.value.handleSubmit(() => {
+    if (!(formData.data.list && formData.data.list.length > 0)) {
+      return ElMessage('请至少添加一条产品明细')
+    }
     loadingDialog.value = true;
-    proxy.post("/stock/stockTransfer", formData.data).then(
+    proxy.post("/workOrder/addBatch", formData.data.list).then(
       () => {
         ElMessage({
           message: "提交成功",
@@ -285,4 +321,7 @@ const handleDelete = (index) => {
 .tenant {
   margin: 20px;
 }
+::v-deep(.el-input-number .el-input__inner) {
+  text-align: left;
+}
 </style>

+ 21 - 1
src/views/purchaseManage/purchaseManage/purchaseDocumentary/index.vue

@@ -91,6 +91,17 @@
       </el-card>
     </div>
 
+    <el-row style="padding-top: 20px" justify="end" type="flex">
+      <el-pagination
+        background
+        layout="total, sizes, prev, pager, next, jumper"
+        :current-page="sourceList.pagination.pageNum"
+        :page-size="sourceList.pagination.pageSize"
+        :total="sourceList.pagination.total"
+        @size-change="handleSizeChange"
+        @current-change="handlePageChange" />
+    </el-row>
+
     <el-dialog :title="title" v-if="dialogVisible" v-model="dialogVisible" width="600" v-loading="loadingDialog">
       <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit">
         <template #completionTime>
@@ -213,6 +224,15 @@ const getList = () => {
 };
 getDict();
 getList();
+const handleSizeChange = (val) => {
+  sourceList.value.pagination.pageNum = 1;
+  sourceList.value.pagination.pageSize = val;
+  getList();
+};
+const handlePageChange = (val) => {
+  sourceList.value.pagination.pageSize = val;
+  getList();
+};
 const selectRegion = (item) => {
   sourceList.value.pagination.pageNum = 1;
   if (selectRecordDocumentaryId.value && selectRecordDocumentaryId.value === item.id) {
@@ -392,7 +412,7 @@ const openFile = (path) => {
 }
 .main-content {
   margin-top: 20px;
-  height: calc(100vh - 140px - 232px);
+  height: calc(100vh - 140px - 232px - 52px);
   overflow: auto;
   &::-webkit-scrollbar {
     width: 0px;

+ 21 - 1
src/views/salesMange/saleContract/salesDocumentary/index.vue

@@ -91,6 +91,17 @@
       </el-card>
     </div>
 
+    <el-row style="padding-top: 20px" justify="end" type="flex">
+      <el-pagination
+        background
+        layout="total, sizes, prev, pager, next, jumper"
+        :current-page="sourceList.pagination.pageNum"
+        :page-size="sourceList.pagination.pageSize"
+        :total="sourceList.pagination.total"
+        @size-change="handleSizeChange"
+        @current-change="handlePageChange" />
+    </el-row>
+
     <el-dialog :title="title" v-if="dialogVisible" v-model="dialogVisible" width="600" v-loading="loadingDialog">
       <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit">
         <template #completionTime>
@@ -213,6 +224,15 @@ const getList = () => {
 };
 getDict();
 getList();
+const handleSizeChange = (val) => {
+  sourceList.value.pagination.pageNum = 1;
+  sourceList.value.pagination.pageSize = val;
+  getList();
+};
+const handlePageChange = (val) => {
+  sourceList.value.pagination.pageSize = val;
+  getList();
+};
 const selectRegion = (item) => {
   sourceList.value.pagination.pageNum = 1;
   if (selectRecordDocumentaryId.value && selectRecordDocumentaryId.value === item.id) {
@@ -392,7 +412,7 @@ const openFile = (path) => {
 }
 .main-content {
   margin-top: 20px;
-  height: calc(100vh - 140px - 232px);
+  height: calc(100vh - 140px - 232px - 52px);
   overflow: auto;
   &::-webkit-scrollbar {
     width: 0px;

+ 0 - 0
src/views/systemTenant/tenant/dept/index.vue → src/views/systemTenant/tenant/deptTenant/index.vue


+ 0 - 0
src/views/systemTenant/tenant/dict/dictTenantDtl.vue → src/views/systemTenant/tenant/dictTenant/dictTenantDtl.vue


+ 0 - 0
src/views/systemTenant/tenant/dict/index.vue → src/views/systemTenant/tenant/dictTenant/index.vue


+ 0 - 0
src/views/systemTenant/tenant/role/index.vue → src/views/systemTenant/tenant/roleTenant/index.vue


+ 0 - 0
src/views/systemTenant/tenant/user/index.vue → src/views/systemTenant/tenant/userTenant/index.vue