xiaodai2017 2 년 전
부모
커밋
5b731ff844
31개의 변경된 파일1469개의 추가작업 그리고 1193개의 파일을 삭제
  1. 24 3
      src/api/system/updates.ts
  2. 1 1
      src/components/PageContent/src/actions/action-status.tsx
  3. 4 0
      src/config/status.ts
  4. 0 1
      src/style/index.scss
  5. 165 0
      src/views/parameter/card/components/edit-dialog.vue
  6. 2 17
      src/views/parameter/card/config/content.config.ts
  7. 0 20
      src/views/parameter/card/config/modal.config.ts
  8. 34 35
      src/views/parameter/card/index.vue
  9. 198 0
      src/views/parameter/company/components/edit-dialog.vue
  10. 3 18
      src/views/parameter/company/config/content.config.ts
  11. 0 43
      src/views/parameter/company/config/modal.config.ts
  12. 35 35
      src/views/parameter/company/index.vue
  13. 389 0
      src/views/parameter/good/components/edit-dialog.vue
  14. 16 10
      src/views/parameter/good/components/ladder-modal.vue
  15. 0 0
      src/views/parameter/good/components/ladder-table.vue
  16. 0 526
      src/views/parameter/good/config/_details.ts
  17. 0 112
      src/views/parameter/good/config/_rules.ts
  18. 2 18
      src/views/parameter/good/config/content.config.ts
  19. 0 45
      src/views/parameter/good/config/modal.config.ts
  20. 32 144
      src/views/parameter/good/index.vue
  21. 212 0
      src/views/parameter/video/components/edit-dialog.vue
  22. 7 17
      src/views/parameter/video/config/content.config.ts
  23. 0 46
      src/views/parameter/video/config/modal.config.ts
  24. 32 54
      src/views/parameter/video/index.vue
  25. 10 4
      src/views/system/logistics/index.vue
  26. 1 2
      src/views/system/menuOperator/components/edit-dialog.vue
  27. 5 3
      src/views/system/setBtn/components/edit-dialog.vue
  28. 234 0
      src/views/system/updates/components/edit-dialog.vue
  29. 16 24
      src/views/system/updates/config/content.config.ts
  30. 7 0
      src/views/system/updates/config/search.config.ts
  31. 40 15
      src/views/system/updates/index.vue

+ 24 - 3
src/api/system/updates.ts

@@ -3,9 +3,30 @@ import { http } from "/@/utils/http";
 
 const { VITE_PROXY_DOMAIN_REAL } = loadEnv();
 
-//获取所有menu
-export async function httpList(): Promise<DataType<any>> {
+//获取版本数据
+export async function httpList(data: object): Promise<DataType<any>> {
   return http.request(`post`, `${VITE_PROXY_DOMAIN_REAL}admin/versionlist`, {
-    data: {}
+    data
   });
 }
+
+//新增
+export async function httpAdd(data: object): Promise<DataType<any>> {
+  return http.request(
+    `post`,
+    `${VITE_PROXY_DOMAIN_REAL}admin//admin/versionAdd`,
+    {
+      data
+    }
+  );
+}
+//获取版本数据
+export async function httpUpdate(data: object): Promise<DataType<any>> {
+  return http.request(
+    `post`,
+    `${VITE_PROXY_DOMAIN_REAL}admin//admin/versionAdd`,
+    {
+      data
+    }
+  );
+}

+ 1 - 1
src/components/PageContent/src/actions/action-status.tsx

@@ -50,7 +50,7 @@ const ActionStatus = defineComponent({
               size="small"
               type="primary"
               icon={useRenderIcon(
-                props.row.status === "1"
+                props.row.status + "" === "1"
                   ? "close-circle-line"
                   : "checkbox-circle-line"
               )}

+ 4 - 0
src/config/status.ts

@@ -84,3 +84,7 @@ export const FLAG_OPTIONS = [
   { id: "1", label: "增加", value: "1", type: "warning" },
   { id: "-1", label: "减少", value: "-1", type: "primary" }
 ];
+export const SYS_TYPE_OPTIONS = [
+  { id: "MSG", label: "公告", value: "MSG", type: "warning" },
+  { id: "VER", label: "版本", value: "VER", type: "primary" }
+];

+ 0 - 1
src/style/index.scss

@@ -55,6 +55,5 @@
 
 .el-form>.el-form-item.asterisk-left {
   margin:0 0 0 0!important;
-
 }
   

+ 165 - 0
src/views/parameter/card/components/edit-dialog.vue

@@ -0,0 +1,165 @@
+<script setup lang="ts">
+import { FormRules, ElForm } from "element-plus";
+import { reactive, ref } from "vue";
+import { httpUpdate, httpAdd, httpDetail } from "/@/api/parameter/card";
+import { responseHandle } from "/@/utils/responseHandle";
+import { useNav } from "/@/layout/hooks/useNav";
+
+enum FROM_TYPE {
+  create = "create",
+  edit = "edit",
+  view = "view"
+}
+const { logout } = useNav();
+const showModel = ref(false);
+const TYPE = ref<FROM_TYPE>(FROM_TYPE.create);
+const formRef = ref<InstanceType<typeof ElForm>>(null);
+const loading = ref(false);
+const titleType = ref("");
+const id = ref("");
+const emit = defineEmits(["reload"]);
+const initform = {
+  title: "",
+  id: ""
+};
+const ruleForm = ref({ ...initform });
+const rules = reactive<FormRules>({
+  title: [{ required: true, trigger: "bulr", message: "请输入卡类型" }]
+});
+const initData = async () => {
+  const { code, data, message } = await httpDetail({ id: id.value });
+  responseHandle({
+    code,
+    message,
+    logout,
+    handler: () => {
+      console.log(data);
+      Object.keys(ruleForm.value).forEach(key => {
+        ruleForm.value[key] = data[key] ? data[key] + "" : "";
+      });
+    }
+  });
+};
+async function show(node: any, did: string, isCreate: string) {
+  id.value = did;
+  Object.keys(ruleForm.value).forEach(key => {
+    ruleForm.value[key] = initform[key] ? initform[key] + "" : "";
+  });
+  TYPE.value = isCreate;
+  switch (TYPE.value) {
+    case "create":
+      titleType.value = "新建卡类型";
+      break;
+    case "edit":
+      titleType.value = "编辑卡类型";
+      break;
+    case "view":
+      titleType.value = "卡类型详情";
+      break;
+    default:
+      titleType.value = "新建卡类型";
+  }
+  if (TYPE.value !== "create") {
+    await initData();
+  }
+
+  showModel.value = true;
+}
+
+function handleUpdate() {
+  const data = {
+    ...ruleForm.value
+  };
+
+  return {
+    data,
+    api: httpUpdate
+  };
+}
+
+function handleCreate() {
+  const data = {
+    ...ruleForm.value
+  };
+
+  return {
+    data,
+    api: httpAdd
+  };
+}
+
+function handleSave() {
+  formRef.value.validate(async vaild => {
+    if (vaild) {
+      if (loading.value) return;
+      const handler =
+        TYPE.value === FROM_TYPE.create ? handleCreate : handleUpdate;
+
+      loading.value = true;
+      const { api, data } = handler();
+      const { message, code } = await api(data);
+      loading.value = false;
+      responseHandle({
+        code,
+        message,
+        logout,
+        handler: () => {
+          showModel.value = false;
+
+          emit("reload");
+        }
+      });
+    }
+  });
+}
+
+defineExpose({
+  show
+});
+</script>
+
+<template>
+  <el-dialog
+    v-model="showModel"
+    :close-on-press-escape="false"
+    center
+    append-to-body
+    destroy-on-close
+    :width="'400px'"
+    :title="titleType"
+    v-loading="loading"
+  >
+    <el-form
+      ref="formRef"
+      :model="ruleForm"
+      :rules="rules"
+      label-width="70px"
+      style="margin-top: -10px"
+      class="demo-ruleForm"
+      status-icon
+    >
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="卡类型" prop="title">
+            <ElInput
+              placeholder="卡类型"
+              :disabled="TYPE === 'view'"
+              maxlength="50"
+              v-model="ruleForm.title"
+            /> </el-form-item
+        ></el-col>
+      </el-row>
+      <div class="flex justify-end">
+        <el-button
+          v-if="TYPE !== 'view'"
+          :loading="loading"
+          :disabled="loading"
+          type="primary"
+          @click="handleSave"
+          >保存</el-button
+        >
+        <el-button @click="showModel = false">取消</el-button>
+      </div>
+    </el-form>
+  </el-dialog>
+</template>

+ 2 - 17
src/views/parameter/card/config/content.config.ts

@@ -1,21 +1,9 @@
 import { ContentConfig } from "/@/components/PageContent";
-import {
-  httpList,
-  httpAdd,
-  httpUpdate,
-  httpStatus,
-  httpDelete
-} from "/@/api/parameter/card";
+import { httpList, httpStatus, httpDelete } from "/@/api/parameter/card";
 import { renderStatus } from "/@/utils/column-helper";
 import { STATUS_OPTIONS } from "/@/config/status";
 
 const columns = [
-  {
-    type: "selection",
-    width: 55,
-    hide: ({ checkList }) => !checkList.includes("勾选列")
-  },
-
   {
     prop: "id",
     label: "ID"
@@ -36,8 +24,7 @@ const columns = [
   },
   {
     prop: "addtime",
-    label: "创建时间",
-    sortable: true
+    label: "创建时间"
   },
 
   {
@@ -52,9 +39,7 @@ const contentConfig: ContentConfig = {
   title: "卡类型管理",
   columns,
   apis: {
-    httpAdd,
     httpList,
-    httpUpdate,
     httpStatus,
     httpDelete
   }

+ 0 - 20
src/views/parameter/card/config/modal.config.ts

@@ -1,20 +0,0 @@
-import { ModalConfig } from "/@/components/PageModal/src/types";
-const modalConfig: ModalConfig = {
-  title: "卡类型",
-  width: "500px",
-  colLayout: { span: 24 },
-  itemStyle: {},
-  contact: "card",
-  labelWidth: "100px",
-  formItems: [
-    {
-      field: "title",
-      type: "input",
-      label: "卡类型",
-      placeholder: "卡类型",
-      rules: [{ required: true, trigger: "change", message: "请输入卡类型" }]
-    }
-  ]
-};
-
-export default modalConfig;

+ 34 - 35
src/views/parameter/card/index.vue

@@ -1,50 +1,49 @@
 <script setup lang="ts">
-import { ref, watch, watchEffect } from "vue";
 import { PageSearch, usePageSearch } from "/@/components/PageSearch";
 import searchConfig from "./config/search.config";
 import contentConfig from "./config/content.config";
-import modalConfig from "./config/modal.config";
-import { PageModal, usePageModal } from "/@/components/PageModal";
+import { usePermission } from "/@/hooks/usePermission";
 import { PageContent } from "/@/components/PageContent";
-
-import type { PageContentInstance } from "/@/components/PageContent";
+import { ref } from "vue";
+import EditModel from "./components/edit-dialog.vue";
 const { pageContentRef, handleResetClick, handleSearchClick } = usePageSearch(
   undefined,
   undefined,
   searchConfig
 );
 const pageName = "card";
-const {
-  pageModalRef,
-  handleUpdateData,
-  handleCreateData,
-  handlePreviewData,
-  handleConfrim,
-  defaultInfo
-} = usePageModal({
-  pageContentRef
-});
+const modelRef = ref<InstanceType<typeof EditModel>>(null);
+const { hasPermissionWithCode, permissions } = usePermission(pageName);
+
+function handleAddChangeCheck(item: any, id: string, type: string) {
+  modelRef.value.show(item, id, type);
+}
 </script>
 
 <template>
-  <!-- <PageAuth :pageName="pageName"> -->
-  <PageSearch
-    :form-config="searchConfig"
-    @search-btn-click="handleSearchClick"
-    @reset-btn-click="handleResetClick"
-  />
-  <PageContent
-    ref="pageContentRef"
-    :content-config="contentConfig"
-    @create-btn-click="handleCreateData"
-    @preview-btn-click="row => handlePreviewData(row)"
-    @update-btn-click="row => handleUpdateData(row)"
-  />
-  <PageModal
-    ref="pageModalRef"
-    :modal-config="modalConfig"
-    :default-info="defaultInfo"
-    @confirm-btn-click="handleConfrim"
-  />
-  <!-- </PageAuth> -->
+  <PageAuth :pageName="pageName">
+    <PageSearch
+      :form-config="searchConfig"
+      @search-btn-click="handleSearchClick"
+      @reset-btn-click="handleResetClick"
+    >
+      <template #action>
+        <el-button
+          type="primary"
+          @click="handleAddChangeCheck({}, '', 'create')"
+          v-if="hasPermissionWithCode('002')"
+        >
+          新增
+        </el-button>
+      </template>
+    </PageSearch>
+    <PageContent
+      ref="pageContentRef"
+      :powers="permissions"
+      :content-config="contentConfig"
+      @preview-btn-click="row => handleAddChangeCheck(row, row.id, 'view')"
+      @update-btn-click="row => handleAddChangeCheck(row, row.id, 'edit')"
+    />
+    <EditModel ref="modelRef" @reload="pageContentRef.onSearch()" />
+  </PageAuth>
 </template>

+ 198 - 0
src/views/parameter/company/components/edit-dialog.vue

@@ -0,0 +1,198 @@
+<script setup lang="ts">
+import { FormRules, ElForm } from "element-plus";
+import { reactive, ref } from "vue";
+import { httpUpdate, httpAdd, httpDetail } from "/@/api/parameter/company";
+import { responseHandle } from "/@/utils/responseHandle";
+import { useNav } from "/@/layout/hooks/useNav";
+
+enum FROM_TYPE {
+  create = "create",
+  edit = "edit",
+  view = "view"
+}
+const { logout } = useNav();
+const showModel = ref(false);
+const TYPE = ref<FROM_TYPE>(FROM_TYPE.create);
+const formRef = ref<InstanceType<typeof ElForm>>(null);
+const loading = ref(false);
+const titleType = ref("");
+const id = ref("");
+const emit = defineEmits(["reload"]);
+const initform = {
+  title: "",
+  contacts: "",
+  id: "",
+  mobile: "",
+  remark: ""
+};
+const ruleForm = ref({ ...initform });
+const rules = reactive<FormRules>({
+  title: [{ required: true, trigger: "bulr", message: "请输入企业" }],
+  contacts: [{ required: true, trigger: "bulr", message: "请输入联系人" }],
+  mobile: [{ required: true, trigger: "blur", message: "请输入联系方式" }],
+  remark: [{ required: false, trigger: "blur", message: "请输入备注" }]
+});
+const initData = async () => {
+  const { code, data, message } = await httpDetail({ id: id.value });
+  responseHandle({
+    code,
+    message,
+    logout,
+    handler: () => {
+      console.log(data);
+      Object.keys(ruleForm.value).forEach(key => {
+        ruleForm.value[key] = data[key] ? data[key] + "" : "";
+      });
+    }
+  });
+};
+async function show(node: any, did: string, isCreate: string) {
+  id.value = did;
+  Object.keys(ruleForm.value).forEach(key => {
+    ruleForm.value[key] = initform[key] ? initform[key] + "" : "";
+  });
+  TYPE.value = isCreate;
+  switch (TYPE.value) {
+    case "create":
+      titleType.value = "新建企业";
+      break;
+    case "edit":
+      titleType.value = "编辑企业";
+      break;
+    case "view":
+      titleType.value = "企业详情";
+      break;
+    default:
+      titleType.value = "新建企业";
+  }
+  if (TYPE.value !== "create") {
+    await initData();
+  }
+
+  showModel.value = true;
+}
+
+function handleUpdate() {
+  const data = {
+    ...ruleForm.value
+  };
+
+  return {
+    data,
+    api: httpUpdate
+  };
+}
+
+function handleCreate() {
+  const data = {
+    ...ruleForm.value
+  };
+
+  return {
+    data,
+    api: httpAdd
+  };
+}
+
+function handleSave() {
+  formRef.value.validate(async vaild => {
+    if (vaild) {
+      if (loading.value) return;
+      const handler =
+        TYPE.value === FROM_TYPE.create ? handleCreate : handleUpdate;
+
+      loading.value = true;
+      const { api, data } = handler();
+      const { message, code } = await api(data);
+      loading.value = false;
+      responseHandle({
+        code,
+        message,
+        logout,
+        handler: () => {
+          showModel.value = false;
+          emit("reload");
+        }
+      });
+    }
+  });
+}
+
+defineExpose({
+  show
+});
+</script>
+
+<template>
+  <el-dialog
+    v-model="showModel"
+    :close-on-press-escape="false"
+    center
+    append-to-body
+    destroy-on-close
+    :width="'900px'"
+    :title="titleType"
+    v-loading="loading"
+  >
+    <el-form
+      ref="formRef"
+      :model="ruleForm"
+      :rules="rules"
+      label-width="90px"
+      style="margin-top: -10px"
+      class="demo-ruleForm"
+      status-icon
+    >
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="企业名称" prop="title">
+            <ElInput
+              placeholder="企业名称"
+              :disabled="TYPE === 'view'"
+              maxlength="50"
+              v-model="ruleForm.title"
+            /> </el-form-item
+        ></el-col>
+        <el-col :span="12">
+          <el-form-item label="联系人" prop="contacts">
+            <ElInput
+              placeholder="联系人"
+              :disabled="TYPE === 'view'"
+              maxlength="50"
+              v-model="ruleForm.contacts"
+            /> </el-form-item
+        ></el-col>
+        <el-col :span="12">
+          <el-form-item label="联系方式" prop="mobile">
+            <ElInput
+              placeholder="联系方式"
+              :disabled="TYPE === 'view'"
+              maxlength="50"
+              v-model="ruleForm.mobile"
+            /> </el-form-item
+        ></el-col>
+        <el-col :span="24">
+          <el-form-item label="备注" prop="remark">
+            <ElInput
+              placeholder="备注"
+              :disabled="TYPE === 'view'"
+              maxlength="500"
+              type="textarea"
+              v-model="ruleForm.remark"
+            /> </el-form-item
+        ></el-col>
+      </el-row>
+      <div class="flex justify-end">
+        <el-button
+          v-if="TYPE !== 'view'"
+          :loading="loading"
+          :disabled="loading"
+          type="primary"
+          @click="handleSave"
+          >保存</el-button
+        >
+        <el-button @click="showModel = false">取消</el-button>
+      </div>
+    </el-form>
+  </el-dialog>
+</template>

+ 3 - 18
src/views/parameter/company/config/content.config.ts

@@ -1,28 +1,16 @@
 import { ContentConfig } from "/@/components/PageContent";
-import {
-  httpList,
-  httpAdd,
-  httpUpdate,
-  httpStatus,
-  httpDelete
-} from "/@/api/parameter/company";
+import { httpList, httpStatus, httpDelete } from "/@/api/parameter/company";
 import { renderStatus } from "/@/utils/column-helper";
 import { STATUS_OPTIONS } from "/@/config/status";
 
 const columns = [
-  {
-    type: "selection",
-    width: 55,
-    hide: ({ checkList }) => !checkList.includes("勾选列")
-  },
-
   {
     prop: "id",
     label: "ID"
   },
   {
     prop: "title",
-    label: "卡类型"
+    label: "公司名称"
   },
 
   {
@@ -40,8 +28,7 @@ const columns = [
   },
   {
     prop: "addtime",
-    label: "创建时间",
-    sortable: true
+    label: "创建时间"
   },
 
   {
@@ -56,9 +43,7 @@ const contentConfig: ContentConfig = {
   title: "企业管理",
   columns,
   apis: {
-    httpAdd,
     httpList,
-    httpUpdate,
     httpStatus,
     httpDelete
   }

+ 0 - 43
src/views/parameter/company/config/modal.config.ts

@@ -1,43 +0,0 @@
-import { ModalConfig } from "/@/components/PageModal/src/types";
-const modalConfig: ModalConfig = {
-  title: "企业",
-  colLayout: { span: 24 },
-  itemStyle: {},
-  width: "900px",
-  contact: "company",
-  labelWidth: "100px",
-  formItems: [
-    {
-      field: "title",
-      type: "input",
-      label: "企业名称",
-      placeholder: "企业名称",
-      rules: [{ required: true, trigger: "blur", message: "请输入企业名称" }]
-    },
-    {
-      field: "contacts",
-      type: "input",
-      label: "联系人",
-      placeholder: "联系人",
-      span: 12,
-      rules: [{ required: true, trigger: "blur", message: "请输入联系人" }]
-    },
-    {
-      field: "mobile",
-      type: "input",
-      label: "联系方式",
-      placeholder: "联系方式",
-      span: 12,
-      rules: [{ required: true, trigger: "blur", message: "请输入联系方式" }]
-    },
-    {
-      field: "remark",
-      type: "textarea",
-      label: "备注",
-      placeholder: "备注",
-      rules: [{ required: false, trigger: "blur", message: "请输入备注" }]
-    }
-  ]
-};
-
-export default modalConfig;

+ 35 - 35
src/views/parameter/company/index.vue

@@ -1,49 +1,49 @@
 <script setup lang="ts">
-import { ref } from "vue";
 import { PageSearch, usePageSearch } from "/@/components/PageSearch";
 import searchConfig from "./config/search.config";
 import contentConfig from "./config/content.config";
-import modalConfig from "./config/modal.config";
-import { PageModal, usePageModal } from "/@/components/PageModal";
+import { usePermission } from "/@/hooks/usePermission";
 import { PageContent } from "/@/components/PageContent";
-
+import { ref } from "vue";
+import EditModel from "./components/edit-dialog.vue";
 const { pageContentRef, handleResetClick, handleSearchClick } = usePageSearch(
   undefined,
   undefined,
   searchConfig
 );
-const pageName = "company";
-const {
-  pageModalRef,
-  handleUpdateData,
-  handleCreateData,
-  handlePreviewData,
-  handleConfrim,
-  defaultInfo
-} = usePageModal({
-  pageContentRef
-});
+const pageName = "card";
+const modelRef = ref<InstanceType<typeof EditModel>>(null);
+const { hasPermissionWithCode, permissions } = usePermission(pageName);
+
+function handleAddChangeCheck(item: any, id: string, type: string) {
+  modelRef.value.show(item, id, type);
+}
 </script>
 
 <template>
-  <!-- <PageAuth :pageName="pageName"> -->
-  <PageSearch
-    :form-config="searchConfig"
-    @search-btn-click="handleSearchClick"
-    @reset-btn-click="handleResetClick"
-  />
-  <PageContent
-    ref="pageContentRef"
-    :content-config="contentConfig"
-    @create-btn-click="handleCreateData"
-    @preview-btn-click="row => handlePreviewData(row)"
-    @update-btn-click="row => handleUpdateData(row)"
-  />
-  <PageModal
-    ref="pageModalRef"
-    :modal-config="modalConfig"
-    :default-info="defaultInfo"
-    @confirm-btn-click="handleConfrim"
-  />
-  <!-- </PageAuth> -->
+  <PageAuth :pageName="pageName">
+    <PageSearch
+      :form-config="searchConfig"
+      @search-btn-click="handleSearchClick"
+      @reset-btn-click="handleResetClick"
+    >
+      <template #action>
+        <el-button
+          type="primary"
+          @click="handleAddChangeCheck({}, '', 'create')"
+          v-if="hasPermissionWithCode('002')"
+        >
+          新增
+        </el-button>
+      </template>
+    </PageSearch>
+    <PageContent
+      ref="pageContentRef"
+      :powers="permissions"
+      :content-config="contentConfig"
+      @preview-btn-click="row => handleAddChangeCheck(row, row.id, 'view')"
+      @update-btn-click="row => handleAddChangeCheck(row, row.id, 'edit')"
+    />
+    <EditModel ref="modelRef" @reload="pageContentRef.onSearch()" />
+  </PageAuth>
 </template>

+ 389 - 0
src/views/parameter/good/components/edit-dialog.vue

@@ -0,0 +1,389 @@
+<script setup lang="ts">
+import { FormRules, ElForm } from "element-plus";
+import { reactive, ref, unref } from "vue";
+import { httpUpdate, httpAdd, httpDetail } from "/@/api/parameter/good";
+import { responseHandle } from "/@/utils/responseHandle";
+import { useNav } from "/@/layout/hooks/useNav";
+import { GOOD_OPTIONS } from "/@/config/status";
+import { ImageUpload } from "/@/components/Upload";
+import { Unit } from "/@/components/RemoteSelect";
+import { ImageUploadList } from "/@/components/UploadList";
+import LadderModal from "./ladder-modal.vue";
+import LadderTable from "./ladder-table.vue";
+const ladderModalRef = ref<InstanceType<typeof LadderModal>>(null);
+enum FROM_TYPE {
+  create = "create",
+  edit = "edit",
+  view = "view"
+}
+const { logout } = useNav();
+const showModel = ref(false);
+const TYPE = ref<FROM_TYPE>(FROM_TYPE.create);
+const formRef = ref<InstanceType<typeof ElForm>>(null);
+const loading = ref(false);
+const titleType = ref("");
+const id = ref("");
+const emit = defineEmits(["reload"]);
+const initform = {
+  id: "",
+  good_name: "",
+  good_cover_img: "",
+  type: "",
+  unit_id: "",
+  moq: 1,
+  step: 1,
+  price: 0,
+  good_banner_img: [],
+  good_img: [],
+  good_param: [],
+  good_remark: ""
+};
+const ruleForm = ref({ ...initform });
+const rules = reactive<FormRules>({
+  good_name: [{ required: true, trigger: "bulr", message: "请输入商品名称" }],
+  good_cover_img: [
+    { required: true, trigger: "change", message: "请选择封面图" }
+  ],
+  type: [{ required: true, trigger: "change", message: "请选择商品类型" }],
+  unit_id: [{ required: true, trigger: "change", message: "请选择单位" }],
+  moq: [{ required: true, trigger: "bulr", message: "请选择起订量" }],
+  step: [{ required: true, trigger: "bulr", message: "请选择步长" }],
+  price: [{ required: true, trigger: "bulr", message: "请选择售价" }],
+  good_banner_img: [
+    {
+      type: "array",
+      required: true,
+      trigger: "change",
+      message: "请上传轮播图"
+    },
+    {
+      type: "array",
+      min: 3,
+      max: 10,
+      trigger: "change",
+      message: "轮播图应为3~10张"
+    }
+  ],
+  good_img: [
+    {
+      type: "array",
+      required: true,
+      trigger: "change",
+      message: "请上传详情图"
+    },
+    {
+      type: "array",
+      min: 1,
+      max: 20,
+      trigger: "change",
+      message: "详情图不得超过20张!"
+    }
+  ],
+  good_param: [
+    {
+      type: "array",
+      required: true,
+      trigger: "change",
+      message: "请填写商品参数!"
+    },
+    {
+      type: "array",
+      min: 1,
+      max: 20,
+      trigger: "change",
+      message: "商品参数应为1~20条!"
+    }
+  ],
+  good_remark: [{ required: true, trigger: "bulr", message: "请输入备注" }]
+});
+const initData = async () => {
+  const { code, data, message } = await httpDetail({ id: id.value });
+  responseHandle({
+    code,
+    message,
+    logout,
+    handler: () => {
+      console.log(data);
+      Object.keys(ruleForm.value).forEach(key => {
+        if (
+          key === "good_banner_img" ||
+          key === "good_img" ||
+          key === "good_param"
+        ) {
+          ruleForm.value[key] = data[key];
+        } else if (key === "moq" || key === "step" || key === "price") {
+          ruleForm.value[key] = Number(data[key]);
+        } else {
+          ruleForm.value[key] = data[key] + "";
+        }
+      });
+    }
+  });
+};
+async function show(node: any, did: string, isCreate: string) {
+  id.value = did;
+  Object.keys(ruleForm.value).forEach(key => {
+    if (
+      key === "good_banner_img" ||
+      key === "good_img" ||
+      key === "good_param"
+    ) {
+      ruleForm.value[key] = [];
+    } else if (key === "moq" || key === "step" || key === "price") {
+      ruleForm.value[key] = initform[key];
+    } else {
+      ruleForm.value[key] = initform[key] + "";
+    }
+  });
+  TYPE.value = isCreate;
+  switch (TYPE.value) {
+    case "create":
+      titleType.value = "新建商品";
+      break;
+    case "edit":
+      titleType.value = "编辑商品";
+      break;
+    case "view":
+      titleType.value = "商品详情";
+      break;
+    default:
+      titleType.value = "新建商品";
+  }
+  if (TYPE.value !== "create") {
+    await initData();
+  }
+  showModel.value = true;
+}
+async function handleLadderUpdate(_ladder, index) {
+  ruleForm.value.good_param[index] = _ladder;
+}
+async function handleLadderPush(_ladder) {
+  ruleForm.value.good_param.push(unref(_ladder));
+}
+function handleUpdate() {
+  const data = {
+    ...ruleForm.value
+  };
+
+  return {
+    data,
+    api: httpUpdate
+  };
+}
+
+function handleCreate() {
+  const data = {
+    ...ruleForm.value
+  };
+
+  return {
+    data,
+    api: httpAdd
+  };
+}
+
+function handleSave() {
+  formRef.value.validate(async vaild => {
+    if (vaild) {
+      if (loading.value) return;
+      const handler =
+        TYPE.value === FROM_TYPE.create ? handleCreate : handleUpdate;
+      loading.value = true;
+      const { api, data } = handler();
+      const { message, code } = await api(data);
+      loading.value = false;
+      responseHandle({
+        code,
+        message,
+        logout,
+        handler: () => {
+          showModel.value = false;
+
+          emit("reload");
+        }
+      });
+    }
+  });
+}
+
+defineExpose({
+  show
+});
+</script>
+
+<template>
+  <el-dialog
+    v-model="showModel"
+    :close-on-press-escape="false"
+    center
+    append-to-body
+    destroy-on-close
+    :width="'1040px'"
+    :title="titleType"
+    v-loading="loading"
+  >
+    <el-form
+      ref="formRef"
+      :model="ruleForm"
+      :rules="rules"
+      label-width="90px"
+      style="margin-top: -10px"
+      class="demo-ruleForm"
+      status-icon
+    >
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="商品名称" prop="good_name">
+            <ElInput
+              placeholder="商品名称"
+              :disabled="TYPE === 'view'"
+              maxlength="50"
+              v-model="ruleForm.good_name"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="封面图" prop="good_cover_img">
+            <ImageUpload
+              v-model:url="ruleForm.good_cover_img"
+              :disabled="TYPE === 'view'"
+              :descs="['小于1Mb']"
+              :types="['png', 'jpg', 'jpeg']"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="商品类型" prop="type">
+            <el-select
+              v-model="ruleForm.type"
+              style="width: 100%"
+              :disabled="TYPE === 'view'"
+              placeholder="商品类型"
+            >
+              <el-option
+                v-for="(si, sii) in GOOD_OPTIONS"
+                :key="'type' + si.id + sii"
+                :label="si.label"
+                :value="si.id + ''"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="单位" prop="unit_id">
+            <Unit
+              v-model="ruleForm.unit_id"
+              :disabled="TYPE === 'view'"
+              placeholder="单位"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="起订量" prop="moq">
+            <el-input-number
+              style="width: 100%"
+              :disabled="TYPE === 'view'"
+              :precision="0"
+              :step="1"
+              controls-position="right"
+              v-model="ruleForm.moq"
+              :min="1"
+              placeholder="起订量"
+              :max="99999999"
+              clearable
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="步长" prop="step">
+            <el-input-number
+              style="width: 100%"
+              :disabled="TYPE === 'view'"
+              :precision="0"
+              :step="1"
+              controls-position="right"
+              v-model="ruleForm.step"
+              :min="1"
+              placeholder="步长"
+              :max="99999999"
+              clearable
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="售价" prop="price">
+            <el-input-number
+              style="width: 100%"
+              :disabled="TYPE === 'view'"
+              :precision="2"
+              :step="1"
+              controls-position="right"
+              v-model="ruleForm.price"
+              :min="0"
+              placeholder="售价"
+              :max="99999999"
+              clearable
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+          <el-form-item label="轮播图" prop="good_banner_img">
+            <ImageUploadList
+              v-model:urls="ruleForm.good_banner_img"
+              :descs="['小于1Mb']"
+              :disabled="TYPE === 'view'"
+              :types="['png', 'jpg', 'jpeg']"
+            /> </el-form-item
+        ></el-col>
+        <el-col :span="24">
+          <el-form-item label="详情图" prop="good_img">
+            <ImageUploadList
+              v-model:urls="ruleForm.good_img"
+              :descs="['小于1Mb']"
+              :disabled="TYPE === 'view'"
+              :types="['png', 'jpg', 'jpeg']"
+            /> </el-form-item
+        ></el-col>
+        <el-col :span="24">
+          <el-form-item label="商品参数" prop="good_param">
+            <LadderTable
+              :readonly="TYPE === 'view'"
+              :ladder="ruleForm.good_param"
+              @choose="() => ladderModalRef.onDisplay()"
+              @update="
+                ({ data, index }) => ladderModalRef.onDisplay(data, index)
+              "
+              @delete="index => ruleForm.good_param.splice(index, 1)"
+            /> </el-form-item
+        ></el-col>
+        <el-col :span="24">
+          <el-form-item label="商品备注" prop="good_remark">
+            <ElInput
+              placeholder="商品备注"
+              :disabled="TYPE === 'view'"
+              type="textarea"
+              maxlength="600"
+              clearable
+              v-model="ruleForm.good_remark"
+            /> </el-form-item
+        ></el-col>
+      </el-row>
+      <div class="flex justify-end">
+        <el-button
+          v-if="TYPE !== 'view'"
+          :loading="loading"
+          :disabled="loading"
+          type="primary"
+          @click="handleSave"
+          >保存</el-button
+        >
+        <el-button @click="showModel = false">取消</el-button>
+      </div>
+    </el-form>
+  </el-dialog>
+  <LadderModal
+    ref="ladderModalRef"
+    @update="handleLadderUpdate"
+    @push="handleLadderPush"
+  />
+</template>

+ 16 - 10
src/views/parameter/good/cpns/ladder-modal.vue → src/views/parameter/good/components/ladder-modal.vue

@@ -1,12 +1,7 @@
 <script setup lang="ts">
 import { ref, unref, computed } from "vue";
 import { ElForm } from "element-plus";
-import { goodTypeOptions } from "../config/_options";
-import { ladderFormRules } from "../config/_rules";
-import { ImageUpload } from "/@/components/Upload";
-
-import { AmountInput, NumberInput } from "/@/components/Input";
-import GoodClass from "/@/components/GoodClass";
+import { FormRules } from "element-plus";
 
 const emit = defineEmits(["push", "update"]);
 
@@ -17,7 +12,18 @@ const defaultData = {
   cat_info: [],
   num: "0"
 };
-
+const ladderFormRules: FormRules = {
+  key: {
+    trigger: "change",
+    required: true,
+    message: "请选择商品类型"
+  },
+  value: {
+    trigger: "change",
+    required: true,
+    message: "请选择单位"
+  }
+};
 const isUpdate = ref(false);
 const visible = ref(false);
 const formRef = ref<InstanceType<typeof ElForm> | null>(null);
@@ -62,14 +68,14 @@ defineExpose({
     center
     :title="title"
     v-model="visible"
+    :width="'500px'"
     @close="() => (formData = { ...defaultData })"
   >
     <ElForm
       ref="formRef"
       :model="formData"
       :rules="ladderFormRules"
-      label-width="100px"
-      size="small"
+      label-width="70px"
     >
       <ElFormItem label="类型" prop="key">
         <ElInput v-model="formData.key" placeholder="类型" />
@@ -79,7 +85,7 @@ defineExpose({
         <ElInput placeholder="类型值" v-model="formData.value" />
       </ElFormItem>
 
-      <ElFormItem>
+      <ElFormItem style="margin: 20px 0 0 0">
         <div class="w-full flex justify-end">
           <ElButton type="primary" @click="handleConfirm">保存</ElButton>
           <ElButton @click="() => (visible = false)">取消</ElButton>

+ 0 - 0
src/views/parameter/good/cpns/ladder-table.vue → src/views/parameter/good/components/ladder-table.vue


+ 0 - 526
src/views/parameter/good/config/_details.ts

@@ -1,526 +0,0 @@
-/* eslint-disable prettier/prettier */
-import { h } from "vue";
-import { ElImage, ElTag } from "element-plus";
-import { DescriptionColumns } from "/@/components/BasicDescriptions";
-import { FormConfig } from "/@/components/PageSearch";
-import { createTooltip } from "/@/utils/tooltip";
-import { GOOD_OPTIONS } from "/@/config/status";
-// import { payWayOptions, sendWayOptions, supplyAreaOptions } from "./_options";
-
-export const projectFormConfig: FormConfig = {
-  labelWidth: "100px",
-  formItems: [
-    {
-      label: "商品名称",
-      field: "good_name",
-      type: "input",
-      placeholder: "商品名称",
-      span: 24
-    },
-    {
-      label: "封面图",
-      field: "good_cover_img",
-      type: "img_upload",
-      placeholder: "封面图",
-      span: 8
-    },
-    {
-      label: "商品类型",
-      field: "type",
-      type: "select",
-      options: GOOD_OPTIONS,
-      placeholder: "商品类型",
-      span: 8
-    },
-    {
-      label: "单位",
-      field: "unit_id",
-      placeholder: "单位",
-      span: 8,
-      slot: "unit_id"
-    },
-
-    {
-      label: "起订量",
-      field: "moq",
-      type: "number",
-      placeholder: "起订量",
-      otherOptions: {
-        precision: 0,
-        step: 1,
-        "controls-position": "right",
-        min: 0,
-        max: 99999999
-      },
-      span: 8
-    },
-    {
-      label: "步长",
-      field: "step",
-      type: "number",
-      placeholder: "步长",
-      span: 8,
-      otherOptions: {
-        precision: 0,
-        step: 1,
-        "controls-position": "right",
-        min: 0,
-        max: 99999999
-      }
-    },
-    {
-      label: "售价",
-      field: "price",
-      type: "number",
-      placeholder: "售价",
-      span: 8,
-      otherOptions: {
-        precision: 2,
-        step: 1,
-        "controls-position": "right",
-        min: 0,
-        max: 99999999
-      }
-    },
-    {
-      label: "轮播图",
-      type: "img_upload_list",
-      field: "good_banner_img",
-      placeholder: "轮播图",
-      span: 24
-    },
-    {
-      label: "详情图",
-      field: "good_img",
-      type: "img_upload_list",
-      placeholder: "详情图",
-      span: 24
-    },
-    {
-      label: "商品参数",
-      type: "array",
-      field: "good_param",
-      placeholder: "商品参数",
-      slot: "good_param",
-      span: 24
-    },
-
-    {
-      label: "备注",
-      field: "good_remark",
-      type: "textarea",
-      placeholder: "备注",
-      span: 24
-    }
-  ]
-};
-
-//平台商品详情字段
-export const platformGoodColumns: DescriptionColumns = [
-  {
-    field: "good_name",
-    label: "商品名称",
-    span: 24,
-    render: (goodname, { skuCode, speclist }) => {
-      const goodName = speclist
-        ? speclist
-            .map(({ spec_name, spec_value }) => `${spec_name}[${spec_value}]`)
-            .join("_")
-        : "";
-
-      return createTooltip(
-        goodname + "_" + goodName,
-        "商品编号: " + skuCode,
-        360
-      );
-    }
-  },
-  {
-    field: "good_img",
-    label: "商品主图",
-    span: 12,
-    render: good_img => {
-      const previewSrcList = good_img ? good_img.split(",") : [];
-      return previewSrcList.map(src =>
-        h(ElImage, {
-          previewSrcList: [src],
-          src,
-          previewTeleported: true,
-          style: {
-            height: "20px",
-            width: "20px"
-          }
-        })
-      );
-    }
-  },
-  {
-    field: "good_info_img",
-    label: "商品详情图",
-    span: 12,
-    render: good_info_img => {
-      return h(ElImage, {
-        previewSrcList: [good_info_img],
-        src: good_info_img,
-        previewTeleported: true,
-        style: {
-          height: "20px",
-          width: "20px"
-        }
-      });
-    }
-  },
-  {
-    field: "company",
-    label: "业务企业名称",
-    span: 8,
-    render: (company, { companyNo }) =>
-      createTooltip(company, "业务企业编号: " + companyNo, 360)
-  },
-  {
-    field: "platform_name",
-    label: "所属平台",
-    span: 8
-  },
-  {
-    field: "brand_name",
-    label: "品牌",
-    span: 8
-  },
-  {
-    field: "cat_info",
-    label: "分类",
-    span: 8,
-    render(cat_info) {
-      return cat_info ? cat_info.map(({ name }) => name).join("_") : "";
-    }
-  },
-  {
-    field: "unit",
-    span: 8,
-    label: "单位"
-  },
-  {
-    field: "is_stock",
-    label: "是否库存品",
-    span: 6,
-    render(is_stock) {
-      return h(ElTag, null, {
-        default: () => (is_stock !== "0" ? "库存品" : "非库存品")
-      });
-    }
-  },
-  // {
-  //   field: "supply_area",
-  //   label: "供货区域",
-  //   span: 6,
-  //   render(supply_area) {
-  //     return h(ElTag, null, {
-  //       default: () =>
-  //         supplyAreaOptions.find(({ id }) => supply_area === id)?.label || "--"
-  //     });
-  //   }
-  // },
-  {
-    field: "good_type",
-    label: "是否定制",
-    span: 8,
-    render(good_type) {
-      return h(ElTag, null, {
-        default: () => (good_type !== "0" ? "是" : "否")
-      });
-    }
-  },
-  {
-    field: "tax",
-    label: "税点",
-    append: "%",
-    span: 4
-  },
-  {
-    field: "delivery_day",
-    label: "物流时间",
-    append: "天",
-    span: 4
-  },
-  {
-    field: "lead_time",
-    label: "供货周期",
-    append: "天",
-    span: 4
-  },
-  {
-    field: "sample_day",
-    label: "调样周期",
-    append: "天",
-    span: 4
-  },
-  {
-    field: "exclusive",
-    label: "专属类型",
-    span: 6,
-    render(exclusive) {
-      return exclusive ? exclusive.map(({ name }) => name).join("/") : "";
-    }
-  },
-  {
-    field: "weight",
-    label: "商品总克重",
-    append: "g",
-    span: 6
-  },
-  {
-    field: "noble",
-    label: "贵金属信息",
-    render(
-      _,
-      {
-        noble_weight,
-        noble_metal,
-        noble_name,
-        gold_price,
-        is_gold_price,
-        is_diff,
-        config,
-        other_config
-      }
-    ) {
-      if (!noble_metal) {
-        return "";
-      }
-
-      const weight = noble_weight ? `${noble_weight}g-${noble_name}` : "";
-
-      const price = gold_price ? gold_price : "0";
-
-      const isGoldPrice = is_gold_price === "0" ? "不" : "";
-
-      const diff = is_diff === "1" ? "有" : "无";
-
-      return `${weight}${price}元/g-${isGoldPrice}启用实时金价-${diff}工差-${config}-${other_config}`;
-    }
-  },
-  {
-    field: "delivery_place_cn",
-    label: "发货地",
-    span: 8
-  },
-  {
-    field: "customized",
-    label: "工期",
-    span: 8
-  },
-  {
-    field: "cgder",
-    label: "供应商负责人",
-    span: 4
-  },
-  {
-    field: "good_creater",
-    label: "商品创建人",
-    span: 4
-  },
-  {
-    field: "after_sales",
-    label: "售后说明",
-    span: 24
-  },
-  {
-    field: "good_remark",
-    label: "商品备注",
-    span: 24
-  },
-
-  {
-    field: "craft_desc",
-    label: "工艺说明",
-    span: 24
-  }
-];
-
-//采反商品详情字段
-export const commodityFeedbackColumns: DescriptionColumns = [
-  {
-    field: "good_name",
-    label: "商品名称",
-    span: 24,
-    render: (goodname, { spuCode, speclist }) => {
-      const goodName = speclist
-        ? speclist
-            .map(({ spec_name, spec_value }) => `${spec_name}[${spec_value}]`)
-            .join("_")
-        : "";
-
-      return createTooltip(
-        goodname + "_" + goodName,
-        "上线商品编号: " + spuCode,
-        360
-      );
-    }
-  },
-
-  {
-    field: "cat_info",
-    label: "分类",
-    span: 8,
-    render(cat_info) {
-      return cat_info ? cat_info.map(({ name }) => name).join("_") : "";
-    }
-  },
-
-  {
-    field: "brand_name",
-    label: "品牌",
-    span: 8
-  },
-
-  // {
-  //   field: "send_way",
-  //   label: "发货方式",
-  //   span: 8,
-  //   render(send_way) {
-  //     return h(ElTag, null, {
-  //       default: () =>
-  //         sendWayOptions.find(({ id }) => send_way === id)?.label || "--"
-  //     });
-  //   }
-  // },
-  {
-    field: "unit",
-    label: "单位",
-    span: 4
-  },
-  {
-    field: "tax",
-    label: "税点",
-    append: "%",
-    span: 4
-  },
-  // {
-  //   field: "pay_way",
-  //   label: "付款方式",
-  //   span: 4,
-  //   render(pay_way) {
-  //     return h(ElTag, null, {
-  //       default: () =>
-  //         payWayOptions.find(({ id }) => pay_way === id)?.label || "--"
-  //     });
-  //   }
-  // },
-
-  {
-    field: "weight",
-    label: "商品总克重",
-    append: "g",
-    span: 6
-  },
-
-  {
-    field: "addtime",
-    label: "反馈时间",
-    span: 6
-  },
-  {
-    field: "expire_day",
-    label: "竞价有效期",
-    append: "天",
-    span: 4
-  },
-
-  {
-    field: "delivery_day",
-    label: "物流时间",
-    append: "天",
-    span: 4
-  },
-  {
-    field: "work_day",
-    label: "生产工期",
-    append: "天",
-    span: 4
-  },
-  {
-    field: "cgder",
-    label: "供应商负责人",
-    span: 4
-  },
-  {
-    field: "creater",
-    label: "商品创建人",
-    span: 4
-  },
-  {
-    field: "supply_area",
-    label: "供货区域",
-    span: 4,
-    render(supply_area) {
-      return h(ElTag, null, {
-        default: () =>
-          supplyAreaOptions.find(({ id }) => supply_area === id)?.label || "--"
-      });
-    }
-  },
-
-  {
-    field: "good_img",
-    label: "商品图片",
-    span: 24,
-    render: good_img => {
-      const previewSrcList = good_img ? good_img.split(",") : [];
-      return previewSrcList.map(src =>
-        h(ElImage, {
-          previewSrcList: [src],
-          src,
-          previewTeleported: true,
-          style: {
-            height: "20px",
-            width: "20px"
-          }
-        })
-      );
-    }
-  },
-  {
-    field: "noble",
-    label: "贵金属信息",
-    span: 24,
-    render(
-      _,
-      {
-        noble_weight,
-        noble_metal,
-        noble_name,
-        gold_price,
-        is_gold_price,
-        is_diff,
-        config,
-        other_config
-      }
-    ) {
-      if (!noble_metal) {
-        return "--";
-      }
-
-      const weight = noble_weight ? `${noble_weight}g-${noble_name}` : "";
-
-      const price = gold_price ? gold_price : "0";
-
-      const isGoldPrice = is_gold_price === "0" ? "不" : "";
-
-      const diff = is_diff === "1" ? "有" : "无";
-
-      return `${weight}${price}元/g-${isGoldPrice}启用实时金价-${diff}工差-${config}-${other_config}`;
-    }
-  },
-
-  {
-    field: "cost_desc",
-    label: "工艺说明",
-    span: 24
-  },
-  {
-    field: "remark",
-    label: "采返备注",
-    span: 24
-  }
-];

+ 0 - 112
src/views/parameter/good/config/_rules.ts

@@ -1,112 +0,0 @@
-import { FormRules } from "element-plus";
-
-export const ladderFormRules: FormRules = {
-  key: {
-    trigger: "change",
-    required: true,
-    message: "请选择商品类型"
-  },
-  value: {
-    trigger: "change",
-    required: true,
-    message: "请选择单位"
-  }
-};
-
-export const projectFormRules: FormRules = {
-  good_name: {
-    trigger: "change",
-    required: true,
-    validator(_, value) {
-      if (value === "") return new Error("请输入商品名称");
-      return true;
-    }
-  },
-  good_cover_img: {
-    trigger: "change",
-    required: true,
-    message: "请上传封面图",
-    validator(_, value) {
-      if (value === "") return new Error("请上传封面图");
-      return true;
-    }
-  },
-  type: {
-    trigger: "change",
-    required: true,
-    message: "请选择商品类型"
-  },
-  unit_id: {
-    trigger: "change",
-    required: true,
-    message: "请选择单位"
-  },
-  price: {
-    trigger: "change",
-    required: true,
-    validator(_, value) {
-      // console.log(typeof value + "--售价--" + value);
-
-      if (value === "") return new Error("请输入售价");
-      return true;
-    }
-  },
-  moq: {
-    trigger: "change",
-    required: true,
-    validator(_, value) {
-      if (typeof value != "number") return new Error("请输入起订量");
-      const num = Number(value + "");
-      if (num < 1) return new Error("起订量不能低于1");
-      return true;
-    }
-  },
-  step: {
-    trigger: "change",
-    required: true,
-    validator(_, value) {
-      if (typeof value != "number") return new Error("请输入步长");
-      const num = Number(value + "");
-      if (num < 1) return new Error("步长不能低于1");
-      return true;
-    }
-  },
-  good_banner_img: {
-    trigger: "change",
-    type: "array",
-    required: true,
-    validator(_, value) {
-      if (value.length === 0) return new Error("请上传轮播图");
-      if (value.length < 3 || value.length > 10)
-        return new Error("轮播图应为3~10张!");
-      return true;
-    }
-  },
-  good_img: {
-    trigger: "change",
-    type: "array",
-    required: true,
-    validator(_, value) {
-      if (value.length === 0) return new Error("请上传详情图");
-      if (value.length > 20) return new Error("详情图不得超过20张!");
-      return true;
-    }
-  },
-  good_param: {
-    trigger: "change",
-    type: "array",
-    required: true,
-    validator(_, value) {
-      if (value === "") return new Error("请输入商品参数");
-      return true;
-    }
-  },
-  good_remark: {
-    trigger: "change",
-    required: true,
-    validator(_, value) {
-      if (!value) return new Error("请输入备注");
-      return true;
-    }
-  }
-};

+ 2 - 18
src/views/parameter/good/config/content.config.ts

@@ -1,20 +1,9 @@
 import { ContentConfig } from "/@/components/PageContent";
-import {
-  httpList,
-  httpAdd,
-  httpUpdate,
-  httpStatus,
-  httpDelete
-} from "/@/api/parameter/good";
+import { httpList, httpStatus, httpDelete } from "/@/api/parameter/good";
 import { renderStatus, renderImage } from "/@/utils/column-helper";
 import { STATUS_OPTIONS, GOOD_OPTIONS } from "/@/config/status";
 
 const columns = [
-  {
-    type: "selection",
-    width: 55,
-    hide: ({ checkList }) => !checkList.includes("勾选列")
-  },
   {
     prop: "good_code",
     label: "商品编码",
@@ -36,20 +25,17 @@ const columns = [
     prop: "type",
     label: "商品类型",
     ...renderStatus(GOOD_OPTIONS, "type")
-    // width: "100px"
   },
   {
     prop: "status",
     label: "状态",
     ...renderStatus(STATUS_OPTIONS)
-    // width: "80px"
   },
 
   {
     prop: "addtime",
     label: "创建时间",
-    // width: 160,
-    sortable: true
+    width: "145px"
   },
 
   {
@@ -64,9 +50,7 @@ const contentConfig: ContentConfig = {
   title: "商品管理",
   columns,
   apis: {
-    httpAdd,
     httpList,
-    httpUpdate,
     httpStatus,
     httpDelete
   }

+ 0 - 45
src/views/parameter/good/config/modal.config.ts

@@ -1,45 +0,0 @@
-import { ModalConfig } from "/@/components/PageModal/src/types";
-import { httpList as httpCompanylist } from "/@/api/parameter/company";
-import { httpList as httpCardlist } from "/@/api/parameter/card";
-const modalConfig: ModalConfig = {
-  title: "企业商品",
-  colLayout: { span: 24 },
-  itemStyle: {  },
-  contact: "setComGood",
-  labelWidth: "85px",
-  formItems: [
-    {
-      field: "id",
-      type: "remote-select",
-      label: "业务企业",
-      placeholder: "业务企业",
-      otherOptions: {
-        api: httpCompanylist,
-        requesetProp: "title",
-        responseLabelProp: "title",
-        responseValPro: "id",
-        prop: "list"
-      },
-      span: 12,
-      rules: [{ required: true, trigger: "change", message: "请选择业务企业" }]
-    },
-    {
-      field: "name2",
-      type: "remote-select",
-      label: "卡类型",
-      placeholder: "卡类型",
-      otherOptions: {
-        api: httpCardlist,
-        responseLabelProp: "title",
-        responseValPro: "id",
-        requesetProp: "",
-        isRoot: false,
-        prop: "list"
-      },
-      span: 12,
-      rules: [{ required: true, trigger: "change", message: "请选择卡类型" }]
-    }
-  ]
-};
-
-export default modalConfig;

+ 32 - 144
src/views/parameter/good/index.vue

@@ -2,161 +2,49 @@
 import { PageSearch, usePageSearch } from "/@/components/PageSearch";
 import searchConfig from "./config/search.config";
 import contentConfig from "./config/content.config";
-// import PageAuth from "/@/components/PageAuth";
-import { PageModal, usePageModal } from "/@/components/PageModalShell";
-import modalConfig from "./config/modal.config";
+import { usePermission } from "/@/hooks/usePermission";
 import { PageContent } from "/@/components/PageContent";
-import { projectFormConfig } from "./config/_details";
-import { projectFormRules } from "./config/_rules";
-import {
-  BasicForm,
-  transform,
-  createDefaultData
-} from "/@/components/BasicForm";
-import { ElImage } from "element-plus";
-import { httpDetail } from "/@/api/parameter/good";
-import { ElForm } from "element-plus";
-import { ref, unref } from "vue";
-// import dayjs from "dayjs";
-import { useResponseHandle } from "/@/hooks/useAsync";
-// import OrderDialog from "/@/components/PageListModal";
-import LadderModal from "./cpns/ladder-modal.vue";
-import LadderTable from "./cpns/ladder-table.vue";
-import { Unit } from "/@/components/RemoteSelect";
-const responseHandle = useResponseHandle();
-const ladderModalRef = ref<InstanceType<typeof LadderModal>>(null);
-// import { httpDetail } from "/@/api/parameter/video";
+import { ref } from "vue";
+
+import EditModel from "./components/edit-dialog.vue";
+const modelRef = ref<InstanceType<typeof EditModel>>(null);
+const pageName = "good";
+const { hasPermissionWithCode, permissions } = usePermission(pageName);
 const { pageContentRef, handleResetClick, handleSearchClick } = usePageSearch(
   undefined,
   undefined,
   searchConfig
 );
-const {
-  pageModalRef,
-  handleUpdateData,
-  handleCreateData,
-  handlePreviewData,
-  handleConfrim,
-  defaultInfo
-} = usePageModal({
-  pageContentRef
-});
-
-const { formItems } = projectFormConfig;
-// const modelRef = ref<InstanceType<typeof OrderDialog>>(null);
-const basicFormRef = ref<InstanceType<typeof ElForm>>(null);
-const formData = ref<Record<string, any>>(createDefaultData(formItems));
-// function handleCreate() {
-//   basicFormRef.value.validate(isValid => {
-//     console.log(isValid);
-//     // if (!isValid) return;
-
-//     const { group_id, good_id } = formData.value;
-//     if (!group_id || good_id.length == 0) return;
-//     console.log(formData.value);
-//     const params = {
-//       group_id,
-//       good_id: []
-//     };
-//     good_id.forEach(si => {
-//       console.log(si);
-//       params.good_id.push(si.id);
-//     });
-//     handleConfrim("create", params);
-//   });
-// }
-async function handleUpdate(_ladder, index) {
-  formData.value.good_param[index] = _ladder;
-}
 
-function handleCreate() {
-  basicFormRef.value.validate(isValid => {
-    if (!isValid) return;
-    const params = unref(formData);
-    handleConfrim("create", params);
-    // emit("create", params);
-  });
-}
-async function handlePush(_ladder) {
-  formData.value.good_param.push(unref(_ladder));
-}
-async function handleDetailData(row, type) {
-  const { id } = row;
-  const { code, data, message } = await httpDetail({ id: id });
-  responseHandle({
-    code,
-    message,
-    handler: () => {
-      if (type === "preview") {
-        handlePreviewData(data);
-      }
-      if (type === "update") {
-        formData.value = transform(formItems, data, {});
-        handleUpdateData(data);
-      }
-    }
-  });
-}
-
-function handleAddOrder(list) {
-  list.forEach(item => {
-    const { id } = item;
-    let findex = formData.value.good_id.findIndex(e => e.id + "" == id + "");
-    if (findex == -1) {
-      formData.value.good_id.push(item);
-    }
-  });
+function handleAddChangeCheck(item: any, id: string, type: string) {
+  modelRef.value.show(item, id, type);
 }
 </script>
 
 <template>
-  <!-- <PageAuth :pageName="pageName"> -->
-  <PageSearch
-    :form-config="searchConfig"
-    @search-btn-click="handleSearchClick"
-    @reset-btn-click="handleResetClick"
-  />
-  <PageContent
-    ref="pageContentRef"
-    :content-config="contentConfig"
-    @create-btn-click="handleCreateData"
-    @preview-btn-click="row => handleDetailData(row, 'preview')"
-    @update-btn-click="row => handleDetailData(row, 'update')"
-  />
-  <PageModal
-    ref="pageModalRef"
-    :modal-config="modalConfig"
-    :default-info="defaultInfo"
-    @confirm-btn-click="handleConfrim"
-  >
-    <BasicForm
-      ref="basicFormRef"
-      v-bind="projectFormConfig"
-      :form-data="formData"
-      :rules="projectFormRules"
-      :disabled="false"
-      label-width="120px"
+  <PageAuth :pageName="pageName">
+    <PageSearch
+      :form-config="searchConfig"
+      @search-btn-click="handleSearchClick"
+      @reset-btn-click="handleResetClick"
     >
-      <template #unit_id>
-        <Unit v-model="formData.unit_id" placeholder="单位" />
-      </template>
-
-      <template #good_param>
-        <LadderTable
-          :readonly="false"
-          :ladder="formData.good_param"
-          @choose="() => ladderModalRef.onDisplay()"
-          @update="({ data, index }) => ladderModalRef.onDisplay(data, index)"
-          @delete="index => formData.good_param.splice(index, 1)"
-        />
-      </template>
-      <template #footer>
-        <div class="w-full flex justify-end">
-          <ElButton type="primary" @click="handleCreate">保存</ElButton>
-        </div>
+      <template #action>
+        <el-button
+          type="primary"
+          @click="handleAddChangeCheck({}, '', 'create')"
+          v-if="hasPermissionWithCode('002')"
+        >
+          新增
+        </el-button>
       </template>
-    </BasicForm>
-  </PageModal>
-  <LadderModal ref="ladderModalRef" @update="handleUpdate" @push="handlePush" />
-  <!-- </PageAuth> -->
+    </PageSearch>
+    <PageContent
+      ref="pageContentRef"
+      :powers="permissions"
+      :content-config="contentConfig"
+      @preview-btn-click="row => handleAddChangeCheck(row, row.id, 'view')"
+      @update-btn-click="row => handleAddChangeCheck(row, row.id, 'edit')"
+    />
+    <EditModel ref="modelRef" @reload="pageContentRef.onSearch()" />
+  </PageAuth>
 </template>

+ 212 - 0
src/views/parameter/video/components/edit-dialog.vue

@@ -0,0 +1,212 @@
+<script setup lang="ts">
+import { FormRules, ElForm } from "element-plus";
+import { reactive, ref } from "vue";
+import { httpUpdate, httpAdd, httpDetail } from "/@/api/parameter/video";
+import { responseHandle } from "/@/utils/responseHandle";
+import { useNav } from "/@/layout/hooks/useNav";
+import { ImageUpload } from "/@/components/Upload";
+
+enum FROM_TYPE {
+  create = "create",
+  edit = "edit",
+  view = "view"
+}
+const { logout } = useNav();
+const showModel = ref(false);
+const currentMenuId = ref("");
+const TYPE = ref<FROM_TYPE>(FROM_TYPE.create);
+const formRef = ref<InstanceType<typeof ElForm>>(null);
+const loading = ref(false);
+const titleType = ref("");
+const id = ref("");
+const emit = defineEmits(["reload"]);
+const initform = {
+  video_img: "",
+  video_name: "",
+  id: "",
+  video_url: "",
+  remark: ""
+};
+const ruleForm = ref({ ...initform });
+const rules = reactive<FormRules>({
+  video_img: [{ required: true, trigger: "change", message: "请选择封面图" }],
+  video_name: [{ required: true, trigger: "bulr", message: "请输入视频名称" }],
+  video_url: [
+    { required: true, trigger: "bulr", message: "请输入视频链接" },
+    {
+      validator: (rule, value, callback) => {
+        if (value === "") {
+          callback(new Error("12"));
+        } else {
+          callback();
+        }
+      }
+    }
+  ],
+  remark: [{ required: true, trigger: "bulr", message: "请输入视频描述" }]
+});
+const initData = async () => {
+  const { code, data, message } = await httpDetail({ id: id.value });
+  responseHandle({
+    code,
+    message,
+    logout,
+    handler: () => {
+      console.log(data);
+      Object.keys(ruleForm.value).forEach(key => {
+        ruleForm.value[key] = data[key] ? data[key] + "" : "";
+      });
+    }
+  });
+};
+async function show(node: any, did: string, isCreate: string) {
+  id.value = did;
+  Object.keys(ruleForm.value).forEach(key => {
+    ruleForm.value[key] = initform[key] ? initform[key] + "" : "";
+  });
+  TYPE.value = isCreate;
+  switch (TYPE.value) {
+    case "create":
+      titleType.value = "新建视频";
+      break;
+    case "edit":
+      titleType.value = "编辑视频";
+      break;
+    case "view":
+      titleType.value = "视频详情";
+      break;
+    default:
+      titleType.value = "新建视频";
+  }
+  if (TYPE.value !== "create") {
+    await initData();
+  }
+
+  showModel.value = true;
+}
+
+function handleUpdate() {
+  const data = {
+    ...ruleForm.value
+  };
+
+  return {
+    data,
+    api: httpUpdate
+  };
+}
+
+function handleCreate() {
+  const data = {
+    ...ruleForm.value
+  };
+
+  return {
+    data,
+    api: httpAdd
+  };
+}
+
+function handleSave() {
+  formRef.value.validate(async vaild => {
+    if (vaild) {
+      if (loading.value) return;
+      const handler =
+        TYPE.value === FROM_TYPE.create ? handleCreate : handleUpdate;
+
+      loading.value = true;
+      const { api, data } = handler();
+      const { message, code } = await api(data);
+      loading.value = false;
+      responseHandle({
+        code,
+        message,
+        logout,
+        handler: () => {
+          showModel.value = false;
+          emit("reload");
+        }
+      });
+    }
+  });
+}
+
+defineExpose({
+  show,
+  changeCurrentMenuId: (id: string) => (currentMenuId.value = id)
+});
+</script>
+
+<template>
+  <el-dialog
+    v-model="showModel"
+    :close-on-press-escape="false"
+    center
+    append-to-body
+    destroy-on-close
+    :width="'800px'"
+    :title="titleType"
+    v-loading="loading"
+  >
+    <el-form
+      ref="formRef"
+      :model="ruleForm"
+      :rules="rules"
+      label-width="90px"
+      style="margin-top: -10px"
+      class="demo-ruleForm"
+      status-icon
+    >
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="封面图" prop="video_img">
+            <ImageUpload
+              v-model:url="ruleForm.video_img"
+              :disabled="TYPE === 'view'"
+              :descs="['小于1Mb']"
+              :types="['png', 'jpg', 'jpeg']"
+            /> </el-form-item
+        ></el-col>
+        <el-col :span="24">
+          <el-form-item label="视频名称" prop="video_name">
+            <ElInput
+              placeholder="视频名称"
+              :disabled="TYPE === 'view'"
+              maxlength="50"
+              v-model="ruleForm.video_name"
+            /> </el-form-item
+        ></el-col>
+        <el-col :span="24">
+          <el-form-item label="视频链接" prop="video_url">
+            <ElInput
+              placeholder="视频链接"
+              :disabled="TYPE === 'view'"
+              maxlength="50"
+              v-model="ruleForm.video_url"
+            /> </el-form-item
+        ></el-col>
+        <el-col :span="24">
+          <el-form-item label="视频描述" prop="remark">
+            <ElInput
+              placeholder="视频描述"
+              :disabled="TYPE === 'view'"
+              type="textarea"
+              maxlength="600"
+              v-model="ruleForm.remark"
+            /> </el-form-item
+        ></el-col>
+      </el-row>
+      <div class="flex justify-end">
+        <el-button
+          v-if="TYPE !== 'view'"
+          :loading="loading"
+          :disabled="loading"
+          type="primary"
+          @click="handleSave"
+          >保存</el-button
+        >
+        <el-button @click="showModel = false">取消</el-button>
+      </div>
+    </el-form>
+  </el-dialog>
+</template>

+ 7 - 17
src/views/parameter/video/config/content.config.ts

@@ -1,20 +1,9 @@
 import { ContentConfig } from "/@/components/PageContent";
-import {
-  httpAdd,
-  httpDelete,
-  httpStatus,
-  httpList,
-  httpUpdate
-} from "/@/api/parameter/video";
+import { httpDelete, httpStatus, httpList } from "/@/api/parameter/video";
 import { renderStatus } from "/@/utils/column-helper";
 import { STATUS_OPTIONS } from "/@/config/status";
 
 const columns = [
-  {
-    type: "selection",
-    width: 55,
-    hide: ({ checkList }) => !checkList.includes("勾选列")
-  },
   {
     prop: "id",
     label: "ID",
@@ -30,6 +19,10 @@ const columns = [
     label: "状态",
     ...renderStatus(STATUS_OPTIONS)
   },
+  {
+    prop: "video_url",
+    label: "视频链接"
+  },
   {
     prop: "addtime",
     label: "创建时间"
@@ -46,13 +39,10 @@ const contentConfig: ContentConfig = {
   title: "视频管理",
   columns,
   apis: {
-    httpAdd,
     httpDelete,
     httpStatus,
-    httpList,
-    httpUpdate,
-  },
-  notPreview: false
+    httpList
+  }
 };
 
 export default contentConfig;

+ 0 - 46
src/views/parameter/video/config/modal.config.ts

@@ -1,46 +0,0 @@
-import { ModalConfig } from "/@/components/PageModal/src/types";
-import { isLicense } from "/@/utils/validate";
-
-const modalConfig: ModalConfig = {
-  title: "视频",
-  colLayout: { span: 24 },
-  itemStyle: {},
-  contact: "invoice_mobile",
-  labelWidth: "100px",
-  formItems: [
-    {
-      field: "video_img",
-      type: "img_upload",
-      label: "视频封面",
-      placeholder: "视频封面",
-      span: 8,
-      rules: [
-        { required: true, trigger: "change", message: "请上传视频封面!" }
-      ]
-    },
-    {
-      field: "video_name",
-      type: "input",
-      label: "视频名称",
-      placeholder: "视频名称",
-      span: 16,
-      rules: [{ required: true, trigger: "change", message: "请输入视频名称" }]
-    },
-    {
-      field: "video_url",
-      type: "input",
-      label: "视频链接",
-      placeholder: "视频链接",
-      rules: [{ required: true, trigger: "change", message: "请输入视频链接" }]
-    },
-    {
-      field: "remark",
-      type: "textarea",
-      label: "视频描述",
-      placeholder: "视频描述",
-      rules: [{ required: true, trigger: "change", message: "请输入视频描述" }]
-    }
-  ]
-};
-
-export default modalConfig;

+ 32 - 54
src/views/parameter/video/index.vue

@@ -3,68 +3,46 @@ import { ref } from "vue";
 import { PageSearch, usePageSearch } from "/@/components/PageSearch";
 import searchConfig from "./config/search.config";
 import contentConfig from "./config/content.config";
-import PageAuth from "/@/components/PageAuth";
-import { PageModal, usePageModal } from "/@/components/PageModal";
-import modalConfig from "./config/modal.config";
+import EditModel from "./components/edit-dialog.vue";
+import { usePermission } from "/@/hooks/usePermission";
 import { PageContent } from "/@/components/PageContent";
-import { useResponseHandle } from "/@/hooks/useAsync";
-import { httpDetail } from "/@/api/parameter/video";
+const modelRef = ref<InstanceType<typeof EditModel>>(null);
+const pageName = "good";
 const { pageContentRef, handleResetClick, handleSearchClick } = usePageSearch(
   undefined,
   undefined,
   searchConfig
 );
-const {
-  pageModalRef,
-  handleUpdateData,
-  handleCreateData,
-  handlePreviewData,
-  handleConfrim,
-  defaultInfo
-} = usePageModal({
-  pageContentRef
-});
-
-const responseHandle = useResponseHandle();
-async function handleDetailData(row, type) {
-  const { id } = row;
-  //
-  const { code, data, message } = await httpDetail({ id: id });
-
-  responseHandle({
-    code,
-    message,
-    handler: () => {
-      if (type === "preview") {
-        handlePreviewData(data);
-      }
-      if (type === "update") {
-        handleUpdateData(data);
-      }
-    }
-  });
+const { hasPermissionWithCode, permissions } = usePermission(pageName);
+function handleAddChangeCheck(item: any, id: string, type: string) {
+  modelRef.value.show(item, id, type);
 }
 </script>
 
 <template>
-  <!-- <PageAuth :pageName="pageName"> -->
-  <PageSearch
-    :form-config="searchConfig"
-    @search-btn-click="handleSearchClick"
-    @reset-btn-click="handleResetClick"
-  />
-  <PageContent
-    ref="pageContentRef"
-    :content-config="contentConfig"
-    @create-btn-click="handleCreateData"
-    @preview-btn-click="row => handleDetailData(row, 'preview')"
-    @update-btn-click="row => handleDetailData(row, 'update')"
-  />
-  <PageModal
-    ref="pageModalRef"
-    :modal-config="modalConfig"
-    :default-info="defaultInfo"
-    @confirm-btn-click="handleConfrim"
-  />
-  <!-- </PageAuth> -->
+  <PageAuth :pageName="pageName">
+    <PageSearch
+      :form-config="searchConfig"
+      @search-btn-click="handleSearchClick"
+      @reset-btn-click="handleResetClick"
+    >
+      <template #action>
+        <el-button
+          type="primary"
+          @click="handleAddChangeCheck({}, '', 'create')"
+          v-if="hasPermissionWithCode('002')"
+        >
+          新增
+        </el-button>
+      </template>
+    </PageSearch>
+    <PageContent
+      ref="pageContentRef"
+      :powers="permissions"
+      :content-config="contentConfig"
+      @preview-btn-click="row => handleAddChangeCheck(row, row.id, 'view')"
+      @update-btn-click="row => handleAddChangeCheck(row, row.id, 'edit')"
+    />
+    <EditModel ref="modelRef" @reload="pageContentRef.onSearch()" />
+  </PageAuth>
 </template>

+ 10 - 4
src/views/system/logistics/index.vue

@@ -3,21 +3,27 @@ import { PageContent } from "/@/components/PageContent";
 import contentConfig from "./config/content.config";
 import searchConfig from "./config/search.config";
 import { PageSearch, usePageSearch } from "/@/components/PageSearch";
-
+import { usePermission } from "/@/hooks/usePermission";
+const pageName = "logistics";
 const { pageContentRef, handleResetClick, handleSearchClick } = usePageSearch(
   undefined,
   undefined,
   searchConfig
 );
+const { permissions } = usePermission(pageName);
 </script>
 
 <template>
-  <div>
+  <PageAuth :pageName="pageName">
     <PageSearch
       :form-config="searchConfig"
       @search-btn-click="handleSearchClick"
       @reset-btn-click="handleResetClick"
     />
-    <PageContent ref="pageContentRef" :content-config="contentConfig" />
-  </div>
+    <PageContent
+      :powers="permissions"
+      ref="pageContentRef"
+      :content-config="contentConfig"
+    />
+  </PageAuth>
 </template>

+ 1 - 2
src/views/system/menuOperator/components/edit-dialog.vue

@@ -161,14 +161,13 @@ function handleSave() {
       loading.value = true;
       const { api, data } = handler();
       const { message, code } = await api(data);
-
+      loading.value = false;
       responseHandle({
         code,
         message,
         logout,
         handler: () => {
           showModel.value = false;
-          loading.value = false;
           emit("reload");
         }
       });

+ 5 - 3
src/views/system/setBtn/components/edit-dialog.vue

@@ -97,14 +97,13 @@ function handleSave() {
       loading.value = true;
       const { api, data } = handler();
       const { message, code } = await api(data);
-
+      loading.value = false;
       responseHandle({
         code,
         message,
         logout,
         handler: () => {
           showModel.value = false;
-          loading.value = false;
           emit("reload");
         }
       });
@@ -157,7 +156,10 @@ defineExpose({
         ></el-col>
         <el-col :span="24">
           <el-form-item label="状态" prop="status">
-            <el-radio-group v-model="ruleForm.status">
+            <el-radio-group
+              v-model="ruleForm.status"
+              :disabled="TYPE === 'view'"
+            >
               <el-radio
                 v-for="(si, sii) in STATUS_OPTIONS"
                 :key="'card_id' + si.id + sii"

+ 234 - 0
src/views/system/updates/components/edit-dialog.vue

@@ -0,0 +1,234 @@
+<script setup lang="ts">
+import "@wangeditor/editor/dist/css/style.css"; // 引入 css
+import { FormRules, ElForm } from "element-plus";
+import { onBeforeUnmount, reactive, shallowRef, ref } from "vue";
+import { httpUpdate, httpAdd } from "/@/api/system/updates";
+import { responseHandle } from "/@/utils/responseHandle";
+import { useNav } from "/@/layout/hooks/useNav";
+import { SYS_TYPE_OPTIONS } from "/@/config/status";
+import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
+enum FROM_TYPE {
+  create = "create",
+  edit = "edit",
+  view = "view"
+}
+const mode = "default";
+const { logout } = useNav();
+const showModel = ref(false);
+const currentMenuId = ref("");
+const TYPE = ref<FROM_TYPE>(FROM_TYPE.create);
+const formRef = ref<InstanceType<typeof ElForm>>(null);
+const loading = ref(false);
+const titleType = ref("");
+const editorRef = shallowRef();
+const emit = defineEmits(["reload"]);
+
+const editorConfig = { placeholder: "请输入内容..." };
+const initform = {
+  sys_type: "",
+  version: "",
+  title: "",
+  addtime: "",
+  content: ""
+};
+const ruleForm = ref({ ...initform });
+const rules = reactive<FormRules>({
+  sys_type: [{ required: true, trigger: "change", message: "请选择类型" }],
+  version: [{ required: true, trigger: "bulr", message: "请输入版本号" }],
+  title: [{ required: true, trigger: "bulr", message: "请输入标题" }],
+  addtime: [{ required: true, trigger: "change", message: "请选择时间" }],
+  content: [{ required: true, trigger: "bulr", message: "请输入内容" }]
+});
+
+const handleCreated = editor => {
+  editorRef.value = editor;
+};
+onBeforeUnmount(() => {
+  const editor = editorRef.value;
+  if (editor == null) return;
+  editor.destroy();
+});
+async function show(node: any, id: string, isCreate: string) {
+  Object.keys(ruleForm.value).forEach(key => {
+    // if (key === "menuid") {
+    //   ruleForm.value[key] = menuid;
+    // } else {
+    ruleForm.value[key] =
+      isCreate === "create"
+        ? initform[key]
+          ? initform[key] + ""
+          : ""
+        : node[key]
+        ? node[key] + ""
+        : "";
+    // }
+  });
+  console.log(ruleForm.value);
+  TYPE.value = isCreate;
+  switch (TYPE.value) {
+    case "create":
+      titleType.value = "新建版本信息";
+      break;
+    case "edit":
+      titleType.value = "编辑版本信息";
+      break;
+    case "view":
+      titleType.value = "版本信息详情";
+      break;
+    default:
+      titleType.value = "新建版本信息";
+  }
+
+  showModel.value = true;
+}
+
+function handleUpdate() {
+  const data = {
+    ...ruleForm.value
+  };
+
+  return {
+    data,
+    api: httpUpdate
+  };
+}
+
+function handleCreate() {
+  const data = {
+    ...ruleForm.value
+  };
+
+  return {
+    data,
+    api: httpAdd
+  };
+}
+
+function handleSave() {
+  formRef.value.validate(async vaild => {
+    if (vaild) {
+      if (loading.value) return;
+      const handler =
+        TYPE.value === FROM_TYPE.create ? handleCreate : handleUpdate;
+
+      loading.value = true;
+      const { api, data } = handler();
+      const { message, code } = await api(data);
+      loading.value = false;
+      responseHandle({
+        code,
+        message,
+        logout,
+        handler: () => {
+          showModel.value = false;
+          emit("reload");
+        }
+      });
+    }
+  });
+}
+
+defineExpose({
+  show,
+  changeCurrentMenuId: (id: string) => (currentMenuId.value = id)
+});
+</script>
+
+<template>
+  <el-dialog
+    v-model="showModel"
+    :close-on-press-escape="false"
+    center
+    append-to-body
+    destroy-on-close
+    :width="'1040px'"
+    :title="titleType"
+    v-loading="loading"
+  >
+    <el-form
+      ref="formRef"
+      :model="ruleForm"
+      :rules="rules"
+      label-width="90px"
+      style="margin-top: -10px"
+      class="demo-ruleForm"
+      status-icon
+    >
+      <el-row>
+        <el-col :span="12">
+          <el-form-item label="类型" prop="sys_type">
+            <el-select
+              v-model="ruleForm.sys_type"
+              style="width: 100%"
+              :disabled="TYPE === 'view'"
+              placeholder="类型"
+            >
+              <el-option
+                v-for="(si, sii) in SYS_TYPE_OPTIONS"
+                :key="'action_code' + si.id + sii"
+                :label="si.label"
+                :value="si.id + ''"
+              />
+            </el-select> </el-form-item
+        ></el-col>
+        <el-col :span="12">
+          <el-form-item label="版本号" prop="version">
+            <ElInput
+              placeholder="版本号"
+              :disabled="TYPE === 'view'"
+              v-model="ruleForm.version"
+            /> </el-form-item
+        ></el-col>
+        <el-col :span="12">
+          <el-form-item label="标题" prop="title">
+            <ElInput
+              placeholder="标题"
+              :disabled="TYPE === 'view'"
+              v-model="ruleForm.title"
+            /> </el-form-item
+        ></el-col>
+        <el-col :span="12">
+          <el-form-item label="时间" prop="addtime">
+            <ElDatePicker
+              value-format="YYYY-MM-DD HH:mm:ss"
+              v-model="ruleForm.addtime"
+              type="datetime"
+              :disabled="TYPE === 'view'"
+              style="width: 100%"
+              placeholder="时间"
+            /> </el-form-item
+        ></el-col>
+        <el-col :span="24">
+          <el-form-item label="内容" prop="content">
+            <div style="border: 1px solid #ccc">
+              <Toolbar
+                style="border-bottom: 1px solid #ccc"
+                :editor="editorRef"
+                :disabled="TYPE === 'view'"
+                :mode="mode"
+              />
+              <Editor
+                style="height: 400px; overflow-y: hidden"
+                v-model="ruleForm.content"
+                :disabled="TYPE === 'view'"
+                :defaultConfig="editorConfig"
+                :mode="mode"
+                @onCreated="handleCreated"
+              />
+            </div> </el-form-item
+        ></el-col>
+      </el-row>
+      <div class="flex justify-end">
+        <el-button
+          v-if="TYPE !== 'view'"
+          :loading="loading"
+          :disabled="loading"
+          type="primary"
+          @click="handleSave"
+          >保存</el-button
+        >
+        <el-button @click="showModel = false">取消</el-button>
+      </div>
+    </el-form>
+  </el-dialog>
+</template>

+ 16 - 24
src/views/system/updates/config/content.config.ts

@@ -1,42 +1,34 @@
 import { ContentConfig } from "/@/components/PageContent";
 import { httpList } from "/@/api/system/updates";
-import dayjs from "dayjs";
-import { renderHtml } from "/@/utils/column-helper";
+import { renderStatus } from "/@/utils/column-helper";
+import { SYS_TYPE_OPTIONS } from "/@/config/status";
 const columns = [
-  {
-    type: "selection",
-    minWidth: 55,
-    align: "left",
-    hide: ({ checkList }) => !checkList.includes("勾选列")
-  },
-  {
-    label: "序号",
-    type: "index",
-    minWidth: 60,
-    align: "left",
-    hide: ({ checkList }) => !checkList.includes("序号列")
-  },
-  {
-    type: "expand",
-    slot: "expand"
-  },
   {
     label: "版本号",
     prop: "version",
-    minWidth: 180,
+
     align: "left"
   },
+  {
+    prop: "sys_type",
+    label: "类型",
+    ...renderStatus(SYS_TYPE_OPTIONS, "sys_type")
+  },
   {
     label: "更新模块",
     prop: "title",
-    minWidth: 180,
+
     align: "left"
   },
   {
     label: "更新时间",
-    minWidth: 180,
-    prop: "addtime",
-    formatter: ({ addtime }) => dayjs(addtime).format("YYYY-MM-DD HH:mm:ss")
+    prop: "addtime"
+  },
+  {
+    label: "操作",
+    fixed: "right",
+    width: 160,
+    slot: "operation"
   }
 ];
 

+ 7 - 0
src/views/system/updates/config/search.config.ts

@@ -0,0 +1,7 @@
+import { FormConfig } from "/@/components/PageSearch";
+const searchFormConfig: FormConfig = {
+  isHide: false,
+  formItems: []
+};
+
+export default searchFormConfig;

+ 40 - 15
src/views/system/updates/index.vue

@@ -1,24 +1,49 @@
 <script setup lang="ts">
+import { ref } from "vue";
+import { PageSearch, usePageSearch } from "/@/components/PageSearch";
 import { PageContent } from "/@/components/PageContent";
 import contentConfig from "./config/content.config";
-
-function transformUpdateInfo(info: string) {
-  const m = "<br/>";
-  const chunks = info.split(m);
-  return chunks;
+import { usePermission } from "/@/hooks/usePermission";
+import searchConfig from "./config/search.config";
+import EditModel from "./components/edit-dialog.vue";
+const { pageContentRef, handleResetClick, handleSearchClick } = usePageSearch(
+  undefined,
+  undefined,
+  searchConfig
+);
+const modelRef = ref<InstanceType<typeof EditModel>>(null);
+const pageName = "updates";
+const { hasPermissionWithCode, permissions } = usePermission(pageName);
+function handleAddChangeCheck(item: any, id: string, type: string) {
+  modelRef.value.show(item, id, type);
 }
 </script>
 
 <template>
-  <div>
-    <PageContent :content-config="contentConfig">
-      <template #expand="{ system }">
-        <div class="px-[20px]">
-          <p v-for="(item, index) in transformUpdateInfo(system)" :key="index">
-            {{ item }}
-          </p>
-        </div>
+  <PageAuth :pageName="pageName">
+    <PageSearch
+      :form-config="searchConfig"
+      @search-btn-click="handleSearchClick"
+      @reset-btn-click="handleResetClick"
+    >
+      <template #action>
+        <el-button
+          type="primary"
+          @click="handleAddChangeCheck({}, '', 'create')"
+          v-if="hasPermissionWithCode('002')"
+        >
+          新增
+        </el-button>
       </template>
-    </PageContent>
-  </div>
+    </PageSearch>
+    <PageContent
+      ref="pageContentRef"
+      :content-config="contentConfig"
+      :powers="permissions"
+      @preview-btn-click="row => handleAddChangeCheck(row, row.id, 'view')"
+      @update-btn-click="row => handleAddChangeCheck(row, row.id, 'edit')"
+    />
+
+    <EditModel ref="modelRef" @reload="pageContentRef.onSearch()" />
+  </PageAuth>
 </template>