瀏覽代碼

feat(upload): 优化文件上传功能并添加宽高比校验

- 修改了多个组件中的文件上传逻辑,增加了宽高比校验功能
- 优化了上传进度显示和错误处理
- 调整了部分组件的接口调用方式
- 重构了某些组件的结构以支持新功能
zhangtao 2 天之前
父節點
當前提交
2c36bf4695

+ 4 - 4
.env.development

@@ -8,15 +8,15 @@ VITE_PUBLIC_PATH = /
 
 # 跨域代理,您可以配置多个 ,请注意,没有换行符
 # VITE_PROXY = [["/jeecgboot","http://192.168.1.34:8080/jeecg-boot"],["/upload","http://192.168.1.34:8080/jeecg-boot"]]
-# VITE_PROXY = [["/jeecgboot","http://192.168.0.11:8080/jeecg-boot"],["/upload","http://192.168.0.11:8080/upload"]]
+VITE_PROXY = [["/jeecgboot","http://192.168.0.11:8080/jeecg-boot"],["/upload","http://192.168.0.11:8080/upload"]]
 # VITE_PROXY = [["/jeecgboot","http://192.168.1.253:8080/jeecg-boot"],["/upload","http://192.168.1.253:8080/upload"]]
-VITE_PROXY = [["/jeecgboot","http://192.168.1.166:8080/jeecg-boot"],["/upload","http://192.168.1.166:8080/upload"]]
+# VITE_PROXY = [["/jeecgboot","http://192.168.1.166:8080/jeecg-boot"],["/upload","http://192.168.1.166:8080/upload"]]
 
 #后台接口全路径地址(必填)
 # VITE_GLOB_DOMAIN_URL=http://192.168.1.34:8080/jeecg-boot #//黄、
-# VITE_GLOB_DOMAIN_URL=http://192.168.0.11:8080/jeecg-boot  #李
+VITE_GLOB_DOMAIN_URL=http://192.168.0.11:8080/jeecg-boot  #李
 # VITE_GLOB_DOMAIN_URL=http://192.168.1.253:8080/jeecg-boot  #张
-VITE_GLOB_DOMAIN_URL=http://192.168.1.166:8080/jeecg-boot  #张
+# VITE_GLOB_DOMAIN_URL=http://192.168.1.166:8080/jeecg-boot  #张
 
 
 #后台接口父地址(必填)

+ 2 - 1
src/api/sys/upload.ts

@@ -14,7 +14,8 @@ export function uploadApi(params: UploadFileParams, onUploadProgress: (progressE
       url: `${uploadUrl}/sys/common/upload`,
       onUploadProgress,
     },
-    params
+    params,
+    { isReturnResponse: true }
   );
 }
 /**

+ 50 - 0
src/components/Form/src/jeecg/components/JImageUpload.vue

@@ -94,6 +94,21 @@
         required: false,
         default: '',
       },
+      isProportion: {
+        type: Boolean,
+        required: false,
+        default: false,
+      },
+      aspectRatioW: {
+        type: Number,
+        required: false,
+        default: 1,
+      },
+      aspectRatioH: {
+        type: Number,
+        required: false,
+        default: 1,
+      },
     },
     emits: ['options-change', 'change', 'update:value'],
     setup(props, { emit, refs }) {
@@ -187,6 +202,41 @@
           createMessage.info('请上传图片');
           return false;
         }
+        if (props.isProportion) {
+          // 优先使用 aspectRatioW 和 aspectRatioH 参数(例如 5:4)
+          // 如果未设置,则使用 aspectRatio 参数(例如 1.25)
+          let targetRatio;
+          let ratioDescription;
+
+          if (props.aspectRatioW > 0 && props.aspectRatioH > 0) {
+            targetRatio = props.aspectRatioW / props.aspectRatioH;
+            ratioDescription = `${props.aspectRatioW}:${props.aspectRatioH}`;
+          } else {
+            // 如果没有设置有效的宽高比参数,则不进行校验
+            return true;
+          }
+          return new Promise((resolve, reject) => {
+            const img = new Image();
+            img.src = URL.createObjectURL(file);
+            img.onload = () => {
+              const { width, height } = img;
+              const ratio = width / height;
+              // 允许一定的误差范围(0.01)以处理浮点数精度问题
+              if (Math.abs(ratio - targetRatio) > 0.01) {
+                createMessage.error(`请上传宽高比为 ${ratioDescription} 的图片`);
+                reject(false);
+              } else {
+                resolve(true);
+              }
+            };
+            img.onerror = () => {
+              createMessage.error('图片加载失败');
+              reject(false);
+            };
+          }).catch(() => {
+            return false;
+          });
+        }
       }
       /**
        * 文件上传结果回调

+ 2 - 0
src/components/Form/src/jeecg/components/JUpload/JUpload.vue

@@ -256,6 +256,8 @@
       createMessage.warning('文件格式不对');
       return false;
     }
+    console.log(file, '撒大声地');
+
     // 扩展 beforeUpload 验证
     if (typeof props.beforeUpload === 'function') {
       return props.beforeUpload(file);

+ 27 - 8
src/components/uploadVideo/index.vue

@@ -3,29 +3,39 @@
     <Upload v-if="!videoUrl" :beforeUpload="beforeUpload" :fileList="[]" :showUploadList="false" accept="video/*">
       <Button type="primary">上传视频</Button>
     </Upload>
-
     <div v-else class="flex items-center">
       <video :src="videoUrl" controls class="w-200px h-200px mb-3"></video>
       <div class="actions">
         <Button type="link" @click="removeVideo">删除</Button>
       </div>
     </div>
+    <a-progress :percent="percent" v-if="!videoUrl && isUpload" />
   </div>
 </template>
 
 <script setup lang="ts">
-  import { ref } from 'vue';
+  import { computed, ref } from 'vue';
   import { Upload, Button, message } from 'ant-design-vue';
   import { uploadApi } from '@/api/sys/upload';
+  import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
   const props = defineProps<{
-    modelValue: File | null;
+    modelValue: string | null | undefined;
   }>();
-
+  const isUpload = ref(false);
+  const percent = ref(0);
   const emit = defineEmits<{
     (e: 'update:modelValue', file: File | null): void;
   }>();
 
-  const videoUrl = ref<string | null>(null);
+  const videoUrl = computed({
+    get() {
+      if (props.modelValue) return props.modelValue;
+      return null;
+    },
+    set(val) {
+      return val;
+    },
+  });
 
   const beforeUpload = async (file: File) => {
     // 验证文件类型
@@ -41,12 +51,21 @@
       message.error('视频大小不能超过100MB');
       return false;
     }
-    const res = await uploadApi({ file });
-    console.log(res, '上传文件');
+    try {
+      isUpload.value = true;
+      const res = await uploadApi({ file }, (progressEvent: ProgressEvent) => {
+        console.log(progressEvent);
+        percent.value = Math.round((progressEvent.loaded / progressEvent.total) * 100);
+      });
+      emit('update:modelValue', getFileAccessHttpUrl(res.message));
+
+      isUpload.value = false;
+    } catch (error) {
+      isUpload.value = false;
+    }
 
     // 创建本地预览链接
     videoUrl.value = URL.createObjectURL(file);
-    emit('update:modelValue', file);
 
     return false; // 禁止自动上传
   };

+ 38 - 38
src/utils/common/compUtils.ts

@@ -2,18 +2,19 @@ import { useGlobSetting } from '/@/hooks/setting';
 import { merge, random } from 'lodash-es';
 import { isArray } from '/@/utils/is';
 import { FormSchema } from '/@/components/Form';
-import { reactive } from "vue";
-import { getTenantId, getToken } from "/@/utils/auth";
-import { useUserStoreWithOut } from "/@/store/modules/user";
+import { reactive } from 'vue';
+import { getTenantId, getToken } from '/@/utils/auth';
+import { useUserStoreWithOut } from '/@/store/modules/user';
 import dayjs from 'dayjs';
 import Big from 'big.js';
 
-import { Modal } from "ant-design-vue";
-import { defHttp } from "@/utils/http/axios";
-import { useI18n } from "@/hooks/web/useI18n";
+import { Modal } from 'ant-design-vue';
+import { defHttp } from '@/utils/http/axios';
+import { useI18n } from '@/hooks/web/useI18n';
 
 const globSetting = useGlobSetting();
 const baseApiUrl = globSetting.domainUrl;
+
 /**
  *  获取文件服务访问路径
  * @param fileUrl 文件路径
@@ -350,37 +351,37 @@ export function stringIsNull(str) {
  * @param node
  */
 export function getAutoScrollContainer(node: HTMLElement) {
-  let element: Nullable<HTMLElement> = node
+  let element: Nullable<HTMLElement> = node;
   while (element != null) {
     if (element.classList.contains('scrollbar__view')) {
       // 判断是否有滚动条
       if (element.clientHeight < element.scrollHeight) {
         // 有滚动条时,挂载到父级,解决滚动问题
-        return node.parentElement
+        return node.parentElement;
       } else {
         // 无滚动条时,挂载到body上,解决下拉框遮盖问题
-        return document.body
+        return document.body;
       }
     } else {
-      element = element.parentElement
+      element = element.parentElement;
     }
   }
   // 不在弹窗内,走默认逻辑
-  return node.parentElement
+  return node.parentElement;
 }
 
 /**
  * 判断子菜单是否全部隐藏
  * @param menuTreeItem
  */
-export  function checkChildrenHidden(menuTreeItem){
+export function checkChildrenHidden(menuTreeItem) {
   //是否是聚合路由
-  let alwaysShow=menuTreeItem.alwaysShow;
-  if(alwaysShow){
+  let alwaysShow = menuTreeItem.alwaysShow;
+  if (alwaysShow) {
     return false;
   }
-  if(!menuTreeItem.children){
-    return false
+  if (!menuTreeItem.children) {
+    return false;
   }
   return menuTreeItem.children?.find((item) => item.hideMenu == false) != null;
 }
@@ -462,7 +463,7 @@ export function replaceUserInfoByExpression(expression: string | any[]) {
     return expression;
   }
   const isString = typeof expression === 'string';
-  const isArray = Array.isArray(expression)
+  const isArray = Array.isArray(expression);
   if (!isString && !isArray) {
     return expression;
   }
@@ -486,26 +487,26 @@ export function replaceUserInfoByExpression(expression: string | any[]) {
 
 /**
  * 设置租户缓存,当租户退出的时候
- * 
+ *
  * @param tenantId
  */
-export async function userExitChangeLoginTenantId(tenantId){
+export async function userExitChangeLoginTenantId(tenantId) {
   const userStore = useUserStoreWithOut();
   //step 1 获取用户租户
-  const url = '/sys/tenant/getCurrentUserTenant'
+  const url = '/sys/tenant/getCurrentUserTenant';
   let currentTenantId = null;
   const data = await defHttp.get({ url });
-  if(data && data.list){
+  if (data && data.list) {
     let arr = data.list;
-    if(arr.length>0){
+    if (arr.length > 0) {
       //step 2.判断当前id是否存在用户租户中
       let filterTenantId = arr.filter((item) => item.id == tenantId);
       //存在说明不是退出的不是当前租户,还用用来的租户即可
-      if(filterTenantId && filterTenantId.length>0){
+      if (filterTenantId && filterTenantId.length > 0) {
         currentTenantId = tenantId;
-      }else{
+      } else {
         //不存在默认第一个
-        currentTenantId = arr[0].id
+        currentTenantId = arr[0].id;
       }
     }
   }
@@ -514,7 +515,7 @@ export async function userExitChangeLoginTenantId(tenantId){
 
   //update-begin---author:wangshuai---date:2023-11-07---for:【QQYUN-7005】退租户,判断退出的租户ID与当前租户ID一致,再刷新---
   //租户为空,说明没有租户了,需要刷新页面。或者当前租户和退出的租户一致则需要刷新浏览器
-  if(!currentTenantId || tenantId == loginTenantId){
+  if (!currentTenantId || tenantId == loginTenantId) {
     window.location.reload();
   }
   //update-end---author:wangshuai---date:2023-11-07---for:【QQYUN-7005】退租户,判断退出的租户ID与当前租户ID一致,再刷新---
@@ -522,20 +523,20 @@ export async function userExitChangeLoginTenantId(tenantId){
 
 /**
  * 我的租户模块需要开启多租户提示
- * 
+ *
  * @param title 标题
  */
-export function tenantSaasMessage(title){
+export function tenantSaasMessage(title) {
   let tenantId = getTenantId();
-  if(!tenantId){
+  if (!tenantId) {
     Modal.confirm({
-      title:title,
+      title: title,
       content: '此菜单需要在多租户模式下使用,否则数据会出现混乱',
       okText: '确认',
       okType: 'danger',
       // @ts-ignore
       cancelButtonProps: { style: { display: 'none' } },
-    })
+    });
   }
 }
 
@@ -567,7 +568,6 @@ export function sameDay(dateStr) {
   }
 }
 
-
 /**
  * 翻译菜单名称
  * 2024-02-28
@@ -599,13 +599,13 @@ export function translateTitle(data) {
 export function freezeDeep(obj: Recordable | Recordable[]) {
   if (obj != null) {
     if (Array.isArray(obj)) {
-      obj.forEach(item => freezeDeep(item))
+      obj.forEach((item) => freezeDeep(item));
     } else if (typeof obj === 'object') {
-      Object.values(obj).forEach(value => {
-        freezeDeep(value)
-      })
+      Object.values(obj).forEach((value) => {
+        freezeDeep(value);
+      });
     }
-    Object.freeze(obj)
+    Object.freeze(obj);
   }
-  return obj
+  return obj;
 }

+ 5 - 0
src/views/businessManagement/courses/courses.api.ts

@@ -13,6 +13,7 @@ enum Api {
   Coach = '/staff/staff/queryList',
   queryCourseList = '/app/appCoursesPriceRules/queryListByCoursesId',
   editPriceRules = '/app/appCoursesPriceRules/editPriceRules',
+  updateStatus = '/app/appCourese/editRackingStatus',
 }
 export const list = (params) => defHttp.get({ url: Api.list, params });
 
@@ -66,3 +67,7 @@ export const queryCourseList = (params) => {
 export const editPriceRules = (params) => {
   return defHttp.post({ url: Api.editPriceRules, params });
 };
+
+export const updateStatus = (params) => {
+  return defHttp.put({ url: `${Api.updateStatus}?appCourseId=${params.id}&rackingStatus=${params.rackingStatus}` });
+};

+ 9 - 12
src/views/businessManagement/courses/index.vue

@@ -6,17 +6,12 @@
       <template #tableTitle>
         <a-button
           type="primary"
+          v-auth="'app:appCourese:add'"
           @click="router.push({ name: 'businessManagement-publishcourses', query: { type: 0 } })"
           preIcon="ant-design:plus-outlined"
         >
           新增</a-button
         >
-        <a-dropdown v-if="selectedRowKeys.length > 0">
-          <a-button v-auth="'courses:nm_courses:deleteBatch'"
-            >批量操作
-            <Icon icon="mdi:chevron-down"></Icon>
-          </a-button>
-        </a-dropdown>
       </template>
       <!--操作栏-->
       <template #action="{ record }">
@@ -26,7 +21,7 @@
       <template v-slot:bodyCell="{ column, record, index, text }"> </template>
       <template #price="{ record }"> {{ record.sellingPrice }}/{{ record.originalPrice }} </template>
       <template #priceType="{ record }">
-        <Switch v-model:checked="record.rackingStatus" :checked-value="0" :un-checked-value="1"></Switch>
+        <Switch v-model:checked="record.rackingStatus" :checked-value="0" :un-checked-value="1" @change="handleSwich(record)"></Switch>
       </template>
       <template #totalNum="{ record }">
         <div>{{ record.totalNum }}课时</div>
@@ -50,7 +45,7 @@
   import { useModal } from '/@/components/Modal';
   import { useListPage } from '/@/hooks/system/useListPage';
   import { columns, searchFormSchema } from './courses.data';
-  import { list, deleteOne, editPriceRules, queryCourseList } from './courses.api';
+  import { list, deleteOne, updateStatus, queryCourseList } from './courses.api';
   import { useUserStore } from '/@/store/modules/user';
   import { useMessage } from '/@/hooks/web/useMessage';
   import { useRouteTabText } from '/@/hooks/web/useRouteTab';
@@ -118,12 +113,11 @@
       {
         label: '查看',
         onClick: handleView.bind(null, record),
-        // auth: 'courses:nm_courses:edit',
       },
       {
         label: '编辑',
         onClick: handleEdit.bind(null, record),
-        // auth: 'courses:nm_courses:edit',
+        auth: 'app:appCourese:edit',
       },
     ];
   }
@@ -139,12 +133,12 @@
           confirm: handleDelete.bind(null, record),
           placement: 'topLeft',
         },
-        // auth: 'courses:nm_courses:delete',
+        auth: 'app:appCourese:delete',
       },
       {
         label: '编辑补课课表',
         onClick: handleEditCourses.bind(null, record),
-        // auth: 'courses:nm_courses:delete',
+        auth: 'app:appCourese:edit',
       },
     ];
   }
@@ -157,6 +151,9 @@
     });
   }
   useRouteTabText(['发布课程', '编辑课程', '查看课程']);
+  async function handleSwich(record) {
+    await updateStatus({ id: record.id, rackingStatus: record.rackingStatus });
+  }
 </script>
 
 <style lang="less" scoped>

+ 1 - 0
src/views/businessManagement/courses/publishcourses.vue

@@ -74,6 +74,7 @@
           ...viewDataSport.value,
           categoryId: viewDataSport.value.categoryId.split(','),
           priceRulesList: customTableData.value,
+          insureIds: viewDataSport.value.insureIds.split(','),
         });
       });
     }

+ 2 - 2
src/views/businessManagement/gymnasiumBag/gymnasiumBag.api.ts

@@ -38,9 +38,9 @@ export const queryById = (params) => {
 };
 /**
  * 营业名称
- * @param params
+ * @param params type:0是学校,1是体育馆,不传查全部
  * @returns
  */
 export const Business = (params) => {
-  return defHttp.get({ url: `${Api.Business}/${params.orgCode}` });
+  return defHttp.get({ url: `${Api.Business}?orgCode=${params.orgCode}&type=${params.type}` });
 };

+ 15 - 13
src/views/businessManagement/gymnasiumBag/index.vue

@@ -10,14 +10,14 @@
           <TypographyTitle :level="4">封面、配套保险、使用须知</TypographyTitle>
           <Divider></Divider>
         </template>
-        <template #customer="{ model, field }">
+        <template #customer="{ model }">
           <div v-for="(item, idx) in getCustomerList(model['categoryId'])" :key="item.value">
             <Card class="my-4">
               <FormItem :label="`${item.label}场地`" required :labelCol="{ xl: 2, sm: 3 }">
                 <InputNumber addon-before="共有" addon-after="个球场" v-model:value="model['inventory' + idx]" :max="30" :min="1"></InputNumber>
               </FormItem>
               <FormItem label="时间段及费用" required :labelCol="{ xl: 2, sm: 3 }" :wrapper-col="{ span: 22 }">
-                <ZtCustomTable :tableColumn="ScheduleArrangementColums" v-model:value="model[item.value]"> </ZtCustomTable>
+                <ZtCustomTable :show-action="isMerchant" :tableColumn="ScheduleArrangementColums" v-model:value="model[item.value]"> </ZtCustomTable>
               </FormItem>
             </Card>
           </div>
@@ -38,6 +38,7 @@
   </div>
 </template>
 <script lang="ts" setup name="business-management-gymnasiumbag">
+  import type { UserInfo } from '/#/store';
   import { TypographyTitle, Divider, InputNumber, FormItem, Card, message } from 'ant-design-vue';
   import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
   import { getSprotProject, siteAdd } from '/@/api/common/api';
@@ -45,13 +46,11 @@
   import ZtCustomTable from '/@/components/ZtCustomTable/index.vue';
   import { ScheduleArrangementColums, apiForm, priceRules } from './gymnasiumBag.data';
   import { saveOrUpdate, queryById, Business } from './gymnasiumBag.api';
-  import { computed, h, onUnmounted, ref, watch } from 'vue';
+  import { computed, ref } from 'vue';
   import { OriginalItem } from '/#/utils';
   import { areAllItemsAllFieldsFilled, extractRefs } from '/@/utils';
-  import dayjs from 'dayjs';
   import { useTabs } from '/@/hooks/web/useTabs';
   import { storeToRefs } from 'pinia';
-  import { unref } from 'vue';
   const projectList = ref<DemoOptionsItem[]>([]);
   import { useUserStore } from '/@/store/modules/user';
   const { userInfo } = storeToRefs(useUserStore());
@@ -59,7 +58,7 @@
   const isSubmit = ref(false);
   const uploadId = ref<any>();
   const isMerchant = computed(() => {
-    return userInfo.value?.orgCode.length > 3;
+    return (userInfo.value as UserInfo).orgCode.length > 3;
   });
   const changeData = ref(false);
   const formSchema: FormSchema[] = [
@@ -196,7 +195,7 @@
       },
     },
   ];
-  const [registerForm, { setProps, resetFields, setFieldsValue, updateSchema, validate, getFieldsValue, appendSchemaByField }] = useForm({
+  const [registerForm, { setFieldsValue, updateSchema, validate, getFieldsValue, appendSchemaByField }] = useForm({
     schemas: formSchema,
     showActionButtonGroup: false,
   });
@@ -239,13 +238,16 @@
     }
   }
   async function getBusinessData() {
-    const res = await Business({ orgCode: userInfo.value?.orgCode });
+    const res = await Business({ orgCode: userInfo.value?.orgCode, type: 1 });
     updateSchema({ field: 'name', componentProps: { options: res.map((it) => ({ label: it.name, value: it.id })) } });
-    //如果商家端进入默认取第一个
-    setFieldsValue({
-      name: res[0].id,
-    });
-    getQueryData(res[0].id);
+
+    if (isMerchant.value) {
+      //如果商家端进入默认取第一个
+      setFieldsValue({
+        name: res[0].id,
+      });
+      getQueryData(res[0].id);
+    }
   }
   getBusinessData();
   async function save() {

+ 3 - 4
src/views/businessManagement/gymnasiumNoFixed/index.vue

@@ -1,7 +1,7 @@
 <template>
   <BasicTable @register="registerTable">
     <template #tableTitle>
-      <a-button type="primary" preIcon="ant-design:plus-outlined" @click="handleAdd"> 新增</a-button>
+      <a-button type="primary" v-auth="'app:appSitePlace:addUnfixed'" preIcon="ant-design:plus-outlined" @click="handleAdd"> 新增</a-button>
       <a-dropdown>
         <template #overlay>
           <a-menu>
@@ -96,12 +96,11 @@
       {
         label: '查看',
         onClick: handleView.bind(null, record),
-        // auth: 'courses:nm_courses:edit',
       },
       {
         label: '编辑',
         onClick: handleEdit.bind(null, record),
-        // auth: 'courses:nm_courses:edit',
+        auth: 'app:appSitePlace:updateUnfixed',
       },
       {
         label: '删除',
@@ -110,7 +109,7 @@
           confirm: handleDelete.bind(null, record),
           placement: 'topLeft',
         },
-        // auth: 'courses:nm_courses:edit',
+        auth: 'app:appSitePlace:deleteUnfixed',
       },
     ];
   }

+ 6 - 7
src/views/businessManagement/schoolOpen/index.vue

@@ -36,9 +36,8 @@
   import ZtCustomTable from '/@/components/ZtCustomTable/index.vue';
   import { useUserStore } from '/@/store/modules/user';
   import { formSchema, ScheduleArrangementColums } from './schoolOpen.data';
-  import { getDetails } from './schoolOpen.api';
-  import { useShopInfoStore } from '/@/store/modules/shopInfo';
-  import { onUnmounted, ref, unref } from 'vue';
+  import { getDetails, saveOrUpdate } from './schoolOpen.api';
+  import { ref, unref } from 'vue';
   import { useRouter } from 'vue-router';
   const router = useRouter();
   const [registerForm, { setProps, resetFields, setFieldsValue, updateSchema, validate, clearValidate, getFieldsValue }] = useForm({
@@ -78,7 +77,7 @@
     try {
       await saveOrUpdate(newObj);
       isSubmit.value = false;
-      back();
+      getData();
     } catch (error) {
       console.log(error);
       isSubmit.value = false;
@@ -87,8 +86,10 @@
   }
   async function getData() {
     const res = await getDetails({ orgCode: useUserStore().userInfo?.orgCode });
+    if (!res.teachingDay) return;
     setFieldsValue({
       ...res,
+      insureIds: res.insureIds.split(','),
       noTeachingDay: res.noTeachingDay
         ? JSON.parse(res.noTeachingDay).data.map((it) => {
             return { ...it, time: [it.startTime, it.endTime] };
@@ -101,9 +102,7 @@
     console.log(JSON.parse(res.noTeachingDay));
   }
   getData();
-  onUnmounted(() => {
-    useShopInfoStore().isShowSelect = false;
-  });
+
   function handleClick() {
     router.push({ path: '/informationManagement/teachorNoteach' });
   }

+ 7 - 11
src/views/businessManagement/schoolOpen/schoolOpen.data.ts

@@ -1,22 +1,18 @@
-import { storeToRefs } from 'pinia';
-import { ZtTableColumnProps } from '/#/utils';
 import { BasicColumn, FormSchema } from '/@/components/Table';
-import { useShopInfoStore } from '/@/store/modules/shopInfo';
 import { getInsureList } from '/@/api/common/api';
-const { deptList } = storeToRefs(useShopInfoStore());
+import { getUserDeparts } from '/@/views/system/depart/depart.api';
 export const formSchema: FormSchema[] = [
   {
     field: 'tenantId',
     label: '营业名称',
-    component: 'Select',
+    component: 'ApiSelect',
     required: true,
     labelWidth: 120,
     componentProps: {
-      options: deptList,
-      fieldNames: {
-        label: 'departName',
-        value: 'id',
-      },
+      api: getUserDeparts,
+      labelField: 'departName',
+      valueField: 'id',
+      resultField: 'list',
     },
     colProps: {
       span: 14,
@@ -76,7 +72,7 @@ export const formSchema: FormSchema[] = [
     },
   },
   {
-    field: 'insurance',
+    field: 'insureIds',
     label: '配套保险',
     component: 'ApiSelect',
     componentProps: {

+ 4 - 3
src/views/informationManagement/shopInfo/index.vue

@@ -74,8 +74,8 @@
     isEdit.value = true;
     setFieldsValue({
       ...res,
-      categoryId: res.categoryId.split(','),
-      Time: [res.startTime, res.endTime].join(','),
+      categoryId: res.categoryId ? res.categoryId.split(',') : null,
+      Time: res.Time ? [res.startTime, res.endTime].join(',') : null,
       down: vr ? vr[vr.length - 1] : null,
       up: vr ? vr[4] : null,
       before: vr ? vr[0] : null,
@@ -89,6 +89,8 @@
     await validate();
     isLoading.value = true;
     const form = await getFieldsValue();
+    console.log(form, 'av');
+
     const obj = {
       ...form,
       startTime: form.Time ? form.Time.split(',')[0] : '',
@@ -99,7 +101,6 @@
       if (!form.before || !form.after || !form.left || !form.right || !form.up || !form.down) return message.error('请上传完整VR实景');
       obj.vr = [form.before, form.after, form.left, form.right, form.up, form.down].join(',');
     }
-    console.log(obj, '测试');
     try {
       await saveOrUpdate(obj, isEdit.value);
       getData(userInfo.value?.orgCode);

+ 26 - 7
src/views/informationManagement/shopInfo/shopInfo.data.ts

@@ -216,7 +216,10 @@ export const formSchema: FormSchema[] = [
     component: 'JImageUpload',
     required: true,
     componentProps: {
-      tipText: '支持单张上传;宽高比为5:4,且宽高均大于480px,大小5M以内。',
+      tipText: '最多支持10张;宽高比为5:4,且宽高均大于480px,大小5M以内。',
+      aspectRatioW: 5,
+      aspectRatioH: 4,
+      isProportion: true,
     },
   },
   {
@@ -235,7 +238,8 @@ export const formSchema: FormSchema[] = [
     component: 'JImageUpload',
     colProps: { xl: 12 },
     componentProps: {
-      tipText: '支持单张上传;宽高比为5:4,且宽高均大于480px,大小5M以内。',
+      isProportion: true,
+      tipText: '支持单张上传;宽高比为1:1,大小5M以内。',
     },
     ifShow(renderCallbackParams) {
       return renderCallbackParams.model.type == 1;
@@ -247,7 +251,10 @@ export const formSchema: FormSchema[] = [
     component: 'JImageUpload',
     colProps: { xl: 12 },
     componentProps: {
-      tipText: '支持单张上传;宽高比为5:4,且宽高均大于480px,大小5M以内。',
+      isProportion: true,
+      tipText: '支持单张上传;宽高比为1:1,大小5M以内。',
+      aspectRatioW: 1,
+      aspectRatioH: 1,
     },
     ifShow(renderCallbackParams) {
       return renderCallbackParams.model.type == 1;
@@ -259,7 +266,10 @@ export const formSchema: FormSchema[] = [
     component: 'JImageUpload',
     colProps: { xl: 12 },
     componentProps: {
-      tipText: '支持单张上传;宽高比为5:4,且宽高均大于480px,大小5M以内。',
+      isProportion: true,
+      tipText: '支持单张上传;宽高比为1:1,大小5M以内。',
+      aspectRatioW: 1,
+      aspectRatioH: 1,
     },
     ifShow(renderCallbackParams) {
       return renderCallbackParams.model.type == 1;
@@ -270,7 +280,10 @@ export const formSchema: FormSchema[] = [
     label: '图片(右)',
     component: 'JImageUpload',
     componentProps: {
-      tipText: '支持单张上传;宽高比为5:4,且宽高均大于480px,大小5M以内。',
+      isProportion: true,
+      tipText: '支持单张上传;宽高比为1:1,大小5M以内。',
+      aspectRatioW: 1,
+      aspectRatioH: 1,
     },
     colProps: { xl: 12 },
     ifShow(renderCallbackParams) {
@@ -282,7 +295,10 @@ export const formSchema: FormSchema[] = [
     label: '图片(上)',
     component: 'JImageUpload',
     componentProps: {
-      tipText: '支持单张上传;宽高比为5:4,且宽高均大于480px,大小5M以内。',
+      isProportion: true,
+      tipText: '支持单张上传;宽高比为1:1,大小5M以内。',
+      aspectRatioW: 1,
+      aspectRatioH: 1,
     },
     colProps: { xl: 12 },
     ifShow(renderCallbackParams) {
@@ -294,7 +310,10 @@ export const formSchema: FormSchema[] = [
     label: '图片(下)',
     component: 'JImageUpload',
     componentProps: {
-      tipText: '支持单张上传;宽高比为5:4,且宽高均大于480px,大小5M以内。',
+      isProportion: true,
+      tipText: '支持单张上传;宽高比为1:1,大小5M以内。',
+      aspectRatioW: 1,
+      aspectRatioH: 1,
     },
     colProps: { xl: 12 },
     ifShow(renderCallbackParams) {

+ 3 - 1
src/views/system/staff/staff.api.ts

@@ -7,8 +7,9 @@ enum Api {
   add = '/staff/staff/add',
   edit = '/staff/staff/edit',
   queryId = '/staff/staff/queryById',
-  del = 'staff/staff/delete',
+  del = '/staff/staff/delete',
   test = '/sys/sysDepart/findByDepTree',
+  updateStatus = '/staff/staff/updateStatus',
 }
 export const getList = (params) => defHttp.get({ url: Api.list, params });
 
@@ -27,3 +28,4 @@ export const queryById = (id) => defHttp.get({ url: Api.queryId, params: { id }
 export const del = (params) => defHttp.delete({ url: Api.del, params }, { joinParamsToUrl: true });
 
 export const test = (params) => defHttp.get({ url: Api.test, params });
+export const updateStatus = (params) => defHttp.put({ url: Api.updateStatus, params });

+ 16 - 0
src/views/system/staff/staff.data.ts

@@ -1,6 +1,9 @@
+import { Switch } from 'ant-design-vue';
 import { getDepListData } from '/@/api/common/api';
 import { BasicColumn } from '/@/components/Table';
 import { FormSchema } from '/@/components/Table';
+import { h } from 'vue';
+import { updateStatus } from './staff.api';
 
 export const columns: BasicColumn[] = [
   {
@@ -23,6 +26,19 @@ export const columns: BasicColumn[] = [
     title: '用户状态',
     dataIndex: 'status',
     width: 100,
+    customRender: ({ record }) => {
+      return h(Switch, {
+        unCheckedValue: 0,
+        checkedValue: 1,
+        checked: record.status,
+        checkedChildren: '正常',
+        unCheckedChildren: '冻结',
+        async onChange(e) {
+          record.status = e;
+          await updateStatus({ status: e, id: record.id });
+        },
+      });
+    },
   },
   {
     title: '创建时间',