Forráskód Böngészése

Merge branch 'dev' of https://git.citupro.com/zhengnaiwen_citu/menduner-admin into dev

lifanagju_citu 6 hónapja
szülő
commit
f83b226a1f

+ 1 - 0
package.json

@@ -34,6 +34,7 @@
     "@vueuse/core": "^10.9.0",
     "@wangeditor/editor": "^5.1.23",
     "@wangeditor/editor-for-vue": "^5.1.10",
+    "@wangeditor/plugin-upload-attachment": "^1.1.0",
     "@zxcvbn-ts/core": "^3.0.4",
     "animate.css": "^4.1.1",
     "axios": "^1.6.8",

+ 29 - 0
pnpm-lock.yaml

@@ -32,6 +32,9 @@ importers:
       '@wangeditor/editor-for-vue':
         specifier: ^5.1.10
         version: 5.1.12(@wangeditor/editor@5.1.23)(vue@3.4.21(typescript@5.3.3))
+      '@wangeditor/plugin-upload-attachment':
+        specifier: ^1.1.0
+        version: 1.1.0(@uppy/core@2.3.4)(@wangeditor/editor@5.1.23)(snabbdom@3.6.2)
       '@zxcvbn-ts/core':
         specifier: ^3.0.4
         version: 3.0.4
@@ -2058,6 +2061,13 @@ packages:
       slate: ^0.72.0
       snabbdom: ^3.1.0
 
+  '@wangeditor/plugin-upload-attachment@1.1.0':
+    resolution: {integrity: sha512-K6SsV3Cv1g+Ob1xjRRQ13Sh3lcj3yAa/aXMaKKbaPI76rNZiOpyAGH/iVv5i9enmwbZql01IXpvhK+HtrikVyQ==}
+    peerDependencies:
+      '@uppy/core': ^2.1.5
+      '@wangeditor/editor': '>=5.1.16'
+      snabbdom: ^3.3.1
+
   '@wangeditor/table-module@1.1.4':
     resolution: {integrity: sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==}
     peerDependencies:
@@ -2717,6 +2727,9 @@ packages:
   dom7@3.0.0:
     resolution: {integrity: sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==}
 
+  dom7@4.0.6:
+    resolution: {integrity: sha512-emjdpPLhpNubapLFdjNL9tP06Sr+GZkrIHEXLWvOGsytACUrkbeIdjO5g77m00BrHTznnlcNqgmn7pCN192TBA==}
+
   domelementtype@1.3.1:
     resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==}
 
@@ -4612,6 +4625,9 @@ packages:
   ssr-window@3.0.0:
     resolution: {integrity: sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA==}
 
+  ssr-window@4.0.2:
+    resolution: {integrity: sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ==}
+
   stable@0.1.8:
     resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==}
     deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility'
@@ -7355,6 +7371,13 @@ snapshots:
       slate: 0.72.8
       snabbdom: 3.6.2
 
+  '@wangeditor/plugin-upload-attachment@1.1.0(@uppy/core@2.3.4)(@wangeditor/editor@5.1.23)(snabbdom@3.6.2)':
+    dependencies:
+      '@uppy/core': 2.3.4
+      '@wangeditor/editor': 5.1.23
+      dom7: 4.0.6
+      snabbdom: 3.6.2
+
   '@wangeditor/table-module@1.1.4(@wangeditor/core@1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.7)(slate@0.72.8)(snabbdom@3.6.2))(dom7@3.0.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(nanoid@3.3.7)(slate@0.72.8)(snabbdom@3.6.2)':
     dependencies:
       '@wangeditor/core': 1.1.19(@uppy/core@2.3.4)(@uppy/xhr-upload@2.1.3(@uppy/core@2.3.4))(dom7@3.0.0)(is-hotkey@0.2.0)(lodash.camelcase@4.3.0)(lodash.clonedeep@4.5.0)(lodash.debounce@4.0.8)(lodash.foreach@4.5.0)(lodash.isequal@4.5.0)(lodash.throttle@4.1.1)(lodash.toarray@4.4.0)(nanoid@3.3.7)(slate@0.72.8)(snabbdom@3.6.2)
@@ -8068,6 +8091,10 @@ snapshots:
     dependencies:
       ssr-window: 3.0.0
 
+  dom7@4.0.6:
+    dependencies:
+      ssr-window: 4.0.2
+
   domelementtype@1.3.1: {}
 
   domelementtype@2.3.0: {}
@@ -10063,6 +10090,8 @@ snapshots:
 
   ssr-window@3.0.0: {}
 
+  ssr-window@4.0.2: {}
+
   stable@0.1.8: {}
 
   static-extend@0.1.2:

+ 4 - 0
src/api/mall/product/spu.ts

@@ -17,6 +17,9 @@ export interface Sku {
   costPrice?: number | string // 成本价
   barCode?: string // 商品条码
   picUrl?: string // 图片地址
+  extend?: {
+    fileUrls: [] // 文件地址
+  },
   stock?: number // 库存
   weight?: number // 商品重量,单位:kg 千克
   volume?: number // 商品体积,单位:m^3 平米
@@ -45,6 +48,7 @@ export interface Spu {
   specType?: boolean // 商品规格
   subCommissionType?: boolean // 分销类型
   skus?: Sku[] // sku数组
+  type: number | string // 商品类型
   description?: string // 商品详情
   sort?: number // 商品排序
   giveIntegral?: number // 赠送积分

+ 24 - 3
src/components/Editor/src/Editor.vue

@@ -7,6 +7,7 @@ import { isNumber } from '@/utils/is'
 import { ElMessage } from 'element-plus'
 import { useLocaleStore } from '@/store/modules/locale'
 import { getAccessToken, getTenantId } from '@/utils/auth'
+// import { updateFile } from '@/api/infra/file/index.ts'
 
 defineOptions({ name: 'Editor' })
 
@@ -61,7 +62,8 @@ const handleCreated = (editor: IDomEditor) => {
 
 // 编辑器配置
 import { getExcludeKeys } from './util/toolbarConfig'
-const toolbarConfig = reactive({ excludeKeys: getExcludeKeys() })
+// const toolbarConfig = reactive({  insertKeys: {index: 0, keys: ['uploadAttachment']}, excludeKeys: getExcludeKeys() })
+const toolbarConfig = reactive({  excludeKeys: getExcludeKeys() })
 
 // 编辑器配置
 const editorConfig = computed((): IEditorConfig => {
@@ -91,7 +93,7 @@ const editorConfig = computed((): IEditorConfig => {
       autoFocus: false,
       scroll: true,
       MENU_CONF: {
-        ['uploadImage']: {
+        uploadImage: {
           server: import.meta.env.VITE_UPLOAD_URL,
           // 单个文件的最大体积限制,默认为 2M
           maxFileSize: 5 * 1024 * 1024,
@@ -146,8 +148,27 @@ const editorConfig = computed((): IEditorConfig => {
           customInsert(res: any, insertFn: InsertFnType) {
             insertFn(res.data, 'image', res.data)
           }
-        }
+        },
+        // 上传附件
+        // uploadAttachment: {
+        //   allowedFileTypes: ['.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.pdf', '.txt'],
+        //   customUpload(file: File, insertFn: Function) {
+        //     let formData = new FormData()
+        //     formData.append("file", file)
+        //     const name = file.name.split('.')[0]
+        //     updateFile(formData).then(res => {
+        //       if (res.code === 0) {
+        //         insertFn(name, res.data)
+        //       }
+        //     })
+        //   }
+        // }
       },
+      // hoverbarKeys: {
+      //   attachment: {
+      //     menuKeys: ['downloadAttachment']
+      //   }
+      // },
       uploadImgShowBase64: true
     },
     props.editorConfig || {}

+ 2 - 1
src/components/UploadFile/src/UploadFile.vue

@@ -46,7 +46,7 @@ import { UploadFile } from 'element-plus/es/components/upload/src/upload'
 defineOptions({ name: 'UploadFile' })
 
 const message = useMessage() // 消息弹窗
-const emit = defineEmits(['update:modelValue'])
+const emit = defineEmits(['update:modelValue', 'clear'])
 
 const props = defineProps({
   modelValue: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired,
@@ -125,6 +125,7 @@ const excelUploadError: UploadProps['onError'] = (): void => {
 }
 // 删除上传文件
 const handleRemove = (file: UploadFile) => {
+  emit('clear', file.url)
   const index = fileList.value.map((f) => f.name).indexOf(file.name)
   if (index > -1) {
     fileList.value.splice(index, 1)

+ 4 - 0
src/main.ts

@@ -42,6 +42,10 @@ import Logger from '@/utils/Logger'
 
 import VueDOMPurifyHTML from 'vue-dompurify-html' // 解决v-html 的安全隐患
 
+// import { Boot } from '@wangeditor/editor'
+// import attachmentModule from '@wangeditor/plugin-upload-attachment'
+// Boot.registerModule(attachmentModule)
+
 // 创建实例
 const setupAll = async () => {
   const app = createApp(App)

+ 1 - 0
src/utils/dict.ts

@@ -165,6 +165,7 @@ export enum DICT_TYPE {
 
   // ========== MALL - 商品模块 ==========
   PRODUCT_SPU_STATUS = 'product_spu_status', //商品状态
+  PRODUCT_SPU_TYPE = 'product_spu_type', //商品类型
 
   // ========== MALL - 交易模块 ==========
   EXPRESS_CHARGE_MODE = 'trade_delivery_express_charge_mode', //快递的计费方式

+ 56 - 0
src/views/mall/product/spu/components/SkuList.vue

@@ -13,6 +13,12 @@
         <UploadImg v-model="row.picUrl" height="50px" width="50px" />
       </template>
     </el-table-column>
+    <el-table-column v-if="productType !== '0'" align="center" label="文件" min-width="90">
+      <template #default="{ row }">
+        <el-button v-if="row?.extend?.fileUrls?.length" type="primary" link @click.stop="handleUpload(row)">已上传</el-button>
+        <el-button v-else size="small" plain @click="handleUpload(row)">上传文件</el-button>
+      </template>
+    </el-table-column>
     <template v-if="formData!.specType && !isBatch">
       <!--  根据商品属性动态添加 -->
       <el-table-column
@@ -157,6 +163,12 @@
         />
       </template>
     </el-table-column>
+    <el-table-column v-if="productType !== '0'" align="center" label="文件" min-width="90">
+      <template #default="{ row }">
+        <el-button v-if="row?.extend?.fileUrls?.length" type="primary" link>已上传</el-button>
+        <div v-else>未上传</div>
+      </template>
+    </el-table-column>
     <template v-if="formData!.specType && !isBatch">
       <!--  根据商品属性动态添加 -->
       <el-table-column
@@ -281,7 +293,23 @@
     <!--  方便扩展每个活动配置的属性不一样  -->
     <slot name="extension"></slot>
   </el-table>
+
+  <Dialog title="文件上传" v-model="dialogVisible">
+    <UploadFile
+      v-model="fileUrl"
+      :file-type="['pdf', 'doc', 'docx', 'ppt']"
+      :limit="1"
+      :drag="true"
+      class="min-w-80px"
+      @clear="fileUrl = ''"
+    />
+    <template #footer>
+      <el-button @click="handleUploadSubmit" type="primary">确 定</el-button>
+      <el-button @click="dialogVisible = false, fileUrl = ''">取 消</el-button>
+    </template>
+  </Dialog>
 </template>
+
 <script lang="ts" setup>
 import { PropType, Ref } from 'vue'
 import { copyValueToTarget, formatToFraction } from '@/utils'
@@ -310,6 +338,7 @@ const props = defineProps({
     type: Array as PropType<RuleConfig[]>,
     default: () => []
   },
+  productType: propTypes.string.def(''), // 商品类型
   isBatch: propTypes.bool.def(false), // 是否作为批量操作组件
   isDetail: propTypes.bool.def(false), // 是否作为 sku 详情组件
   isComponent: propTypes.bool.def(false), // 是否作为 sku 选择组件
@@ -324,6 +353,9 @@ const skuList = ref<Sku[]>([
     barCode: '', // 商品条码
     picUrl: '', // 图片地址
     stock: 0, // 库存
+    extend: {
+      fileUrls: [] // 文件地址
+    },
     weight: 0, // 商品重量
     volume: 0, // 商品体积
     firstBrokeragePrice: 0, // 一级分销的佣金
@@ -339,6 +371,24 @@ const imagePreview = (imgUrl: string) => {
   })
 }
 
+// 文件上传
+const dialogVisible = ref(false)
+const fileUrl = ref('')
+const itemData = ref({})
+const handleUpload = (row) => {
+  itemData.value = row
+  if (row.extend?.fileUrls?.length) fileUrl.value = row.extend.fileUrls[0]
+  dialogVisible.value = true
+}
+const handleUploadSubmit = () => {
+  if (!fileUrl.value) return message.warning('请上传文件')
+  itemData.value.extend = {
+    fileUrls: [fileUrl.value]
+  }
+  dialogVisible.value = false
+  fileUrl.value = ''
+}
+
 /** 批量添加 */
 const batchAdd = () => {
   validateProperty()
@@ -457,6 +507,9 @@ const generateTableData = (propertyList: any[]) => {
       picUrl: '',
       stock: 0,
       weight: 0,
+      extend: {
+        fileUrls: [] // 文件地址
+      },
       volume: 0,
       firstBrokeragePrice: 0,
       secondBrokeragePrice: 0
@@ -530,6 +583,9 @@ watch(
           costPrice: 0,
           barCode: '',
           picUrl: '',
+          extend: {
+            fileUrls: [] // 文件地址
+          },
           stock: 0,
           weight: 0,
           volume: 0,

+ 13 - 2
src/views/mall/product/spu/form/InfoForm.vue

@@ -1,6 +1,11 @@
 <!-- 商品发布 - 基础设置 -->
 <template>
   <el-form ref="formRef" :disabled="isDetail" :model="formData" :rules="rules" label-width="120px">
+    <el-form-item label="商品类型" prop="type">
+      <el-radio-group v-model="formData.type" @change="val => emit('changeProductType', val)">
+        <el-radio v-for="dict in getIntDictOptions(DICT_TYPE.PRODUCT_SPU_TYPE)" :key="dict.value" :value="dict.value.toString()">{{ dict.label }}</el-radio>
+      </el-radio-group>
+    </el-form-item>
     <el-form-item label="商品名称" prop="name">
       <el-input
         v-model="formData.name"
@@ -57,6 +62,7 @@
     </el-form-item>
   </el-form>
 </template>
+
 <script lang="ts" setup>
 import { PropType } from 'vue'
 import { copyValueToTarget } from '@/utils'
@@ -67,8 +73,10 @@ import * as ProductCategoryApi from '@/api/mall/product/category'
 import { CategoryVO } from '@/api/mall/product/category'
 import * as ProductBrandApi from '@/api/mall/product/brand'
 import { BrandVO } from '@/api/mall/product/brand'
+import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
 
 defineOptions({ name: 'ProductSpuInfoForm' })
+
 const props = defineProps({
   propFormData: {
     type: Object as PropType<Spu>,
@@ -87,6 +95,7 @@ const formData = reactive<Spu>({
   picUrl: '', // 商品封面图
   sliderPicUrls: [], // 商品轮播图
   introduction: '', // 商品简介
+  type: '0', // 商品类型
   brandId: undefined // 商品品牌
 })
 const rules = reactive({
@@ -96,9 +105,11 @@ const rules = reactive({
   introduction: [required],
   picUrl: [required],
   sliderPicUrls: [required],
-  brandId: [required]
+  brandId: [required],
+  type: [required]
 })
 
+const emit = defineEmits(['update:activeName', 'changeProductType'])
 /** 将传进来的值赋值给 formData */
 watch(
   () => props.propFormData,
@@ -107,6 +118,7 @@ watch(
       return
     }
     copyValueToTarget(formData, data)
+    emit('changeProductType', data?.type || '0')
   },
   {
     immediate: true
@@ -114,7 +126,6 @@ watch(
 )
 
 /** 表单校验 */
-const emit = defineEmits(['update:activeName'])
 const validate = async () => {
   if (!formRef) return
   try {

+ 7 - 1
src/views/mall/product/spu/form/SkuForm.vue

@@ -29,6 +29,7 @@
       <SkuList
         ref="skuListRef"
         :prop-form-data="formData"
+        :productType="productType"
         :property-list="propertyList"
         :rule-config="ruleConfig"
       />
@@ -43,7 +44,7 @@
     </el-form-item>
     <template v-if="formData.specType && propertyList.length > 0">
       <el-form-item v-if="!isDetail" label="批量设置">
-        <SkuList :is-batch="true" :prop-form-data="formData" :property-list="propertyList" />
+        <SkuList :is-batch="true" :productType="productType" :prop-form-data="formData" :property-list="propertyList" />
       </el-form-item>
       <el-form-item label="规格列表">
         <SkuList
@@ -51,6 +52,7 @@
           :is-detail="isDetail"
           :prop-form-data="formData"
           :property-list="propertyList"
+          :productType="productType"
           :rule-config="ruleConfig"
         />
       </el-form-item>
@@ -107,6 +109,7 @@ const props = defineProps({
     type: Object as PropType<Spu>,
     default: () => {}
   },
+  productType: propTypes.string.def(''), // 商品类型
   isDetail: propTypes.bool.def(false) // 是否作为详情组件
 })
 const attributesAddFormRef = ref() // 添加商品属性表单
@@ -180,6 +183,9 @@ const onChangeSpec = () => {
       picUrl: '',
       stock: 0,
       weight: 0,
+      extend: {
+        fileUrls: []
+      },
       volume: 0,
       firstBrokeragePrice: 0,
       secondBrokeragePrice: 0

+ 12 - 2
src/views/mall/product/spu/form/index.vue

@@ -7,6 +7,7 @@
           v-model:activeName="activeName"
           :is-detail="isDetail"
           :propFormData="formData"
+          @change-product-type="handleChangeProductType"
         />
       </el-tab-pane>
       <el-tab-pane label="价格库存" name="sku">
@@ -14,10 +15,11 @@
           ref="skuRef"
           v-model:activeName="activeName"
           :is-detail="isDetail"
+          :productType="productType"
           :propFormData="formData"
         />
       </el-tab-pane>
-      <el-tab-pane label="物流设置" name="delivery">
+      <el-tab-pane v-if="productType === '0'" label="物流设置" name="delivery">
         <DeliveryForm
           ref="deliveryRef"
           v-model:activeName="activeName"
@@ -100,6 +102,9 @@ const formData = ref<ProductSpuApi.Spu>({
       barCode: '', // 商品条码
       picUrl: '', // 图片地址
       stock: 0, // 库存
+      extend: {
+        fileUrls: [] // 文件
+      },
       weight: 0, // 商品重量
       volume: 0, // 商品体积
       firstBrokeragePrice: 0, // 一级分销的佣金
@@ -112,6 +117,11 @@ const formData = ref<ProductSpuApi.Spu>({
   virtualSalesCount: 0 // 虚拟销量
 })
 
+const productType = ref('') // 是否显示物流设置
+const handleChangeProductType = (val: string) => {
+  productType.value = val
+}
+
 /** 获得详情 */
 const getDetail = async () => {
   if ('ProductSpuDetail' === name) {
@@ -153,7 +163,7 @@ const submitForm = async () => {
     // 校验各表单
     await unref(infoRef)?.validate()
     await unref(skuRef)?.validate()
-    await unref(deliveryRef)?.validate()
+    if (productType.value === '0') await unref(deliveryRef)?.validate()
     await unref(descriptionRef)?.validate()
     await unref(otherRef)?.validate()
     // 深拷贝一份, 这样最终 server 端不满足,不需要影响原始数据

+ 8 - 2
src/views/menduner/system/enterprise/message/SetVip.vue

@@ -3,6 +3,7 @@
 		<el-descriptions class="mb-50px" title="企业当前权益" :column="2" border>
 			<el-descriptions-item label="是否开启人才地图">{{ info.personMap ? '是' : '否' }}</el-descriptions-item>
 			<el-descriptions-item label="是否允许发布众聘职位">{{ info.hireJob ? '是' : '否' }}</el-descriptions-item>
+			<!-- <el-descriptions-item label="是否开启新任命">{{ info.newAppointment ? '是' : '否' }}</el-descriptions-item> -->
 			<el-descriptions-item label="剩余发布职位数量">{{ info.publishJobCount || 0 }}个</el-descriptions-item>
 			<el-descriptions-item label="剩余搜索人才数量">{{ info.searchCount || 0 }}次</el-descriptions-item>
 			<el-descriptions-item label="剩余查看简历数量">{{ info.lookCvCount || 0 }}次</el-descriptions-item>
@@ -42,6 +43,9 @@
       <el-form-item label="允许发布众聘职位" prop="entitlement.hireJob" :rules="[{ required: true, message: '请设置是否允许发布众聘职位', trigger: 'change' }]">
         <el-switch v-model="formData.entitlement.hireJob" />
       </el-form-item>
+      <!-- <el-form-item label="开启新任命" prop="entitlement.newAppointment" :rules="[{ required: true, message: '请设置是否开启新任命', trigger: 'change' }]">
+        <el-switch v-model="formData.entitlement.newAppointment" />
+      </el-form-item> -->
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
@@ -67,7 +71,8 @@ const formData = ref({
     searchCount: 0,
     lookCvCount: 0,
     personMap: false,
-    hireJob: false
+    hireJob: false,
+    // newAppointment: false
   }
 })
 const formRef = ref()
@@ -166,7 +171,8 @@ const resetForm = () => {
       searchCount: 0,
       lookCvCount: 0,
       personMap: false,
-      hireJob: false
+      hireJob: false,
+      // newAppointment: false
     }
   }
 }

+ 0 - 1
src/views/menduner/system/enterprise/message/index.vue

@@ -74,7 +74,6 @@
   <!-- 列表 -->
   <ContentWrap>
     <el-table v-loading="loading" :data="list" :stripe="true">
-      <el-table-column label="ID" align="center" prop="id" />
       <el-table-column label="企业LOGO" align="center" prop="logoUrl" fixed="left">
         <template #default="scope">
           <div class="h-70px w-80px">

+ 36 - 13
src/views/menduner/system/web/PreferredGroup.vue

@@ -3,25 +3,36 @@
     <el-form
       ref="formRef"
       :model="formData"
-      label-width="100px"
+      label-width="170px"
       v-loading="formLoading"
     >
-			<el-form-item label="企业ID" prop="enterpriseId" :rules="[{ required: true, message: '请输入企业ID', trigger: 'blur'}]">
+			<!-- <el-form-item label="企业ID" prop="enterpriseId" :rules="[{ required: true, message: '请输入企业ID', trigger: 'blur'}]">
         <el-input v-model="formData.enterpriseId" />
       </el-form-item>
       <el-form-item label="企业名称" prop="title" :rules="[{ required: true, message: '请输入企业名称', trigger: 'blur'}]">
         <el-input v-model="formData.title" />
+      </el-form-item> -->
+      <el-form-item label="企业名称" prop="enterpriseId" :rules="[{ required: true, message: '请选择企业', trigger: 'blur'}]">
+        <el-select-v2
+          ref="selectRef"
+          v-model="formData.enterpriseId"
+          :options="enterpriseList"
+          placeholder="请输入企业名称进行查找"
+          filterable
+          :props="{ label: 'name', value: 'id' }"
+          @blur="handleChange"
+        />
       </el-form-item>
-      <el-form-item label="企业LOGO" prop="logo">
+      <el-form-item label="顶部轮播图左上角LOGO" prop="logo">
         <UploadImg v-model="formData.logo" height="150px" width="150px" />
       </el-form-item>
-      <el-form-item label="轮播图" prop="carousel" :rules="[{ required: true, message: '请上传企业轮播图', trigger: 'change'}]">
+      <el-form-item label="顶部轮播图" prop="carousel" :rules="[{ required: true, message: '请上传企业轮播图', trigger: 'change'}]">
         <UploadImgs v-model="formData.carousel" />
       </el-form-item>
 			<el-form-item label="简介标题" prop="introduce.title" :rules="[{ required: true, message: '请输入简介标题', trigger: 'blur'}]">
         <el-input v-model="formData.introduce.title" />
       </el-form-item>
-			<el-form-item label="简介内容" prop="introduce.describe" :rules="[{ required: true, message: '请输入简介内容', trigger: 'blur'}]">
+			<el-form-item label="集团简介" prop="introduce.describe" :rules="[{ required: true, message: '请输入简介内容', trigger: 'blur'}]">
         <Editor v-model:modelValue="formData.introduce.describe" />
       </el-form-item>
 			<el-form-item label="简介小图" prop="introduce.thumbnail">
@@ -33,11 +44,9 @@
 			<el-form-item label="简介大图高度" prop="introduce.bigPicture.height">
         <el-input v-model="formData.introduce.bigPicture.height" />
       </el-form-item>
-
       <el-form-item label="品牌介绍" prop="">
         <el-button @click="showBrandDialog = true" type="primary">编 辑</el-button>
       </el-form-item>
-
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
@@ -46,13 +55,16 @@
   </Dialog>
 
   <Dialog title="品牌介绍" v-model="showBrandDialog" style="width: 70%;">
+    <div class="text-right">
+      <el-button type="primary" @click="handleAdd"><Icon icon="ep:plus" class="mr-5px" />新 增</el-button>
+    </div>
     <el-table :data="formData.brandIntroduce" :stripe="true">
       <el-table-column label="品牌名称" align="center" prop="content">
         <template #default="scope">
           <el-input type="textarea" :rows="2" v-model="scope.row.content" />
         </template>
       </el-table-column>
-      <el-table-column label="品牌图片" align="center" prop="title" width="300">
+      <el-table-column label="品牌图片" align="center" prop="url" width="300">
         <template #default="scope">
           <UploadImg v-model="scope.row.url" height="150px" width="280px" />
         </template>
@@ -80,6 +92,7 @@ import { WebContentApi } from '@/api/menduner/system/web'
 
 /** 页面内容 表单 */
 defineOptions({ name: 'WebContentForm' })
+defineProps({ enterpriseList: Array })
 
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
@@ -108,6 +121,11 @@ const formData = ref({
 const showBrandDialog = ref(false)
 
 const formRef = ref() // 表单 Ref
+const selectRef = ref()
+
+const handleChange = () => {
+  formData.value.title = selectRef.value.currentPlaceholder
+}
 
 /** 打开弹窗 */
 const result = ref({})
@@ -139,20 +157,25 @@ const handleDeleteBrand = (index) => {
   delete formData.value.brandIntroduce[index]
 }
 const handleBrandSubmit = () => {
+  const checkValue = formData.value.brandIntroduce.every(item => item.content.trim() && item.url && item.desc.trim())
+  if (!checkValue) return message.warning('请将列表中的项填写完整')
   showBrandDialog.value = false
 }
 
+// 提交表单
+const handleAdd = () => {
+  formData.value.brandIntroduce.push({ content: '', url: '', desc: '' })
+}
+
 /** 提交表单 */
 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
 const submitForm = async () => {
-
   // 校验表单
   await formRef.value.validate()
 	
-	if (!editId.value) {
-		result.value[currentKey.value][formData.value.enterpriseId] = formData.value
-		delete result.value[currentKey.value][formData.value.enterpriseId].enterpriseId
-	}
+	result.value[currentKey.value][formData.value.enterpriseId] = formData.value
+  if (editId.value !== formData.value.enterpriseId) delete result.value[currentKey.value][editId.value]
+  else delete result.value[currentKey.value][formData.value.enterpriseId].enterpriseId
 
   // 提交请求
   formLoading.value = true

+ 18 - 3
src/views/menduner/system/web/WebContentForm.vue

@@ -4,7 +4,7 @@
       ref="formRef"
       :model="formData"
       :rules="formRules"
-      label-width="140px"
+      label-width="130px"
       v-loading="formLoading"
     >
       <el-form-item label="上传图片尺寸" prop="imgSize" required>
@@ -16,9 +16,22 @@
         </div>
         <div style="display: flex; color: orange; align-items: center;"><Icon :size="20" icon="ep:warning" class="mr-3px" />提示:请严格按照图片规格上传</div>
       </el-form-item>
-      <el-form-item label="点击图片跳转链接" prop="link">
+      <el-form-item label="展示现有企业详情">
+        <el-switch v-model="showEnterprise" style="display: block;" />
+        <div>点击图片跳转场景:1、跳转到平台现有企业详情页面(有定制集团页面的则会跳转到集团页面),2.跳转已关联的公众号链接或其它外部链接</div>
+      </el-form-item>
+      <el-form-item v-if="showEnterprise" label="平台现有企业" prop="link">
+        <el-select-v2
+          ref="selectRef"
+          v-model="formData.link"
+          :options="enterpriseList"
+          placeholder="请输入企业名称进行查找"
+          filterable
+          :props="{ label: 'name', value: 'id' }"
+        />
+      </el-form-item>
+      <el-form-item v-else label="跳转链接" prop="link" placeholder="请填写">
         <el-input v-model="formData.link" />
-        <div style="color: orange;">提示:跳转已有的优选集团页面或者平台上的企业(详情页面),请将“招聘企业管理-招聘企业”列表中的ID复制填入此处!</div>
       </el-form-item>
       <el-form-item label="标题" prop="title">
         <el-input v-model="formData.title" placeholder="请填写" />
@@ -42,6 +55,7 @@ import { WebContentApi } from '@/api/menduner/system/web'
 
 /** 页面内容 表单 */
 defineOptions({ name: 'WebContentForm' })
+defineProps({ enterpriseList: Array })
 
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
@@ -89,6 +103,7 @@ const query = ref({
   appAdvertisement: undefined,
   status: undefined
 })
+const showEnterprise = ref(true)
 
 const formRules = reactive({
   url: [{ required: true, message: '图片不能为空', trigger: 'blur' }],

+ 14 - 12
src/views/menduner/system/web/index.vue

@@ -55,10 +55,10 @@
   </ContentWrap>
 
   <!-- 表单弹窗:添加/修改 -->
-  <WebContentForm ref="formRef" @success="getList" />
+  <WebContentForm ref="formRef" :enterpriseList="enterpriseList" @success="getList" />
 
   <!-- 优选集团 -->
-  <PreferredGroup ref="preferredGroupRef" @success="getList" />
+  <PreferredGroup ref="preferredGroupRef" :enterpriseList="enterpriseList" @success="getList" />
 
 </template>
 
@@ -67,6 +67,7 @@ import { WebContentApi } from '@/api/menduner/system/web'
 import WebContentForm from './WebContentForm.vue'
 import PreferredGroup from './PreferredGroup.vue'
 import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+import { EnterpriseUserBindApi } from '@/api/menduner/system/enterprise/userBind'
 
 /** 页面内容 列表 */
 defineOptions({ name: 'WebContent' })
@@ -86,18 +87,9 @@ const tabList = ref([
   { label: 'PC登录页背景图', value: 6, key: 'pcLoginBackground', size: '宽1920px*高940px' },
   { label: '小程序首页轮播图', value: 7, key: 'appHomeCarousel', size: '宽750px*高350px' },
   { label: '小程序首页弹窗广告图', value: 8, key: 'appAdvertisement', size: '宽331px*高442px' },
-  // { label: '小程序首页功能模块', value: 10, key: 'appHomeColumn', size: '宽72px*高72px' },
+  { label: '优选集团内容', value: 9, key: 'appPreferredGroup' }
 ])
 
-// 只有我们自己用的admin账号显示
-const { wsCache } = useCache()
-let userInfo = wsCache.get(CACHE_KEY.USER)
-if (userInfo && userInfo.user.nickname === 'admin') {
-  const obj = tabList.value.find(e => e.value === 9)
-  if (!obj) tabList.value.push({ label: '优选集团内容', value: 9, key: 'appPreferredGroup' })
-  else tabList.value = tabList.value.filter(e => e.value !== 9)
-} 
-
 /** 查询列表 */
 const getList = async () => {
   loading.value = true
@@ -109,6 +101,16 @@ const getList = async () => {
   }
 }
 
+// 企业列表
+const enterpriseList = ref([])
+const getEnterpriseListData = async () => {
+  try {
+    const data = await EnterpriseUserBindApi.getEnterpriseList()
+    enterpriseList.value = data
+  } catch (err) {}
+}
+getEnterpriseListData()
+
 // 优选集团
 const preferredGroup = computed(() => (data) => {
   const list = []