xiaodai2017 2 years ago
parent
commit
44165d630d

+ 6 - 6
src/api/parameter/good.ts

@@ -5,37 +5,37 @@ const { VITE_PROXY_DOMAIN_REAL } = loadEnv();
 
 // 添加
 export async function httpAdd(data: object = {}): Promise<DataType<any>> {
-  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/companyAdd`, {
+  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/goodAdd`, {
     data
   });
 }
 // 列表
 export async function httpList(data: object = {}): Promise<DataType<any>> {
-  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/companylist`, {
+  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/goodList`, {
     data
   });
 }
 // 详情
 export async function httpDetail(data: object = {}): Promise<DataType<any>> {
-  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/companyRead`, {
+  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/goodRead`, {
     data
   });
 }
 // 更新
 export async function httpUpdate(data: object = {}): Promise<DataType<any>> {
-  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/companyEdit`, {
+  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/goodEdit`, {
     data
   });
 }
 // 状态
 export async function httpStatus(data: object = {}): Promise<DataType<any>> {
-  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/companyChange`, {
+  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/goodChange`, {
     data
   });
 }
 // 删除
 export async function httpDelete(data: object = {}): Promise<DataType<any>> {
-  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/companyDelete`, {
+  return http.request("post", `${VITE_PROXY_DOMAIN_REAL}admin/goodDelete`, {
     data
   });
 }

+ 4 - 1
src/components/BasicForm/src/_createDafaultData.ts

@@ -1,7 +1,7 @@
 import { FormItem } from "./types";
 
 export function createDefaultData(formItems: FormItem[]) {
-  console.log(formItems);
+  // console.log(formItems);
   const data: Record<string, any> = {};
   //创建默认值策略
   for (const item of formItems) {
@@ -13,6 +13,9 @@ export function createDefaultData(formItems: FormItem[]) {
       case "number":
         data[item.field] = 0;
         break;
+      case "array":
+        data[item.field] = [];
+        break;
       default:
         data[item.field] = "";
         break;

+ 2 - 1
src/components/BasicForm/src/types.ts

@@ -16,7 +16,8 @@ export type FormItemType =
   | "number"
   | "custom"
   | "input_group"
-  | "remote-select";
+  | "remote-select"
+  | "array";
 
 export type FormItem = {
   field: string;

+ 1 - 1
src/components/PageContent/src/page-content.tsx

@@ -32,7 +32,7 @@ const PageConent = defineComponent({
   setup(props, { expose, emit, slots }) {
     //根据传入的api决定表格需要的操作
     const action = createOperation(props.contentConfig.apis);
-    console.log(action);
+    // console.log(action);
 
     const tableRef = ref<InstanceType<typeof PureTable>>(null);
 

+ 3 - 2
src/components/UploadList/src/image.vue

@@ -110,7 +110,7 @@ const httpupLoad = (file, i): Promise<string> => {
     >
       <img :src="item" alt="" />
 
-      <div class="absolute top-[-3px] right-[5px]">
+      <div class="absolute top-[-3px] right-[5px]" v-show="!disabled">
         <ElButton
           link
           size="large"
@@ -120,7 +120,8 @@ const httpupLoad = (file, i): Promise<string> => {
         />
       </div>
     </li>
-    <li class="img-input">
+
+    <li class="img-input" v-show="!disabled">
       <input
         ref="inputer"
         v-loading="loading"

+ 1 - 3
src/hooks/useAsync.ts

@@ -7,13 +7,12 @@ type Params = {
   code: number;
   message: string;
   handler: () => void;
-  errorHandler?: () => void;
 };
 
 export function useResponseHandle() {
   const { logout } = useNav();
 
-  function responseHandle({ code, message, handler, errorHandler }: Params) {
+  function responseHandle({ code, message, handler }: Params) {
     const c = Number(code);
     if (c === 0) {
       handler();
@@ -21,7 +20,6 @@ export function useResponseHandle() {
       logout();
     } else {
       ElMessage.error(message);
-      errorHandler();
     }
   }
 

+ 29 - 1
src/utils/column-helper.ts

@@ -1,5 +1,5 @@
 import { h } from "vue";
-import { ElTag } from "element-plus";
+import { ElTag, ElImage } from "element-plus";
 
 export function renderCategory(prop = "can") {
   return {
@@ -26,6 +26,34 @@ export function renderStatus(options: any[], prop = "status") {
   };
 }
 
+export function renderImage(prop = "image") {
+  return {
+    cellRenderer({ row }) {
+      return h(
+        ElImage,
+        {
+          src: row[prop],
+          fit: "cover",
+          lazy: true,
+          "preview-src-list": row[prop] !== "" ? [row[prop]] : [],
+          "z-index": 99999,
+          "preview-teleported": true
+        },
+        {
+          default: () => "--"
+        }
+      );
+    }
+  };
+}
+// <el-image
+//       style="width: 100px; height: 100px"
+//       :src="url"
+//       :preview-src-list="src"
+//       :initial-index="4"
+//       fit="cover"
+//     />
+
 export function convertOptions(source: any[], prop = "id") {
   return source.map(item => ({ value: item[prop], label: item.label }));
 }

+ 3 - 2
src/views/parameter/good/config/_details.ts

@@ -63,7 +63,7 @@ export const projectFormConfig: FormConfig = {
     },
     {
       label: "轮播图",
-      type: 'img_upload_list',
+      type: "img_upload_list",
       field: "good_banner_img",
       placeholder: "轮播图",
       span: 24
@@ -71,12 +71,13 @@ export const projectFormConfig: FormConfig = {
     {
       label: "详情图",
       field: "good_img",
-      type: 'img_upload_list',
+      type: "img_upload_list",
       placeholder: "详情图",
       span: 24
     },
     {
       label: "商品参数",
+      type: "array",
       field: "good_param",
       placeholder: "商品参数",
       slot: "good_param",

+ 13 - 39
src/views/parameter/good/config/_rules.ts

@@ -1,31 +1,12 @@
 import { FormRules } from "element-plus";
 
 export const ladderFormRules: FormRules = {
-  good_name: {
-    trigger: "change",
-    required: true,
-    validator(_, value) {
-      const val = value ?? "";
-      if (val === "") return new Error("请输入商品名称");
-      return true;
-    }
-  },
-  good_cover_img: {
-    trigger: "change",
-    required: true,
-    message: "请上传封面图",
-    validator(_, value) {
-      const val = value ?? "";
-      if (val === "") return new Error("请上传封面图");
-      return true;
-    }
-  },
-  type: {
+  key: {
     trigger: "change",
     required: true,
     message: "请选择商品类型"
   },
-  unit_id: {
+  value: {
     trigger: "change",
     required: true,
     message: "请选择单位"
@@ -37,9 +18,7 @@ export const projectFormRules: FormRules = {
     trigger: "change",
     required: true,
     validator(_, value) {
-      console.log(value);
-      const val = value ?? "";
-      if (val === "") return new Error("请输入商品名称");
+      if (value === "") return new Error("请输入商品名称");
       return true;
     }
   },
@@ -48,8 +27,7 @@ export const projectFormRules: FormRules = {
     required: true,
     message: "请上传封面图",
     validator(_, value) {
-      const val = value ?? "";
-      if (val === "") return new Error("请上传封面图");
+      if (value === "") return new Error("请上传封面图");
       return true;
     }
   },
@@ -66,11 +44,10 @@ export const projectFormRules: FormRules = {
   price: {
     trigger: "change",
     required: true,
-    message: "请输入售价",
     validator(_, value) {
-      console.log(typeof value + "--售价--" + value);
-      const val = value ?? "";
-      if (val === "") return new Error("请输入售价");
+      // console.log(typeof value + "--售价--" + value);
+
+      if (value === "") return new Error("请输入售价");
       return true;
     }
   },
@@ -98,11 +75,10 @@ export const projectFormRules: FormRules = {
     trigger: "change",
     type: "array",
     required: true,
-    message: "请上传轮播图",
     validator(_, value) {
-      console.log(value);
-      // const val = value ?? "";
-      // if (val === "") return new Error("请上传轮播图");
+      if (value.length === 0) return new Error("请上传轮播图");
+      if (value.length < 3 || value.length > 10)
+        return new Error("轮播图应为3~10张!");
       return true;
     }
   },
@@ -110,10 +86,9 @@ export const projectFormRules: FormRules = {
     trigger: "change",
     type: "array",
     required: true,
-    message: "请上传详情图",
     validator(_, value) {
-      const val = value ?? "";
-      if (val === "") return new Error("请上传详情图");
+      if (value.length === 0) return new Error("请上传详情图");
+      if (value.length > 20) return new Error("详情图不得超过20张!");
       return true;
     }
   },
@@ -122,8 +97,7 @@ export const projectFormRules: FormRules = {
     type: "array",
     required: true,
     validator(_, value) {
-      const val = value ?? "";
-      if (val === "") return new Error("请输入商品参数");
+      if (value === "") return new Error("请输入商品参数");
       return true;
     }
   }

+ 23 - 15
src/views/parameter/good/config/content.config.ts

@@ -6,8 +6,8 @@ import {
   httpStatus,
   httpDelete
 } from "/@/api/parameter/good";
-import { renderStatus } from "/@/utils/column-helper";
-import { STATUS_OPTIONS } from "/@/config/status";
+import { renderStatus, renderImage } from "/@/utils/column-helper";
+import { STATUS_OPTIONS, GOOD_OPTIONS } from "/@/config/status";
 
 const columns = [
   {
@@ -15,32 +15,40 @@ const columns = [
     width: 55,
     hide: ({ checkList }) => !checkList.includes("勾选列")
   },
-
   {
-    prop: "id",
-    label: "ID"
+    prop: "good_code",
+    label: "商品编码",
+    width: "180px"
   },
   {
-    prop: "title",
-    label: "卡类型"
+    prop: "good_cover_img",
+    label: "图片",
+    width: "60px",
+    ...renderImage("good_cover_img")
   },
-
   {
-    prop: "status",
-    label: "状态",
-    ...renderStatus(STATUS_OPTIONS)
+    prop: "good_name",
+    label: "商品名称",
+    minWidth: "200px"
   },
+
   {
-    prop: "contacts",
-    label: "联系人"
+    prop: "type",
+    label: "商品类型",
+    ...renderStatus(GOOD_OPTIONS, "type")
+    // width: "100px"
   },
   {
-    prop: "mobile",
-    label: "联系方式"
+    prop: "status",
+    label: "状态",
+    ...renderStatus(STATUS_OPTIONS)
+    // width: "80px"
   },
+
   {
     prop: "addtime",
     label: "创建时间",
+    // width: 160,
     sortable: true
   },
 

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

@@ -1,100 +0,0 @@
-import { ModalConfig } from "/@/components/PageModal/src/types";
-import { GOOD_OPTIONS } from "/@/config/status";
-const modalConfig: ModalConfig = {
-  title: "商品",
-  colLayout: { span: 24 },
-  itemStyle: {},
-  contact: "good",
-  labelWidth: "85px",
-  formItems: [
-    {
-      field: "name",
-      type: "input",
-      label: "商品名称",
-      placeholder: "商品名称",
-      span: 24,
-      rules: [{ required: true, trigger: "blur", message: "请输入商品名称" }]
-    },
-    {
-      field: "type",
-      type: "select",
-      label: "商品类型",
-      placeholder: "商品类型",
-      span: 8,
-      options: GOOD_OPTIONS,
-      rules: [{ required: true, trigger: "change", message: "请选择商品类型" }]
-    },
-    {
-      field: "unit",
-      type: "input",
-      label: "单位",
-      placeholder: "单位",
-      span: 8,
-      rules: [{ required: true, trigger: "blur", message: "请输入步长" }]
-    },
-    {
-      field: "price",
-      type: "number",
-      label: "售价",
-      placeholder: "售价",
-      span: 8,
-      rules: [{ required: true, trigger: "blur", message: "请输入售价" }]
-    },
-    {
-      field: "img1",
-      type: "img_upload",
-      label: "封面图",
-      placeholder: "封面图",
-      span: 8,
-      rules: [{ required: true, trigger: "blur", message: "请输入备注" }]
-    },
-    {
-      field: "a",
-      type: "number",
-      label: "起订量",
-      placeholder: "起订量",
-      span: 8,
-      rules: [{ required: true, trigger: "blur", message: "请输入起订量" }]
-    },
-    {
-      field: "b",
-      type: "number",
-      label: "步长",
-      placeholder: "步长",
-      span: 8,
-      rules: [{ required: true, trigger: "blur", message: "请输入步长" }]
-    },
-
-    {
-      field: "img2",
-      type: "img_upload",
-      label: "轮播图",
-      placeholder: "轮播图",
-      span: 16,
-      rules: [{ required: true, trigger: "blur", message: "请输入备注" }]
-    },
-    {
-      field: "img3",
-      type: "img_upload_list",
-      label: "详情图",
-      placeholder: "详情图",
-      rules: [{ required: true, trigger: "blur", message: "请输入备注" }]
-    },
-    {
-      field: "arr",
-      type: "input",
-      label: "产品参数",
-      placeholder: "产品参数",
-      rules: [{ required: true, trigger: "blur", message: "请输入备注" }]
-    },
-    {
-      field: "remark",
-      type: "textarea",
-      label: "备注",
-      placeholder: "备注",
-      rules: [{ required: false, trigger: "blur", message: "请输入备注" }]
-    }
-  ]
-};
-
-export default modalConfig;

+ 7 - 43
src/views/parameter/good/cpns/ladder-modal.vue

@@ -1,21 +1,13 @@
 <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";
 
 const emit = defineEmits(["push", "update"]);
 
 const defaultData = {
-  budget_price: "0.00",
-  good_type: "1",
-  good_name: "",
-  cat_info: [],
-  num: "0"
+  key: "",
+  value: ""
 };
 
 const isUpdate = ref(false);
@@ -67,45 +59,17 @@ defineExpose({
     <ElForm
       ref="formRef"
       :model="formData"
+      width="500px"
       :rules="ladderFormRules"
       label-width="100px"
-      size="small"
     >
-      <ElFormItem label="预算单价" prop="budget_price">
-        <AmountInput v-model="formData.budget_price" />
-      </ElFormItem>
-
-      <ElFormItem label="购买数量" prop="num">
-        <NumberInput placeholder="购买数量" v-model="formData.num" />
-      </ElFormItem>
-
-      <ElFormItem label="商品类型" prop="good_type">
-        <ElSelect
-          style="width: 100%"
-          placeholder="商品类型"
-          v-model="formData.good_type"
-        >
-          <ElOption
-            v-for="item in goodTypeOptions"
-            :value="item.id"
-            :label="item.label"
-            :key="item.id"
-          />
-        </ElSelect>
+      <ElFormItem label="类型" prop="key">
+        <ElInput placeholder="类型" v-model="formData.key" />
       </ElFormItem>
 
-      <ElFormItem label="商品分类" prop="cat_info">
-        <GoodClass v-model="formData.cat_info" style="width: 100%" />
+      <ElFormItem label="类型值" prop="value">
+        <ElInput placeholder="类型值" v-model="formData.value" />
       </ElFormItem>
-
-      <ElFormItem label="商品名称" prop="good_name">
-        <ElInput placeholder="商品名称" v-model="formData.good_name" />
-      </ElFormItem>
-
-      <ElFormItem label="商品图片" prop="good_info_img">
-        <ImageUpload />
-      </ElFormItem>
-
       <ElFormItem>
         <div class="w-full flex justify-end">
           <ElButton type="primary" @click="handleConfirm">保存</ElButton>

+ 3 - 33
src/views/parameter/good/cpns/ladder-table.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-// import { goodTypeOptions } from "../config/_options";
 import { useRenderIcon } from "/@/components/ReIcon/src/hooks";
 
 const emit = defineEmits(["choose", "delete", "update"]);
@@ -12,42 +11,13 @@ defineProps<{
 
 <template>
   <ElTable size="small" border :data="ladder">
-    <ElTableColumn prop="name" label="商品阶梯">
+    <ElTableColumn prop="name" label="顺序">
       <template #="{ $index }">
         {{ $index + 1 }}
       </template>
     </ElTableColumn>
-    <!-- 
-    <ElTableColumn prop="good_type" label="商品类型">
-      <template #="{ row }">
-        <ElTag>{{
-          goodTypeOptions.find(({ id }) => id === row.good_type)?.label || "--"
-        }}</ElTag>
-      </template>
-    </ElTableColumn> -->
-    <ElTableColumn prop="budget_price" label="预算单价" />
-
-    <ElTableColumn prop="num" label="购买数量" />
-
-    <ElTableColumn prop="cat_name" label="商品分类" width="280">
-      <template #="{ row }">
-        {{ row.cat_info.map(({ name }) => name).join("_") }}
-      </template>
-    </ElTableColumn>
-
-    <ElTableColumn prop="good_img" label="图片">
-      <template #="{ row }">
-        <ElImage
-          v-if="row.good_img"
-          style="width: 20px; height: 20px"
-          :preview-src-list="[row.good_img]"
-          preview-teleported=""
-        />
-      </template>
-    </ElTableColumn>
-
-    <ElTableColumn prop="good_name" label="商品名称" />
-
+    <ElTableColumn prop="key" label="类型" />
+    <ElTableColumn prop="value" label="类型值" />
     <ElTableColumn v-if="!readonly">
       <template #header>
         <div class="w-full flex justify-between">

+ 10 - 79
src/views/parameter/good/cpns/project-form.vue

@@ -7,13 +7,9 @@ import { httpDetail } from "/@/api/parameter/good";
 import { BasicForm } from "/@/components/BasicForm";
 import LadderModal from "./ladder-modal.vue";
 import LadderTable from "./ladder-table.vue";
-import { ImageUpload } from "/@/components/Upload";
-import { ImageUploadList } from "/@/components/UploadList";
 // import SearchTerrace from "/@/components/SearchTerrace";
 import { Unit } from "/@/components/RemoteSelect";
 import { transform, createDefaultData } from "/@/components/BasicForm";
-import { Customer } from "/@/components/RemoteSelect";
-// import { AmountInput } from "/@/components/Input";
 import { useResponseHandle } from "/@/hooks/useAsync";
 
 const emit = defineEmits(["create"]);
@@ -26,97 +22,33 @@ const props = defineProps<{
 
 const loading = ref(false);
 const { formItems } = projectFormConfig;
-console.log(formItems);
 
 const responseHandle = useResponseHandle();
 const basicFormRef = ref<InstanceType<typeof ElForm>>(null);
 const formData = ref<Record<string, any>>(createDefaultData(formItems));
-console.log(formData);
 const ladderModalRef = ref<InstanceType<typeof LadderModal>>(null);
 
-function requesetCategoryById(id: string) {
-  const transform = ({ cat_name, ...rest }: any) => ({
-    ...rest,
-    name: cat_name
-  });
-  return new Promise(resolve => {
-    httpDetail({ id }).then(({ code, message, data }) => {
-      responseHandle({
-        code,
-        message,
-        handler: () => resolve(transform(data))
-      });
-    });
-  });
-}
-
-async function ladderTransform(ladder) {
-  loading.value = true;
-  const { ladder: _ladder } = formData.value;
-  const tasks = ladder.cat_info.map(async id => await requesetCategoryById(id));
-  ladder.cat_info = await Promise.all(tasks);
-  loading.value = false;
-  return ladder;
-}
-
 async function handlePush(_ladder) {
-  const ladder = await ladderTransform(_ladder);
-  if (!Array.isArray(formData.value.ladder)) {
-    formData.value.ladder = [];
-  }
-  formData.value.ladder.push(ladder);
+  formData.value.good_param.push(unref(_ladder));
 }
 
 async function handleUpdate(_ladder, index) {
-  const ladder = await ladderTransform(_ladder);
-  formData.value.ladder[index] = ladder;
-}
-
-function disabledDate(date) {
-  return date.getTime() < new Date().getTime() - 86400000;
-}
-
-function handleDateChange(prop: string) {
-  const { arrtime, endtime } = formData.value;
-  const start = new Date(arrtime).valueOf();
-  const end = new Date(endtime).valueOf();
-  if (start > end) {
-    formData.value[prop] = "";
-    ElMessage.warning(`竞价截止时间不能大于要求到货时间!`);
-  }
+  formData.value.good_param[index] = _ladder;
 }
 
 function handleCreate() {
-  console.log(formData.value);
   basicFormRef.value.validate(isValid => {
     if (!isValid) return;
-    // const { ladder, ...rest } = unref(formData);
-    // const transform = ladder => {
-    //   return {
-    //     ...(ladder.good_img ? { good_img: ladder.good_img } : {}),
-    //     ...{
-    //       budget_price: ladder.budget_price,
-    //       good_name: ladder.good_name,
-    //       good_type: ladder.good_type,
-    //       num: ladder.num
-    //     }
-    //   };
-    // };
-
-    // const params = {
-    //   ...rest,
-    //   ladder: ladder.map(transform)
-    // };
-
-    // emit("create", params);
+    const params = unref(formData);
+    emit("create", params);
   });
 }
-
 watchEffect(() => {
   const { readonly, data } = props;
   if (readonly && !data) {
     return;
   }
+  formData.value = transform(formItems, data, {});
 });
 </script>
 
@@ -135,14 +67,13 @@ watchEffect(() => {
       </template>
 
       <template #good_param>
-        111 先展示
-        <!-- <LadderTable
+        <LadderTable
           :readonly="readonly"
           :ladder="formData.good_param"
           @choose="() => ladderModalRef.onDisplay()"
           @update="({ data, index }) => ladderModalRef.onDisplay(data, index)"
-          @delete="index => formData.ladder.splice(index, 1)"
-        /> -->
+          @delete="index => formData.good_param.splice(index, 1)"
+        />
       </template>
 
       <template #footer>
@@ -152,10 +83,10 @@ watchEffect(() => {
       </template>
     </BasicForm>
 
-    <!-- <LadderModal
+    <LadderModal
       ref="ladderModalRef"
       @update="handleUpdate"
       @push="handlePush"
-    /> -->
+    />
   </ElScrollbar>
 </template>

+ 2 - 28
src/views/parameter/good/detail.vue

@@ -52,7 +52,8 @@ function initalData() {
     return;
   }
 
-  project(httpDetail({ projectNo: id.value }));
+  project(httpDetail({ id: id.value }));
+  console.log(projectData);
   // feedback(httpCommodityFeedback({ projectNo: id.value }));
 }
 
@@ -72,34 +73,7 @@ initalData();
             />
           </ElCollapseItem>
         </ElCollapse>
-
-        <template v-if="isDetail" />
       </ElTabPane>
-
-      <template v-if="isDetail">
-        <!-- <ElTabPane label="商品反馈详情" v-loading="feedbackLoading">
-          <CommodityFeedback :feedback="feedbackData" />
-        </ElTabPane>
-
-        <ElTabPane
-          v-if="schemeStatus.includes(projectData.status)"
-          label="方案制作"
-        >
-          <SchemePlans
-            :id="id"
-            :feedback="feedbackData"
-            :project="projectData"
-          />
-        </ElTabPane> -->
-
-        <ElTabPane label="审批记录">
-          <!-- <ApprovalRecord :orderCode="id" :type="'PRO'" /> -->
-        </ElTabPane>
-
-        <ElTabPane label="流程图">
-          <!-- <FlowChart processId="14" :orderCode="id" type="PRO" /> -->
-        </ElTabPane>
-      </template>
     </ElTabs>
   </PgaeDetail>
 </template>

+ 1 - 1
src/views/parameter/good/index.vue

@@ -22,7 +22,7 @@ const hooks: Hooks = {
 
 const events: Events = {
   content: {
-    preview: ({ goodNo }) => push(`${basePath}?id=${goodNo}`),
+    preview: ({ id }) => push(`${basePath}?id=${id}`),
     create: () => push(basePath)
   }
 };