cz 2 жил өмнө
parent
commit
0b4e5399c9

+ 10 - 5
src/components/byTable/index.vue

@@ -28,7 +28,11 @@
           style="margin-right: 10px"
         >
           <div class="by-dropdown-title">
-            {{ i.label }}<i style="margin-left:5px" class="iconfont icon-iconm_xialan1"></i>
+            {{ i.label
+            }}<i
+              style="margin-left: 5px"
+              class="iconfont icon-iconm_xialan1"
+            ></i>
           </div>
           <ul class="by-dropdown-lists">
             <li
@@ -398,11 +402,13 @@ export default defineComponent({
 
     const isSelectable = (row, index, item) => {
       if (item.type === "selection") {
-        if (row[item.attrs.checkAtt]) {
+        if (item.attrs && item.attrs.checkAtt) {
+          if (row[item.attrs.checkAtt]) {
+            return row[item.attrs.checkAtt];
+          }
+        } else {
           return true;
         }
-      } else {
-        return true;
       }
     };
 
@@ -450,7 +456,6 @@ export default defineComponent({
   margin-bottom: 10px;
 }
 .by-dropdown {
-  
   position: relative;
   text-align: left;
   height: 32px;

+ 11 - 0
src/store/modules/mail.js

@@ -0,0 +1,11 @@
+const useMailStore = defineStore(
+  'mail', {
+    state: () => ({
+      selectMail: {}, //当前选中的邮箱
+      currentMenu: {}, //当前选中的邮箱菜单数据
+      currentId: "", //当前选中的邮箱菜单id
+      mailMenuList: [] //邮箱菜单数据
+    }),
+    actions: {}
+  })
+export default useMailStore

+ 10 - 9
src/views/WDLY/basic/product/index.vue

@@ -374,42 +374,39 @@ const config = computed(() => {
     {
       attrs: {
         label: "管理部门",
-        prop: "spec",
+        prop: "deptName",
       },
     },
     {
       attrs: {
         label: "生命周期",
-        prop: "spec",
+        prop: "lifeCycle",
       },
     },
-
     {
       attrs: {
         label: "京东供价",
-        prop: "spec",
+        prop: "jdPurchasePrice",
       },
     },
     {
       attrs: {
         label: "标准售价",
-        prop: "spec",
+        prop: "sellingPrice",
       },
     },
     {
       attrs: {
         label: "标准采购价",
-        prop: "spec",
+        prop: "purchasePrice",
       },
     },
-
     {
       attrs: {
         label: "产品备注",
         prop: "remark",
       },
     },
-
     {
       attrs: {
         label: "操作",
@@ -619,7 +616,11 @@ const getList = async (req) => {
     .post("/productInfo/page", sourceList.value.pagination)
     .then((message) => {
       console.log(message);
-      sourceList.value.data = message.rows.map((x) => ({ ...x, fileList: [] }));
+      sourceList.value.data = message.rows.map((x) => ({
+        ...x,
+        fileList: [],
+        victoriatouristJson: JSON.parse(x.victoriatouristJson),
+      }));
       sourceList.value.pagination.total = message.total;
       setTimeout(() => {
         loading.value = false;

+ 540 - 0
src/views/WDLY/basic/supplier/index.vue

@@ -0,0 +1,540 @@
+<template>
+  <div class="tenant">
+    <!-- <Banner /> -->
+    <div class="content">
+      <byTable
+        :source="sourceList.data"
+        :pagination="sourceList.pagination"
+        :config="config"
+        :loading="loading"
+        highlight-current-row
+        :selectConfig="selectConfig"
+        :table-events="{
+          //element talbe事件都能传
+          select: select,
+        }"
+        :action-list="[
+          {
+            text: '添加供应商',
+            action: () => openModal('add'),
+          },
+        ]"
+        @get-list="getList"
+      >
+        <template #address="{ item }">
+          <div>
+            {{ item.countryName }}, {{ item.provinceName }} ,
+            {{ item.cityName }}, {{ item.areaDetail }}
+          </div>
+        </template>
+      </byTable>
+    </div>
+    <el-dialog
+      :title="modalType == 'add' ? '添加供应商' : '编辑供应商'"
+      v-model="dialogVisible"
+      width="800"
+      v-loading="loading"
+    >
+      <byForm
+        :formConfig="formConfig"
+        :formOption="formOption"
+        v-model="formData.data"
+        :rules="rules"
+        ref="byform"
+      >
+        <template #address>
+          <el-row :gutter="10" style="width: 100%; margin-left: -15px">
+            <el-col :span="8">
+              <el-form-item prop="countryId">
+                <el-select
+                  v-model="formData.data.countryId"
+                  placeholder="国家"
+                  @change="(val) => getCityData(val, '20', true)"
+                >
+                  <el-option
+                    v-for="item in countryData"
+                    :label="item.chineseName"
+                    :value="item.id"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item prop="provinceId">
+                <el-select
+                  v-model="formData.data.provinceId"
+                  placeholder="省/洲"
+                  @change="(val) => getCityData(val, '30', true)"
+                >
+                  <el-option
+                    v-for="item in provinceData"
+                    :label="item.name"
+                    :value="item.id"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item prop="cityId">
+                <el-select v-model="formData.data.cityId" placeholder="城市">
+                  <el-option
+                    v-for="item in cityData"
+                    :label="item.name"
+                    :value="item.id"
+                  >
+                  </el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row style="margin-top: 20px; width: 100%; margin-left: -10px">
+            <el-col :span="24">
+              <el-form-item prop="areaDetail">
+                <el-input v-model="formData.data.areaDetail" type="textarea">
+                </el-input>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </template>
+
+        <template #contact>
+          <el-row :gutter="10" style="width: 100%; margin-left: -15px">
+            <el-col :span="8">
+              <el-form-item prop="contactPerson">
+                <el-input
+                  v-model="formData.data.contactPerson"
+                  placeholder="联系人"
+                >
+                </el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="16">
+              <el-form-item prop="contactNumber">
+                <el-input
+                  v-model="formData.data.contactNumber"
+                  placeholder="联系电话"
+                  :formatter="(val) => val.replace(/[^\d\-]/g, '')"
+                  :parser="(val) => val.replace(/[^\d\-]/g, '')"
+                >
+                </el-input>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </template>
+
+        <template #fileSlot>
+          <div>
+            <el-upload
+              v-model:fileList="fileList"
+              :show-file-list="false"
+              class="upload-demo"
+              action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
+              :data="uploadData"
+              :on-preview="handlePreview"
+              :on-remove="handleRemove"
+              :on-success="handleSuccess"
+              :before-upload="handleBeforeUpload"
+            >
+              <el-button type="primary">选择</el-button>
+            </el-upload>
+            <div>
+              <div style="margin-top: 15px">
+                <el-tag
+                  style="margin-right: 10px"
+                  class="ml-2"
+                  type="info"
+                  v-for="(item, index) in fileListCopy"
+                  :key="index"
+                  closable
+                  @close="handleClose(index)"
+                  >{{ item.fileName }}</el-tag
+                >
+              </div>
+            </div>
+          </div>
+        </template>
+      </byForm>
+      <template #footer>
+        <el-button @click="dialogVisible = false" size="large">取 消</el-button>
+        <el-button
+          type="primary"
+          @click="submitForm('byform')"
+          size="large"
+          :loading="submitLoading"
+        >
+          确 定
+        </el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+  
+<script setup>
+/* eslint-disable vue/no-unused-components */
+import { ElMessage, ElMessageBox } from "element-plus";
+import byTable from "@/components/byTable/index";
+import byForm from "@/components/byForm/index";
+import FileUpload from "@/components/FileUpload/index";
+import { computed, defineComponent, ref } from "vue";
+import { getToken } from "@/utils/auth";
+
+const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传文件服务器地址
+const headers = ref({ Authorization: "Bearer " + getToken() });
+const uploadData = ref({});
+const loading = ref(false);
+const submitLoading = ref(false);
+const sourceList = ref({
+  data: [],
+  pagination: {
+    total: 3,
+    pageNum: 1,
+    pageSize: 10,
+    type: "",
+    keyword: "",
+  },
+});
+let dialogVisible = ref(false);
+let modalType = ref("add");
+let fileList = ref([]);
+let fileListCopy = ref([]);
+
+const checkContactNumber = (rule, val, callback) => {
+  if (val === "") {
+    callback(new Error("请输入联系电话"));
+  } else {
+    val = "aaa";
+  }
+  console.log(rule, val, callback, "213");
+  // @input="(val) => val.replace(/[^\d]/g, '')"
+};
+let rules = ref({
+  name: [{ required: true, message: "请输入供应商名称", trigger: "blur" }],
+  type: [{ required: true, message: "请选择供应商类型", trigger: "change" }],
+  countryId: [{ required: true, message: "请选择国家", trigger: "change" }],
+  provinceId: [{ required: true, message: "请选择省/洲", trigger: "change" }],
+  cityId: [{ required: true, message: "请选择城市", trigger: "change" }],
+  areaDetail: [{ required: true, message: "请输入详细地址", trigger: "blur" }],
+  contactPerson: [{ required: true, message: "请输入联系人", trigger: "blur" }],
+  // contactNumber: [{ validator: checkContactNumber, trigger: "blur" }],
+  contactNumber: [
+    { required: true, message: "请输入联系电话", trigger: "blur" },
+  ],
+});
+const { proxy } = getCurrentInstance();
+const selectConfig = reactive([
+  {
+    label: "供应商类型",
+    prop: "type",
+    data: [
+      {
+        label: "贸易商",
+        value: "1",
+      },
+      {
+        label: "工厂",
+        value: "2",
+      },
+    ],
+  },
+]);
+const config = computed(() => {
+  return [
+    {
+      attrs: {
+        label: "供应商类型",
+        prop: "type",
+      },
+      render(type) {
+        return type === 1 ? "贸易商" : "工厂";
+      },
+    },
+    {
+      attrs: {
+        label: "供应商编码",
+        prop: "code",
+      },
+    },
+    {
+      attrs: {
+        label: "供应商名称",
+        prop: "name",
+      },
+    },
+    {
+      attrs: {
+        label: "所在城市",
+        prop: "remarks",
+        slot: "address",
+      },
+    },
+    {
+      attrs: {
+        label: "联系人",
+        prop: "contactPerson",
+      },
+    },
+    {
+      attrs: {
+        label: "联系人电话",
+        prop: "contactNumber",
+      },
+    },
+    {
+      attrs: {
+        label: "备注",
+        prop: "remark",
+      },
+    },
+
+    {
+      attrs: {
+        label: "操作",
+        width: "200",
+        align: "right",
+      },
+      // 渲染 el-button,一般用在最后一列。
+      renderHTML(row) {
+        return [
+          {
+            attrs: {
+              label: "修改",
+              type: "primary",
+              text: true,
+            },
+            el: "button",
+            click() {
+              getDtl(row);
+            },
+          },
+          {
+            attrs: {
+              label: "删除",
+              type: "danger",
+              text: true,
+            },
+            el: "button",
+            click() {
+              // 弹窗提示是否删除
+              ElMessageBox.confirm(
+                "此操作将永久删除该数据, 是否继续?",
+                "提示",
+                {
+                  confirmButtonText: "确定",
+                  cancelButtonText: "取消",
+                  type: "warning",
+                }
+              ).then(() => {
+                // 删除
+                proxy
+                  .post("/supplierInfo/delete", {
+                    id: row.id,
+                  })
+                  .then((res) => {
+                    ElMessage({
+                      message: "删除成功",
+                      type: "success",
+                    });
+                    getList();
+                  });
+              });
+            },
+          },
+        ];
+      },
+    },
+  ];
+});
+
+let formData = reactive({
+  data: {
+    type: "1",
+  },
+});
+const formOption = reactive({
+  inline: true,
+  labelWidth: 100,
+  itemWidth: 100,
+  rules: [],
+});
+const byform = ref(null);
+const formConfig = computed(() => {
+  return [
+    {
+      type: "radio",
+      prop: "type",
+      label: "供应商类型",
+      required: true,
+      border: true,
+      data: [
+        { label: "贸易商", value: "1" },
+        { label: "工厂", value: "2" },
+      ],
+    },
+    {
+      type: "input",
+      prop: "name",
+      label: "供应商名称",
+      required: true,
+    },
+    {
+      type: "slot",
+      slotName: "address",
+      prop: "countryId",
+      label: "地址",
+      required: true,
+    },
+    {
+      type: "slot",
+      slotName: "contact",
+      prop: "contactPerson",
+      label: "联系信息",
+      required: true,
+    },
+    {
+      type: "slot",
+      slotName: "fileSlot",
+      label: "上传附件",
+    },
+    {
+      type: "input",
+      label: "备注",
+      prop: "remark",
+      itemType: "textarea",
+    },
+  ];
+});
+const getList = async (req) => {
+  sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
+  loading.value = true;
+  proxy
+    .post("/supplierInfo/page", sourceList.value.pagination)
+    .then((message) => {
+      console.log(message);
+      sourceList.value.data = message.rows;
+      sourceList.value.pagination.total = message.total;
+      setTimeout(() => {
+        loading.value = false;
+      }, 200);
+    });
+};
+const openModal = () => {
+  dialogVisible.value = true;
+  modalType.value = "add";
+  formData.data = {
+    type: "1",
+    countryId: "China",
+  };
+  getCityData(formData.data.countryId, "20");
+};
+
+const submitForm = () => {
+  byform.value.handleSubmit((valid) => {
+    formData.data.fileList =
+      fileListCopy.value.map((x) => ({
+        id: x.id,
+        fileName: x.fileName,
+      })) || [];
+    submitLoading.value = true;
+    proxy.post("/supplierInfo/" + modalType.value, formData.data).then(
+      (res) => {
+        ElMessage({
+          message: modalType.value == "add" ? "添加成功" : "编辑成功",
+          type: "success",
+        });
+        fileList.value = [];
+        dialogVisible.value = false;
+        submitLoading.value = false;
+        getList();
+      },
+      (err) => {
+        submitLoading.value = false;
+      }
+    );
+  });
+};
+
+const getDtl = (row) => {
+  modalType.value = "edit";
+  proxy.post("/supplierInfo/detail", { id: row.id }).then((res) => {
+    proxy
+      .post("/fileInfo/getList", { businessIdList: [row.id] })
+      .then((fileObj) => {
+        fileList.value = fileObj[row.id];
+        fileListCopy.value = [...fileList.value];
+        getCityData(res.countryId, "20");
+        getCityData(res.provinceId, "30");
+        res.type = res.type + "";
+        formData.data = res;
+        dialogVisible.value = true;
+      });
+  });
+};
+
+const handleBeforeUpload = async (file) => {
+  const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
+  uploadData.value = res.uploadBody;
+  fileListCopy.value.push({
+    id: res.id,
+    fileName: res.fileName,
+    path: res.fileUrl,
+    url: res.fileUrl,
+    uid: file.uid,
+  });
+};
+
+const handleClickFile = (row) => {
+  ElMessage({
+    message: "数据请求中,请稍后!",
+    type: "success",
+  });
+  let id = row.id;
+  proxy.post("/fileInfo/getList", { businessIdList: [id] }).then((res) => {
+    const file = res[id][0];
+    window.open(file.fileUrl, "_blank");
+  });
+};
+
+const handleClose = (index) => {
+  if (fileListCopy.value.length === 1) {
+    return ElMessage({
+      message: "最后一个附件啦!",
+      type: "info",
+    });
+  }
+  fileList.value.splice(index, 1);
+  fileListCopy.value.splice(index, 1);
+};
+
+const countryData = ref([]);
+const provinceData = ref([]);
+const cityData = ref([]);
+
+const getCityData = (id, type, isChange) => {
+  proxy.post("/areaInfo/list", { parentId: id }).then((res) => {
+    if (type === "20") {
+      provinceData.value = res;
+      if (isChange) {
+        formData.data.provinceId = "";
+        formData.data.cityId = "";
+      }
+    } else if (type === "30") {
+      cityData.value = res;
+      if (isChange) {
+        formData.data.cityId = "";
+      }
+    } else {
+      countryData.value = res;
+    }
+  });
+};
+getCityData("0");
+getList();
+</script>
+  
+<style lang="scss" scoped>
+.tenant {
+  padding: 20px;
+}
+</style>

+ 297 - 0
src/views/WDLY/outInBound/waitInBound/index.vue

@@ -0,0 +1,297 @@
+<template>
+  <div class="tenant">
+    <!-- <Banner /> -->
+    <div class="content">
+      <byTable
+        :source="sourceList.data"
+        :pagination="sourceList.pagination"
+        :config="config"
+        :loading="loading"
+        highlight-current-row
+        :selectConfig="selectConfig"
+        :table-events="{
+          //element talbe事件都能传
+          select: select,
+        }"
+        :action-list="[]"
+        @get-list="getList"
+      >
+        <template #slotName="{ item }">
+          {{ item.createTime }}
+        </template>
+      </byTable>
+    </div>
+    <el-dialog
+      :title="modalType == 'add' ? '添加仓库' : '编辑'"
+      v-model="dialogVisible"
+      width="800"
+      v-loading="loading"
+    >
+      <byForm
+        :formConfig="formConfig"
+        :formOption="formOption"
+        v-model="formData.data"
+        :rules="rules"
+        ref="byform"
+      >
+      </byForm>
+      <template #footer>
+        <el-button @click="dialogVisible = false" size="large">取 消</el-button>
+        <el-button
+          type="primary"
+          @click="submitForm('byform')"
+          size="large"
+          :loading="submitLoading"
+        >
+          确 定
+        </el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+  
+<script setup>
+/* eslint-disable vue/no-unused-components */
+import { ElMessage, ElMessageBox } from "element-plus";
+import byTable from "@/components/byTable/index";
+import byForm from "@/components/byForm/index";
+import { computed, defineComponent, ref } from "vue";
+import useUserStore from "@/store/modules/user";
+
+const loading = ref(false);
+const submitLoading = ref(false);
+const sourceList = ref({
+  data: [],
+  pagination: {
+    total: 3,
+    pageNum: 1,
+    pageSize: 10,
+  },
+});
+let dialogVisible = ref(false);
+let roomDialogVisible = ref(false);
+let modalType = ref("add");
+let rules = ref({
+  type: [
+    { required: true, message: "请选择仓库类型", trigger: ["blur", "change"] },
+  ],
+  name: [{ required: true, message: "请输入仓库名称", trigger: "blur" }],
+});
+const { proxy } = getCurrentInstance();
+const selectConfig = reactive([
+  {
+    label: "异常来源",
+    prop: "type",
+    data: [],
+  },
+  {
+    label: "处理状态",
+    prop: "type",
+    data: [],
+  },
+]);
+
+const config = computed(() => {
+  return [
+    {
+      attrs: {
+        label: "类型",
+        prop: "name",
+      },
+      render(type) {
+        return proxy.dictDataEcho(type, warehouseType.value);
+      },
+    },
+    {
+      attrs: {
+        label: "仓库名称",
+        prop: "type",
+      },
+    },
+    {
+      attrs: {
+        label: "单号",
+        prop: "name",
+      },
+    },
+    {
+      attrs: {
+        label: "物流/快递公司",
+        prop: "keeperName",
+      },
+    },
+    {
+      attrs: {
+        label: "物流/快递单号",
+        prop: "remark",
+      },
+    },
+    {
+      attrs: {
+        label: "操作人",
+        prop: "remark",
+      },
+    },
+    {
+      attrs: {
+        label: "操作时间",
+        prop: "remark",
+      },
+    },
+    {
+      attrs: {
+        label: "状态",
+        prop: "name",
+      },
+    },
+    {
+      attrs: {
+        label: "操作",
+        width: "100",
+        align: "right",
+      },
+      // 渲染 el-button,一般用在最后一列。
+      renderHTML(row) {
+        return [
+          {
+            attrs: {
+              label: "入库",
+              type: "primary",
+              text: true,
+            },
+            el: "button",
+            click() {
+              getDtl(row);
+            },
+          },
+        ];
+      },
+    },
+  ];
+});
+
+let formData = reactive({
+  data: {},
+  treeData: [],
+});
+const formOption = reactive({
+  inline: true,
+  labelWidth: 100,
+  itemWidth: 100,
+  rules: [],
+});
+const byform = ref(null);
+const treeData = ref([]);
+const formConfig = reactive([
+  {
+    type: "select",
+    prop: "type",
+    label: "仓库类型",
+    required: true,
+    data: [],
+  },
+  {
+    type: "input",
+    prop: "name",
+    label: "仓库名称",
+  },
+  {
+    type: "select",
+    prop: "keeperId",
+    label: "仓管员",
+    isLoad: {
+      url: `/tenantUser/list?pageNum=1&pageSize=9999&tenantId=${
+        useUserStore().user.tenantId
+      }`,
+      labelKey: "nickName",
+      labelVal: "userId",
+      method: "get",
+      resUrl: "rows",
+    },
+  },
+  {
+    type: "input",
+    itemType: "textarea",
+    prop: "remark",
+    label: "备注",
+  },
+]);
+const getList = async (req) => {
+  sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
+  loading.value = true;
+  proxy
+    .post("/abnormalInfo/page", sourceList.value.pagination)
+    .then((message) => {
+      console.log(message);
+      sourceList.value.data = message.rows;
+      sourceList.value.pagination.total = message.total;
+      setTimeout(() => {
+        loading.value = false;
+      }, 200);
+    });
+};
+const openModal = () => {
+  dialogVisible.value = true;
+  modalType.value = "add";
+  formData.data = {};
+};
+
+const submitForm = () => {
+  console.log(byform.value);
+  byform.value.handleSubmit((valid) => {
+    submitLoading.value = true;
+    proxy.post("/warehouse/" + modalType.value, formData.data).then(
+      (res) => {
+        ElMessage({
+          message: modalType.value == "add" ? "添加成功" : "编辑成功",
+          type: "success",
+        });
+        dialogVisible.value = false;
+        submitLoading.value = false;
+        getList();
+      },
+      (err) => (submitLoading.value = false)
+    );
+  });
+};
+
+const getDtl = (row) => {
+  modalType.value = "edit";
+  proxy.post("/warehouse/detail", { id: row.id }).then((res) => {
+    res.type = res.type + "";
+    formData.data = res;
+    console.log(formData);
+    dialogVisible.value = true;
+  });
+};
+const warehouseType = ref([]);
+const getDict = () => {
+  // // 币种数据
+  proxy
+    .post("/dictTenantData/page", {
+      pageNum: 1,
+      pageSize: 999,
+      tenantId: useUserStore().user.tenantId,
+      dictCode: "warehouse_type",
+    })
+    .then((res) => {
+      warehouseType.value = res.rows;
+      selectConfig[0].data = res.rows.map((x) => ({
+        label: x.dictValue,
+        value: x.dictKey,
+      }));
+      formConfig[0].data = res.rows.map((x) => ({
+        label: x.dictValue,
+        value: x.dictKey,
+      }));
+    });
+};
+getList();
+getDict();
+</script>
+  
+<style lang="scss" scoped>
+.tenant {
+  padding: 20px;
+}
+</style>

+ 167 - 0
src/views/connect/E-mail/mail/com/left.vue

@@ -0,0 +1,167 @@
+<template>
+  <div class="left">
+    <div class="top">
+      <el-dropdown>
+        <span class="mail">
+          {{ selectMail.mailUser }}
+          <el-icon class="el-icon--right">
+            <arrow-down />
+          </el-icon>
+        </span>
+        <template #dropdown>
+          <el-dropdown-menu>
+            <el-dropdown-item
+              v-for="item in mailList"
+              :key="item.id"
+              @click="handleClickMail(item)"
+              >{{ item.mailUser }}</el-dropdown-item
+            >
+          </el-dropdown-menu>
+        </template>
+      </el-dropdown>
+      <el-tabs v-model="activeName" class="demo-tabs" stretch>
+        <el-tab-pane label="邮箱" name="first">
+          <template #label>
+            <span>邮箱</span>
+          </template>
+        </el-tab-pane>
+        <el-tab-pane label="联系人" name="second">
+          <template #label>
+            <span>联系人</span>
+          </template>
+        </el-tab-pane>
+        <el-tab-pane label="客户" name="third">
+          <template #label>
+            <span>客户</span>
+          </template>
+        </el-tab-pane>
+      </el-tabs>
+      <div>
+        <el-button type="primary" style="width: 100%" @click="handleGoWrite"
+          >写信</el-button
+        >
+      </div>
+    </div>
+    <div class="body">
+      <div v-if="activeName === 'first'">
+        <ul class="mail-menu">
+          <li
+            class="menu-item"
+            v-bind:class="{ 'select-menu': item.id === selectFloderId }"
+            v-for="item in selectMail.mailFolderInfoList"
+            :key="item.id"
+            @click="handleOpenMenu(item)"
+          >
+            {{ item.name }}
+          </li>
+        </ul>
+      </div>
+      <div v-if="activeName === 'second'">b</div>
+      <div v-if="activeName === 'third'">c</div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import useMailStore from "@/store/modules/mail";
+const mailStore = useMailStore();
+const { proxy } = getCurrentInstance();
+let selectMail = ref({});
+let activeName = ref("first");
+let selectFloderId = ref("");
+const mailList = ref([]);
+const getMialList = () => {
+  proxy.get("/mailService/getUserEmailList").then((res) => {
+    mailList.value = res.data;
+    if (mailList.value.length) {
+      selectMail.value = mailList.value[0];
+      mailStore.selectMail = mailList.value[0];
+      if (selectMail.value.mailFolderInfoList.length > 0) {
+        handleOpenMenu(selectMail.value.mailFolderInfoList[0]);
+      }
+    }
+  });
+};
+
+const handleClickMail = (item) => {
+  selectMail.value = item;
+  mailStore.selectMail = item;
+};
+
+const handleOpenMenu = (item) => {
+  selectFloderId.value = item.id;
+  const menu = {
+    title: item.name,
+    type: selectMail.value.type,
+    folderId: item.id,
+    id: "floder" + "," + item.id,
+  };
+  const menuItem = mailStore.mailMenuList.find((x) => x.id === menu.id);
+  if (menuItem === undefined) {
+    mailStore.mailMenuList.push(menu);
+  }
+  mailStore.currentMenu = menu;
+  mailStore.currentId = menu.id;
+};
+
+const handleGoWrite = () => {
+  const menu = {
+    title: "写信",
+    type: selectMail.value.type,
+    id: "write",
+  };
+  const menuItem = mailStore.mailMenuList.find((x) => x.id === menu.id);
+  if (menuItem === undefined) {
+    mailStore.mailMenuList.push(menu);
+  }
+  mailStore.currentMenu = menu;
+  mailStore.currentId = menu.id;
+};
+
+onMounted(() => {
+  getMialList();
+});
+</script>
+
+<style lang="scss" scoped>
+.left {
+  font-size: 14px;
+  .top {
+    padding: 10px;
+    text-align: center;
+    border-bottom: 1px solid #ddd;
+    .mail {
+      color: black;
+      font-weight: 700;
+      font-size: 14px;
+    }
+  }
+  .body {
+    padding: 10px;
+    .mail-menu {
+      list-style: none;
+      margin-block-start: 0;
+      margin-block-end: 0;
+      padding: 0px;
+      .menu-item {
+        font-weight: 700;
+        padding-left: 10px;
+        font-size: 12px;
+        width: 100%;
+        height: 40px;
+        line-height: 40px;
+        border-radius: 3px;
+        color: #696969;
+        cursor: pointer;
+        &:hover {
+          background: #ddedfe;
+        }
+      }
+    }
+  }
+}
+.select-menu {
+  background: #ddedfe;
+  color: #169bd5 !important;
+}
+</style>

+ 149 - 0
src/views/connect/E-mail/mail/com/mailDetail.vue

@@ -0,0 +1,149 @@
+<template>
+  <div v-loading="loading" class="box">
+    <div class="top">
+      <div class="top-row">
+        <div class="label">发 件 人:</div>
+        <div class="value">
+          <span
+            v-for="item in replyTo"
+            :key="item.id"
+            style="margin-right: 10px"
+          >
+            {{ item.personalName }}</span
+          >
+        </div>
+      </div>
+      <div class="top-row">
+        <div class="label">收 件 人:</div>
+        <div class="value">
+          <span v-for="item in to" :key="item.id" style="margin-right: 10px">{{
+            item.personalName
+          }}</span>
+        </div>
+      </div>
+      <div class="top-row" v-if="cc.length > 0">
+        <div class="label">抄 送 人:</div>
+        <div class="value">
+          <span v-for="item in cc" :key="item.id" style="margin-right: 10px">
+            {{ item.personalName }}</span
+          >
+        </div>
+      </div>
+      <div class="top-row" v-if="bcc.length > 0">
+        <div class="label">密 送 人:</div>
+        <div class="value">
+          <span v-for="item in bcc" :key="item.id" style="margin-right: 10px">
+            {{ item.personalName }}</span
+          >
+        </div>
+      </div>
+      <div class="top-row">
+        <div class="label">时 间:</div>
+        <div class="value">{{ time }}</div>
+      </div>
+    </div>
+    <div class="body">
+      <iframe
+        frameborder="0"
+        allowTransparency="true"
+        style="
+          width: 99% !important;
+          overflow-x: scroll;
+          padding-top: 10px;
+          height: 600px;
+        "
+        :srcdoc="showBodyText(detailsData.data.content)"
+        :ref="'iframeText_' + mailStore.currentId"
+        :id="'iframeText_' + mailStore.currentId"
+      >
+      </iframe>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import byTable from "@/components/byTable/index";
+import useMailStore from "@/store/modules/mail";
+const { proxy } = getCurrentInstance();
+const mailStore = useMailStore();
+let loading = ref(false);
+const detailsData = reactive({
+  data: {},
+});
+const to = ref([]);
+const cc = ref([]);
+const bcc = ref([]);
+const replyTo = ref([]);
+const requestData = ref({});
+const getDetails = () => {
+  loading.value = true;
+  proxy
+    .post("/mailService/getMessageDetail", {
+      ...mailStore.currentMenu,
+    })
+    .then((res) => {
+      detailsData.data = res;
+      to.value = res.messageAddressList.filter((x) => x.type === 1);
+      cc.value = res.messageAddressList.filter((x) => x.type === 2);
+      bcc.value = res.messageAddressList.filter((x) => x.type === 3);
+      replyTo.value = res.messageAddressList.filter((x) => x.type === 4);
+      loading.value = false;
+    });
+};
+
+const showBodyText = (text) => {
+  if (text) {
+    let val = JSON.parse(JSON.stringify(text));
+    val = val.replace("body {", "tbody {");
+    val = val.replace(
+      "td, p, li, th {",
+      "tbody td, tbody p, tbody li, tbody th {"
+    );
+    val = val.replace(
+      /<p>/g,
+      '<p style="margin-block-start: 0; margin-block-end: 0;">'
+    );
+    return val;
+  } else {
+    return text;
+  }
+};
+
+const init = () => {
+  getDetails();
+};
+
+onMounted(() => {
+  // init();
+});
+
+defineExpose({
+  initFn: init,
+});
+</script>
+
+<style lang="scss" scoped>
+.box {
+  padding: 0 10px;
+  font-size: 12px;
+  .top {
+    padding: 10px;
+    background: #f1f1f1;
+    .top-row {
+      display: flex;
+      margin-bottom: 10px;
+      .label {
+        min-width: 60px;
+        color: #999999;
+        text-align: right;
+      }
+      .value {
+        flex: 1;
+        color: #333333;
+        font-weight: 700;
+        margin-right: 10px;
+      }
+    }
+  }
+}
+</style>

+ 121 - 0
src/views/connect/E-mail/mail/com/mailList.vue

@@ -0,0 +1,121 @@
+<template>
+  <div>
+    <div style="padding-left: 20px">
+      <el-icon @click="handleRefresh" style="cursor: pointer">
+        <Refresh />
+      </el-icon>
+    </div>
+    <byTable
+      :source="tableData.data"
+      :pagination="tableData.pagination"
+      :config="config"
+      :loading="loading"
+      :hideSearch="true"
+      highlight-current-row
+      :action-list="[]"
+      :table-events="{
+        //element talbe事件都能传
+        'row-click': handleRowClick,
+      }"
+      @get-list="getList"
+    >
+    </byTable>
+  </div>
+</template>
+
+<script setup>
+import byTable from "@/components/byTable/index";
+import useMailStore from "@/store/modules/mail";
+const { proxy } = getCurrentInstance();
+const mailStore = useMailStore();
+let loading = ref(false);
+const tableData = reactive({
+  data: [],
+  pagination: {
+    pageNum: 1,
+    pageSize: 10,
+    total: 0,
+  },
+});
+const config = computed(() => {
+  return [
+    {
+      attrs: {
+        label: "发件人",
+        prop: "fromPersonalName",
+      },
+    },
+    {
+      attrs: {
+        label: "发件人地址",
+        prop: "fromEmail",
+      },
+    },
+    {
+      attrs: {
+        label: "主题",
+        prop: "subject",
+      },
+    },
+    {
+      attrs: {
+        label: "时间",
+        prop: "sendDate",
+      },
+    },
+  ];
+});
+
+const getList = (req = {}) => {
+  tableData.pagination = { ...tableData.pagination, ...req };
+  loading.value = true;
+  proxy
+    .post("/mailService/getMessagePage", {
+      ...mailStore.currentMenu,
+      ...tableData.pagination,
+      ...req,
+    })
+    .then((res) => {
+      tableData.data = res.rows;
+      tableData.pagination.total = res.total;
+      loading.value = false;
+    });
+};
+
+const handleRefresh = () => {
+  tableData.pagination = {
+    pageNum: 1,
+    pageSize: 10,
+  };
+  getList();
+};
+
+const handleRowClick = (row) => {
+  const menu = {
+    title: row.subject.slice(0, 4) + "...",
+    type: mailStore.selectMail.type,
+    messageId: row.id,
+    id: "detail" + "," + row.id,
+  };
+  const menuItem = mailStore.mailMenuList.find((x) => x.id === menu.id);
+  if (menuItem === undefined) {
+    mailStore.mailMenuList.push(menu);
+  }
+  mailStore.currentMenu = menu;
+  mailStore.currentId = menu.id;
+};
+onMounted(() => {
+  // getList();
+});
+
+const init = () => {
+  getList();
+};
+
+defineExpose({
+  initFn: init,
+});
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 78 - 0
src/views/connect/E-mail/mail/com/mailWrite.vue

@@ -0,0 +1,78 @@
+<template>
+  <div v-loading="loading" style="padding: 10px">
+    <div style="margin-bottom: 10px; padding-left: 65px">
+      <el-button type="primary" @click="handleSend">发送</el-button>
+    </div>
+    <div style="width: 70%">
+      <byForm
+        :formConfig="formConfig"
+        :formOption="formOption"
+        v-model="formData.data"
+        :rules="rules"
+        ref="submit"
+      >
+        <template #contentSlot> 内容插槽 </template>
+      </byForm>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import byForm from "@/components/byForm/index";
+import { ElMessage, ElMessageBox } from "element-plus";
+let loading = ref(false);
+const formOption = reactive({
+  inline: true,
+  labelWidth: 65,
+  itemWidth: 100,
+  labelPosition: "left",
+});
+const formConfig = computed(() => {
+  return [
+    {
+      type: "input",
+      prop: "aa",
+      label: "收件人",
+      required: true,
+      itemWidth: 100,
+      itemType: "text",
+    },
+    {
+      type: "input",
+      prop: "bb",
+      label: "主题",
+      required: true,
+      itemWidth: 100,
+      itemType: "text",
+    },
+    {
+      type: "slot",
+      slotName: "contentSlot",
+      label: " ",
+    },
+    {
+      type: "input",
+      prop: "cc",
+      label: "发件人",
+      required: true,
+      itemWidth: 100,
+      itemType: "text",
+    },
+  ];
+});
+const rules = ref({
+  aa: [{ required: true, message: "请输入收件人", trigger: "blur" }],
+  bb: [{ required: true, message: "请输入主题", trigger: "blur" }],
+  cc: [{ required: true, message: "请输入发件人", trigger: "blur" }],
+});
+const formData = reactive({
+  data: {},
+});
+const submit = ref(null);
+const handleSend = () => {
+  submit.value.handleSubmit(() => {});
+};
+</script>
+
+<style lang="scss" scoped>
+</style>

+ 120 - 0
src/views/connect/E-mail/mail/com/main.vue

@@ -0,0 +1,120 @@
+<template>
+  <div class="container">
+    <el-tabs
+      v-model="activeMenu"
+      closable
+      :stretch="false"
+      type="card"
+      @tab-remove="handleTabRemove"
+      @tab-change="handleTabChange"
+    >
+      <el-tab-pane
+        v-for="(item, index) in menuList"
+        :key="index"
+        :label="item.title"
+        :name="item.id"
+      >
+        <div class="main">
+          <mailList
+            v-if="item.id.includes('floder')"
+            :ref="'floder' + index"
+          ></mailList>
+          <mailDetail
+            v-if="item.id.includes('detail')"
+            :ref="'detail' + index"
+          ></mailDetail>
+          <mailWrite v-if="item.id.includes('write')"></mailWrite>
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script setup>
+import mailList from "./mailList.vue";
+import mailDetail from "./mailDetail.vue";
+import mailWrite from "./mailWrite.vue";
+
+import useMailStore from "@/store/modules/mail";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { nextTick } from "vue";
+
+const mailStore = useMailStore();
+const { proxy } = getCurrentInstance();
+const menuList = ref([]);
+let activeMenu = ref("");
+
+mailStore.$subscribe((mutations, state) => {
+  activeMenu.value = state.currentId;
+  menuList.value = state.mailMenuList;
+  // 判断是文件夹还是邮件详情
+  const currentMenu = state.currentMenu;
+  let type = "";
+  if (currentMenu.id.includes("floder")) {
+    type = "floder";
+  } else if (currentMenu.id.includes("detail")) {
+    type = "detail";
+  } else {
+    type = "write";
+  }
+  checkType(currentMenu, type);
+});
+
+const handleTabRemove = (id) => {
+  const clickIndex = menuList.value.findIndex((x) => x.id === id);
+  let currentMenu = {};
+  if (menuList.value.length > 1) {
+    // 如果删除的是当前菜单
+    if (activeMenu.value === id) {
+      if (menuList.value.length > clickIndex + 1) {
+        currentMenu = menuList.value[clickIndex + 1];
+      } else {
+        currentMenu = menuList.value[clickIndex - 1];
+      }
+      // 更新store值
+      mailStore.currentMenu = currentMenu;
+      mailStore.currentId = currentMenu.id;
+    }
+    menuList.value.splice(clickIndex, 1);
+  } else {
+    return ElMessage({
+      message: "最后一个标签页啦!",
+      type: "info",
+    });
+  }
+};
+
+const checkType = (menu, type) => {
+  if (type == "write") return;
+  const index = menuList.value.findIndex((x) => x.id === activeMenu.value);
+  const dom = type + index.toString();
+  nextTick(() => {
+    console.log(dom, "wss");
+    proxy.$refs[dom][0].initFn();
+  });
+};
+
+// const handleTabChange = () => {
+//   // 判断是文件夹还是邮件详情
+//   let type = "";
+//   if (activeMenu.value.id.includes("floder")) {
+//     type = "floder";
+//   } else if (activeMenu.value.id.includes("detail")) {
+//     type = "detail";
+//   } else {
+//     type = "write";
+//   }
+//   checkType(currentMenu, type);
+// };
+
+onMounted(() => {});
+</script>
+
+<style lang="scss" scoped>
+.container {
+  .main {
+    height: calc(100vh - 180px);
+    overflow: auto;
+  }
+}
+</style>

+ 34 - 0
src/views/connect/E-mail/mail/index.vue

@@ -0,0 +1,34 @@
+<template>
+  <div class="box">
+    <div class="left">
+      <mailLeft></mailLeft>
+    </div>
+    <div class="right">
+      <mailMain></mailMain>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import mailLeft from "./com/left.vue";
+import mailMain from "./com/main.vue";
+</script>
+
+<style lang="scss" scoped>
+.box {
+  height: calc(100vh - 50px - 50px);
+  padding: 10px;
+  display: flex;
+  .left,
+  .right {
+    background: #fff;
+  }
+  .left {
+    width: 300px;
+    margin-right: 10px;
+  }
+  .right {
+    flex: 1;
+  }
+}
+</style>

+ 20 - 31
src/views/process/processApproval/index.vue

@@ -5,21 +5,21 @@
         <div class="commons-title title">流程标题</div>
         <SendSubscribe
           ref="makeDom"
-          v-if="queryData.data.isSubscribe == '10'"
+          v-if="flowForm.flowKey == 'subscribe_flow'"
         ></SendSubscribe>
         <SendPurchase
           ref="makeDom"
-          v-else-if="queryData.data.isSubscribe == '20'"
+          v-else-if="flowForm.flowKey == 'purchase_flow'"
           :queryData="queryData.data"
         ></SendPurchase>
         <SendFunds
           ref="makeDom"
-          v-else-if="queryData.data.isSubscribe == '30'"
+          v-else-if="flowForm.flowKey == '30'"
           :queryData="queryData.data"
         ></SendFunds>
         <ReturnGood
           ref="makeDom"
-          v-else-if="queryData.data.isSubscribe == '40'"
+          v-else-if="flowForm.flowKey == '40'"
           :queryData="queryData.data"
         ></ReturnGood>
       </div>
@@ -226,7 +226,7 @@ const handleSelectUser = () => {
 };
 
 const handleResult = (res) => {
-  if (res !== null && res.success === 1) {
+  if (res !== null && res.success) {
     skipPage();
   } else {
     dialogVisible.value = true;
@@ -242,16 +242,13 @@ const handleSubmit = async () => {
       flowFormDom.value.validate((vaild) => {
         if (vaild) {
           const data = { ...makeDom.value.submitData };
-          if (queryData.data.isSubscribe == "10") {
+          if (flowForm.flowKey == "subscribe_flow") {
             data.subscribeDetailList = data.subscribeDetailList.map((x) => ({
               bussinessId: x.bussinessId,
               count: x.count,
               remark: x.remark,
             }));
-            proxy.post("/subscribe/add", data).then((res) => {
-              handleResult(res);
-            });
-          } else if (queryData.data.isSubscribe == "20") {
+          } else if (flowForm.flowKey == "purchase_flow") {
             data.purchaseDetailList = data.purchaseDetailList.map((x) => ({
               bussinessId: x.bussinessId,
               subscribeDetailId: x.id,
@@ -259,26 +256,17 @@ const handleSubmit = async () => {
               price: x.price,
               amount: x.amount,
             }));
-            proxy.post("/purchase/add", data).then((res) => {
-              handleResult(res);
-            });
-          } else if (queryData.data.isSubscribe == "30") {
-            proxy
-              .post("/flowProcess/initiate", {
-                ...flowForm,
-                flowKey: "account_request_funds_flow",
-                data,
-              })
-              .then((res) => {
-                console.log(res, "awss");
-                handleResult(res);
-              });
-          } else if (queryData.data.isSubscribe == "40") {
-            console.log(data, "wssaa");
-            proxy.post("/flowProcess/initiate", data).then((res) => {
+          } else if (flowForm.flowKey == "30") {
+          } else if (flowForm.flowKey == "40") {
+          }
+          proxy
+            .post("/flowProcess/initiate", {
+              ...flowForm,
+              data,
+            })
+            .then((res) => {
               handleResult(res);
             });
-          }
         }
       });
     }
@@ -292,15 +280,15 @@ const skipPage = () => {
     message: "操作成功!",
     type: "success",
   });
-  if (queryData.data.isSubscribe == "10") {
+  if (flowForm.flowKey == "subscribe_flow") {
     router.replace({
       path: "/purchaseManage/purchaseManage/subscribe",
     });
-  } else if (queryData.data.isSubscribe == "20") {
+  } else if (flowForm.flowKey == "purchase_flow") {
     router.replace({
       path: "/purchaseManage/purchaseManage/purchase",
     });
-  } else if (queryData.data.isSubscribe == "30") {
+  } else if (flowForm.flowKey == "30") {
     router.replace({
       path: "/finance/fundManage/funds",
     });
@@ -313,6 +301,7 @@ let queryData = reactive({
 
 onMounted(() => {
   queryData.data = { ...route.query };
+  flowForm.flowKey = route.query.flowKey;
 });
 </script>
 

+ 3 - 3
src/views/purchaseManage/purchaseManage/purchase/index.vue

@@ -156,7 +156,7 @@ const sourceList = ref({
     total: 3,
     pageNum: 1,
     pageSize: 10,
-    status: "15,30",
+    status: "15",
   },
 });
 let dialogVisible = ref(false);
@@ -169,7 +169,7 @@ const { proxy } = getCurrentInstance();
 const selectConfig = reactive([
   {
     label: "状态",
-    prop: "type",
+    prop: "status",
     data: [
       {
         label: "待采购",
@@ -445,7 +445,7 @@ const start = () => {
     proxy.$router.replace({
       path: "/platform_manage/process/processApproval",
       query: {
-        isSubscribe: "20",
+        flowKey: "purchase_flow",
         ids,
       },
     });

+ 1 - 1
src/views/purchaseManage/purchaseManage/subscribe/index.vue

@@ -399,7 +399,7 @@ const openModal = () => {
   proxy.$router.replace({
     path: "/platform_manage/process/processApproval",
     query: {
-      isSubscribe: "10",
+      flowKey: "subscribe_flow",
     },
   });
 };