Browse Source

更新区域组件

tongshangming 5 months ago
parent
commit
5bdca60cdc

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "fs-admin",
-  "version": "2.3.0",
+  "version": "2.4.0",
   "type": "module",
   "scripts": {
     "dev": "vite --host",

+ 0 - 110
src/components/FsCitySelect/index.vue

@@ -1,110 +0,0 @@
-<script setup lang="ts">
-import type { citySelectProps } from './props'
-import { citySelectEmits } from './props'
-import { getAreaList } from '@/api/area'
-
-const emits = defineEmits(citySelectEmits)
-
-const props = withDefaults(defineProps<citySelectProps>(), {
-  type: 'area',
-  size: 'default',
-  clearable: true
-})
-
-const cascaderRef = ref(null)
-
-// 选中的数据
-const cascaderValue = ref<any>()
-
-const options = ref<any>([])
-
-/* 自定义配置 */
-const setting = {
-  value: 'id'
-}
-
-/* 配置 */
-const cascaderProps = computed(() => {
-  return Object.assign(setting, props.props)
-})
-
-/* 级联数据 */
-const cascaderData = computed(() => {
-  // 选择区
-  if (props.type === 'area') {
-    return options.value
-  } else if (props.type === 'city') {
-    // 选择市返回两级
-    return options.value.map((x: any) => {
-      return {
-        id: x.id,
-        label: x.label,
-        children: x.children.map((y: any) => {
-          return {
-            id: y.id,
-            label: y.label
-          }
-        })
-      }
-    })
-  } else {
-    // 全部返回
-    return options.value.map((x: any) => {
-      return {
-        id: x.id,
-        label: x.label
-      }
-    })
-  }
-})
-
-/* 获取数据 */
-const getData = () => {
-  if (props.datasource && typeof props.datasource === 'function') {
-    props.datasource().then((res: any) => {
-      options.value = res
-    })
-  } else {
-    getAreaList().then((res: any) => {
-      options.value = res
-    })
-  }
-}
-getData()
-
-/* 修改modelValue */
-const updateModelValue = (modelValue: any) => {
-  const value = Array.isArray(modelValue) ? [...new Set([...modelValue])].join(',') : modelValue
-  emits('update:modelValue', value)
-}
-
-/* 监听cascaderValue */
-watch(cascaderValue, () => {
-  updateModelValue(cascaderValue.value)
-  // 触发change事件
-  emits('change', cascaderValue.value)
-})
-
-watch(
-  () => props.modelValue,
-  () => {
-    // 传入是字符串转为数组
-    if (typeof props.modelValue === 'string') {
-      cascaderValue.value = props.modelValue.split(',')
-    }
-  },
-  {
-    immediate: true
-  }
-)
-</script>
-
-<template>
-  <el-cascader ref="cascaderRef" v-model="cascaderValue" :options="cascaderData" :props="cascaderProps" />
-</template>
-
-<style scoped lang="scss">
-:deep(.el-cascader__dropdown) {
-  min-width: 200px;
-}
-</style>

+ 0 - 19
src/components/FsCitySelect/props.ts

@@ -1,19 +0,0 @@
-/* eslint-disable @typescript-eslint/no-unused-vars */
-import type { CascaderProps } from 'element-plus'
-export interface citySelectProps {
-  // 选中数据
-  modelValue: string
-  // 地区类型
-  type?: 'province' | 'city' | 'area'
-  props?: CascaderProps
-  // 自定义数据源
-  datasource?: () => Promise<Array<any>>
-}
-
-/* 事件 */
-export const citySelectEmits = {
-  // 选择事件
-  change: (_value: any) => true,
-  // 修改modelValue
-  'update:modelValue': (_value: any) => true
-}

+ 1 - 1
src/components/core/GlobalHeader.vue

@@ -185,7 +185,7 @@ const handleSelect = (menu: any) => {
         <!-- <el-button link  @click="newsVisible = true">
           <icon-remind :size="iconSize" :fill="headerStyle.color" />
         </el-button> -->
-        <el-avatar class="mr-10px ml-4" :src="user.photo" :size="35">
+        <el-avatar class="mr-10px ml-4" :src="user.photo" :size="30">
           <img :src="avatar" alt="" />
         </el-avatar>
         <el-dropdown size="large">

+ 67 - 9
src/components/form/ElArea.vue

@@ -1,25 +1,83 @@
-<script lang="ts" setup>
+<script setup lang="ts">
+import type { CascaderProps } from 'element-plus'
 import { getAreaList } from '@/api/area'
 
 interface Props {
-  modelValue: any
+  // 选中数据
+  modelValue: string | string[]
+  // 地区类型
+  type?: 'province' | 'city' | 'area'
+  props?: CascaderProps
+  // 自定义数据源
+  request?: () => Promise<any>
 }
-const props = defineProps<Props>()
-const emits = defineEmits(['update:modelValue'])
+
+const props = withDefaults(defineProps<Props>(), {
+  type: 'area',
+  clearable: true,
+  request: getAreaList
+})
+const emits = defineEmits(['change', 'update:modelValue'])
 
 const modelValue = computed({
-  get: () => props.modelValue,
-  set: value => emits('update:modelValue', value)
+  get: () => (typeof props.modelValue === 'string' ? props.modelValue.split(',') : props.modelValue),
+  set: value => emits('update:modelValue', Array.isArray(value) ? value.join(',') : value)
 })
 
+/* 配置 */
+const cascaderProps = {
+  value: 'id',
+  ...props.props
+}
+
 const options = ref<any>([])
-getAreaList().then(res => {
+props.request().then((res: any) => {
   options.value = res
 })
+/* 级联数据 */
+const cascaderData = computed(() => {
+  // 选择区
+  if (props.type === 'area') {
+    return options.value
+  } else if (props.type === 'city') {
+    // 选择市返回两级
+    return options.value.map((x: any) => {
+      return {
+        id: x.id,
+        label: x.label,
+        children: x.children.map((y: any) => {
+          return {
+            id: y.id,
+            label: y.label
+          }
+        })
+      }
+    })
+  } else {
+    // 全部返回
+    return options.value.map((x: any) => {
+      return {
+        id: x.id,
+        label: x.label
+      }
+    })
+  }
+})
 </script>
 
 <template>
-  <el-cascader v-model="modelValue" :options="options" style="width: 100%" />
+  <el-cascader
+    v-model="modelValue"
+    :options="cascaderData"
+    :props="cascaderProps"
+    clearable
+    collapse-tags
+    style="width: 100%"
+  />
 </template>
 
-<style lang="scss" scoped></style>
+<style scoped lang="scss">
+:deep(.el-cascader__dropdown) {
+  min-width: 200px;
+}
+</style>

+ 11 - 21
src/router/asyncRouter.ts

@@ -175,8 +175,7 @@ const asyncRouter: RouteRecordRaw[] = [
         name: 'cardList',
         component: () => import('@/views/list/CardList.vue'),
         meta: {
-          title: '卡片列表',
-          icon: 'icon-bank-card'
+          title: '卡片列表'
         }
       }
     ]
@@ -291,15 +290,6 @@ const asyncRouter: RouteRecordRaw[] = [
           icon: 'MoreFilled'
         }
       },
-      {
-        path: '/extension/imageUpload',
-        name: 'imageUpload',
-        component: () => import('@/views/extension/imageUpload/index.vue'),
-        meta: {
-          title: '图片上传',
-          icon: 'MoreFilled'
-        }
-      },
       {
         path: '/extension/splitePanel',
         name: 'splitePanel',
@@ -359,19 +349,19 @@ const asyncRouter: RouteRecordRaw[] = [
         name: 'citySelect',
         component: () => import('@/views/extension/citySelect/index.vue'),
         meta: {
-          title: '城市选择',
-          icon: 'MoreFilled'
-        }
-      },
-      {
-        path: '/extension/map',
-        name: 'extensionMap',
-        component: () => import('@/views/extension/map/index.vue'),
-        meta: {
-          title: '地图选择',
+          title: '区域选择',
           icon: 'MoreFilled'
         }
       }
+      // {
+      //   path: '/extension/map',
+      //   name: 'extensionMap',
+      //   component: () => import('@/views/extension/map/index.vue'),
+      //   meta: {
+      //     title: '地图选择',
+      //     icon: 'MoreFilled'
+      //   }
+      // }
     ]
   },
   {

+ 4 - 6
src/views/extension/citySelect/base.vue

@@ -1,6 +1,4 @@
 <script setup lang="ts">
-import FsCitySelect from '@/components/FsCitySelect/index.vue'
-
 const city = ref('')
 const city2 = ref('')
 const city3 = ref('')
@@ -8,20 +6,20 @@ const city3 = ref('')
 
 <template>
   <el-card header="基础使用" shadow="never">
-    <el-row :gutter="0">
+    <el-row :gutter="15">
       <el-col :span="8">
         <el-form-item label="选择区:" prop="">
-          <fs-city-select v-model="city" class="w-200px" tag-type="success" clearable></fs-city-select>
+          <el-area v-model="city" class="w-200px" tag-type="success" clearable></el-area>
         </el-form-item>
       </el-col>
       <el-col :span="8">
         <el-form-item label="选择市:" prop="">
-          <fs-city-select v-model="city2" class="w-200px" type="city" clearable></fs-city-select>
+          <el-area v-model="city2" class="w-200px" type="city" clearable></el-area>
         </el-form-item>
       </el-col>
       <el-col :span="8">
         <el-form-item label="选择省:" prop="">
-          <fs-city-select v-model="city3" class="w-200px" type="province" clearable></fs-city-select>
+          <el-area v-model="city3" class="w-200px" type="province" clearable></el-area>
         </el-form-item>
       </el-col>
     </el-row>

+ 2 - 3
src/views/extension/citySelect/custom.vue

@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import FsCitySelect from '@/components/FsCitySelect/index.vue'
 import { getAreaList } from '@/api/area'
 
 const city = ref('')
@@ -25,12 +24,12 @@ const getList2 = async () => {
     <el-row :gutter="15">
       <el-col :span="8">
         <el-form-item label="山西省:" prop="">
-          <fs-city-select v-model="city" class="w-200px" tag-type="success" :datasource="getList"></fs-city-select>
+          <el-area v-model="city" class="w-200px" tag-type="success" :request="getList"></el-area>
         </el-form-item>
       </el-col>
       <el-col :span="8">
         <el-form-item label="太原市:" prop="">
-          <fs-city-select v-model="city2" class="w-200px" tag-type="success" :datasource="getList2"></fs-city-select>
+          <el-area v-model="city2" class="w-200px" tag-type="success" :request="getList2"></el-area>
         </el-form-item>
       </el-col>
     </el-row>

+ 4 - 25
src/views/extension/citySelect/multiple.vue

@@ -1,6 +1,4 @@
 <script setup lang="ts">
-import FsCitySelect from '@/components/FsCitySelect/index.vue'
-
 const city = ref('')
 const city2 = ref('')
 const city3 = ref('')
@@ -8,39 +6,20 @@ const city3 = ref('')
 
 <template>
   <el-card header="多选使用" shadow="never">
-    <el-row :gutter="0">
+    <el-row :gutter="15">
       <el-col :span="8">
         <el-form-item label="选择区:" prop="">
-          <fs-city-select
-            v-model="city"
-            class="w-200px"
-            tag-type="success"
-            collapse-tags
-            :props="{ multiple: true }"
-            clearable
-          ></fs-city-select>
+          <el-area v-model="city" class="w-200px" tag-type="success" :props="{ multiple: true }"></el-area>
         </el-form-item>
       </el-col>
       <el-col :span="8">
         <el-form-item label="选择市:" prop="">
-          <fs-city-select
-            v-model="city2"
-            class="w-200px"
-            type="city"
-            clearable
-            :props="{ multiple: true }"
-          ></fs-city-select>
+          <el-area v-model="city2" class="w-200px" type="city" :props="{ multiple: true }"></el-area>
         </el-form-item>
       </el-col>
       <el-col :span="8">
         <el-form-item label="选择省:" prop="">
-          <fs-city-select
-            v-model="city3"
-            class="w-200px"
-            type="province"
-            clearable
-            :props="{ multiple: true }"
-          ></fs-city-select>
+          <el-area v-model="city3" class="w-200px" type="province" :props="{ multiple: true }"></el-area>
         </el-form-item>
       </el-col>
     </el-row>

+ 0 - 78
src/views/extension/imageUpload/index.vue

@@ -1,78 +0,0 @@
-<script setup lang="ts">
-import { ElMessage } from 'element-plus'
-import config from '@/config/defaultSetting'
-const images = ref('')
-// 手动上传数据
-const images2 = ref('')
-const images3 = ref('')
-const imageUploadRef = ref()
-
-const disabled = ref(false)
-
-const onRemove = (file: any) => {
-  console.log(file)
-}
-
-const uploadFunction = () => {
-  return new Promise(resolve => {
-    setTimeout(() => {
-      resolve({
-        data: 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png'
-      })
-    }, 1000)
-  })
-}
-
-const upload = () => {
-  imageUploadRef.value?.submit()
-}
-
-const submit = () => {
-  if (!imageUploadRef.value?.checkUpload()) {
-    ElMessage.error('请等待图片上传完成')
-    return
-  }
-  ElMessage.success('上传完成')
-}
-</script>
-
-<template>
-  <el-card header="基础示例" shadow="never">
-    <el-image-upload
-      v-model="images"
-      :limit="5"
-      :uploadFunction="uploadFunction"
-      :disabled="disabled"
-      :action="config.uploadApi"
-      drag
-      @remove="onRemove"
-    />
-    <div class="flex items-center mt-2">
-      <div>是否禁用:</div>
-      <el-radio-group v-model="disabled">
-        <el-radio label="是" :value="true"> </el-radio>
-        <el-radio label="否" :value="false"> </el-radio>
-      </el-radio-group>
-    </div>
-  </el-card>
-  <el-card header="支持多选" shadow="never" class="mt-3">
-    <el-image-upload v-model="images2" multiple :limit="5" :uploadFunction="uploadFunction" @remove="onRemove" />
-  </el-card>
-  <el-card header="基础示例" shadow="never" class="mt-3">
-    <el-image-upload
-      v-model="images3"
-      :auto-upload="false"
-      :limit="5"
-      :uploadFunction="uploadFunction"
-      :item-style="{ width: '50px', height: '100px' }"
-      ref="imageUploadRef"
-      @remove="onRemove"
-    />
-    <div class="flex items-center mt-2">
-      <el-button type="primary" @click="upload">手动上传</el-button>
-      <el-button type="primary" @click="submit">检查是否上传完毕</el-button>
-    </div>
-  </el-card>
-</template>
-
-<style scoped></style>

+ 47 - 49
src/views/form/Basic.vue

@@ -4,7 +4,7 @@ import { ElInput } from 'element-plus'
 
 const formData = reactive<any>({})
 const formConfig = reactive<BasicForm>({
-  span: 24,
+  span: 12,
   props: {
     labelPosition: 'right'
   },
@@ -36,7 +36,7 @@ const formConfig = reactive<BasicForm>({
       type: 'area',
       props: {
         props: {
-          value: 'id'
+          multiple: true
         }
       }
     },
@@ -324,54 +324,52 @@ const handleInputConfirm = () => {
 </script>
 
 <template>
-  <div class="h-full bg-white p-16px pt-50px flex justify-center overflow-auto">
-    <div class="w-500px">
-      <pro-form :formConfig="formConfig" :formData="formData" :create="create" :update="update" ref="proFormRef">
-        <template #prepend1> test1 </template>
-        <template #append1> test1 </template>
-        <template #cDefault="{ node, data }">
-          <span>{{ data.label }}</span>
-          <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
-        </template>
-        <template #file>
-          <el-button type="primary">上传文件</el-button>
-        </template>
-        <template #tip>
-          <div><el-text>请上传750*450px 的图片</el-text></div>
-        </template>
+  <div class="h-full bg-white p-16px pt-20px overflow-auto">
+    <pro-form :formConfig="formConfig" :formData="formData" :create="create" :update="update" ref="proFormRef">
+      <template #prepend1> test1 </template>
+      <template #append1> test1 </template>
+      <template #cDefault="{ node, data }">
+        <span>{{ data.label }}</span>
+        <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
+      </template>
+      <template #file>
+        <el-button type="primary">上传文件</el-button>
+      </template>
+      <template #tip>
+        <div><el-text>请上传750*450px 的图片</el-text></div>
+      </template>
 
-        <template #password>
-          <el-input type="password" name="password" v-model="formData.password" placeholder="请输入密码"></el-input>
-          <el-text type="info">密码需包含大写字母、小写字母、数字</el-text>
-        </template>
-        <template #customDefault>
-          <el-space wrap>
-            <el-tag
-              v-for="tag in dynamicTags"
-              :key="tag"
-              size="small"
-              closable
-              :disable-transitions="false"
-              @close="handleClose(tag)"
-            >
-              {{ tag }}
-            </el-tag>
-            <el-input
-              v-if="inputVisible"
-              ref="InputRef"
-              v-model="inputValue"
-              class="ml-1 w-20"
-              size="small"
-              @keyup.enter="handleInputConfirm"
-              @blur="handleInputConfirm"
-            />
-            <el-button v-else class="button-new-tag ml-1" size="small" @click="showInput"> + New Tag </el-button>
-          </el-space>
-        </template>
-      </pro-form>
-      <div class="text-center">
-        <el-button type="primary" @click="handleSave">保存</el-button>
-      </div>
+      <template #password>
+        <el-input type="password" name="password" v-model="formData.password" placeholder="请输入密码"></el-input>
+        <el-text type="info">密码需包含大写字母、小写字母、数字</el-text>
+      </template>
+      <template #customDefault>
+        <el-space wrap>
+          <el-tag
+            v-for="tag in dynamicTags"
+            :key="tag"
+            size="small"
+            closable
+            :disable-transitions="false"
+            @close="handleClose(tag)"
+          >
+            {{ tag }}
+          </el-tag>
+          <el-input
+            v-if="inputVisible"
+            ref="InputRef"
+            v-model="inputValue"
+            class="ml-1 w-20"
+            size="small"
+            @keyup.enter="handleInputConfirm"
+            @blur="handleInputConfirm"
+          />
+          <el-button v-else class="button-new-tag ml-1" size="small" @click="showInput"> + New Tag </el-button>
+        </el-space>
+      </template>
+    </pro-form>
+    <div class="text-center">
+      <el-button type="primary" @click="handleSave">保存</el-button>
     </div>
   </div>
 </template>