【招生平台主控端】 优化# 移除无用代码

master
kaeery 2025-02-26 11:22:45 +08:00
parent ed0fc05be1
commit 13058f0936
22 changed files with 0 additions and 1739 deletions

View File

@ -1,41 +0,0 @@
<script setup lang="ts">
import { nextTick, unref, watch } from 'vue'
import { useAreaMapOperation } from './hooks/useServiceArea';
import { MAP_INJECTION_KEY } from '@/config/symbol'
const parentApi = inject(MAP_INJECTION_KEY)
const { mapRef, setMapCenter, drawPolygon, removePolygon, initPolygon } = useAreaMapOperation(parentApi)
const isInited = computed(() => parentApi?.isInited.value)
const location = computed(() => !isInited.value && parentApi?.address.value.location)
watch(() => unref(parentApi?.address), ({ location }) => {
if (isInited.value) return
setMapCenter(location)
})
onMounted(() => {
if (isInited.value) return
nextTick(() => setMapCenter(location.value))
})
defineExpose({
setMapCenter,
initPolygon,
removePolygon,
})
</script>
<template>
<div class="map">
<div ref="mapRef" class="map__inner"></div>
<div id="toolControl">
<div class="toolItem" title="添加区域按钮" @click="drawPolygon"></div>
</div>
</div>
</template>
<style lang="scss" scoped>
@import '@/components/area-common/styles/map.scss';
</style>

View File

@ -1,52 +0,0 @@
<script setup lang="ts">
import { watch, onMounted, type PropType } from 'vue'
import area from '@/utils/area'
import { MAP_INJECTION_KEY } from '@/config/symbol'
const cascaderProps = {
checkStrictly: true,
value: 'label'
}
const parentApi = inject(MAP_INJECTION_KEY)
const emit = defineEmits(['handleSearch'])
const form = reactive<{ area: string[] }>({
area: [],
})
const isDisabled = computed(() => !form.area?.length)
const isInited = computed(() => parentApi?.isInited.value)
const location = computed(() => !isInited.value ? parentApi?.address.value.address_components : '')
onMounted(() => {
if (isInited.value) return
setCascaderValue(location.value)
})
const handleSearch = async () => {
emit('handleSearch', form)
}
function setCascaderValue(location: any) {
const { province, city, district } = location
form.area = [province, city, district]
}
defineExpose({
setCascaderValue
})
</script>
<template>
<div class="area__search">
<el-form :model="form" :inline="true">
<el-form-item label="地区选择">
<el-cascader v-model="form.area" :options="area" :props="cascaderProps" clearable>
</el-cascader>
</el-form-item>
<el-form-item>
<el-button type="primary" :disabled="isDisabled" @click="handleSearch"></el-button>
</el-form-item>
</el-form>
</div>
</template>
<style lang="scss" scoped></style>

View File

@ -1,86 +0,0 @@
<script setup lang="ts">
import { useRoute } from 'vue-router'
import type { ElTable } from 'element-plus'
import Pagination from '@/components/pagination/index.vue'
import { MAP_INJECTION_KEY, type Pager } from '@/config/symbol'
interface TableProps {
zone: String
pager: Pager
selectData?: any[]
}
const props = withDefaults(defineProps<TableProps>(), {
pager: {}
})
const emit = defineEmits(['update:selectData', 'update:pager'])
const route = useRoute()
const parentApi = inject(MAP_INJECTION_KEY)
const tableRef = ref<InstanceType<typeof ElTable>>()
const tableData = computed(() => props.pager?.lists)
const getLists = computed(() => props.pager?.getLists)
const pathName = computed(() => route.meta.activeMenu)
const originSelectData = computed(() => parentApi?.originSelectData?.value)
const pager = computed({
get() {
return props.pager
},
set(newVal) {
emit('update:pager', newVal)
}
})
/**定位 */
const handleLocation = (row: any) => {
parentApi?.handleLocation(row)
}
/**删除 */
const handleDelete = (id: number) => {
parentApi?.handleDelete(id)
}
/**选中 */
const handleSelectionChange = (val: any) => {
emit('update:selectData', val)
}
/**初始化选中 */
watch(() => unref(tableData), (val) => {
if (val.length && props.selectData?.length) {
parentApi?.toggleRowSelection!(originSelectData.value)
}
})
defineExpose({
tableRef
})
</script>
<template>
<div class="atable">
<div class="atable__top">
<span>{{ zone }}已有服务区域</span>
</div>
<div class="atable-bottom">
<el-table ref="tableRef" :data="tableData" row-key="id" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" reserve-selection />
<el-table-column prop="name" label="名称" />
<el-table-column label="操作">
<template #default="{ row }">
<el-button link type="primary" @click="handleLocation(row)"></el-button>
<el-button v-if="!pathName" link type="danger" @click="handleDelete(row.id)"></el-button>
</template>
</el-table-column>
</el-table>
<div class="flex justify-end mt-4">
<Pagination v-model="pager" @change="getLists" />
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.atable {
background-color: #fff;
// width: 450px;
}
</style>

View File

@ -1,263 +0,0 @@
import { nextTick, type Ref, unref, watch } from "vue"
import { useRequest } from "@/hooks/useFetchData"
import { usePaging } from "@/hooks/usePaging"
import { addArea, apiMapLocation, delArea, getAreaListByLocation, getLonAndLatByArea } from "@/api/service/area"
import type { Pager, Location } from '@/config/symbol'
import { VITE_MAP_KEY } from "@/config/env"
import { toast } from "@/utils/util"
/**用户操作 */
export function useAreaOperation(inited = true) {
const areaSearch = ref()
const tcMap = ref()
const zone = ref('') //地区
const regionCode = ref() //地区编码
const base = ref<Pager<any>>() //区域列表信息
const address = ref() //当前地址信息
const isInited = ref(true) //初始化
// 查询
const handleSearch = (form: any) => {
const params = {
address: encodeURIComponent(form.area.join('')),
key: VITE_MAP_KEY
}
const { runFn } = useRequest({
apiFn: getLonAndLatByArea,
onSuccess(response) {
const { result: { location, address_components, ad_info } } = response
searchCommon({ location, address_components, ad_info })
},
})
runFn(params)
}
// 查询后操作
const searchCommon = (payload: any) => {
const { location, address_components, ad_info } = payload
if (isInited.value) {
tcMap.value?.setMapCenter(location)
areaSearch.value?.setCascaderValue(address_components)
}
address.value = payload
zone.value = address_components.district
regionCode.value = ad_info.adcode
fetchAreaList()
}
// 添加区域
const increment = async (payload: any) => {
const { runFn } = useRequest({
apiFn: addArea,
onSuccess(response) {
tcMap.value.removePolygon()
toast('添加成功', 'success')
fetchAreaList()
},
})
runFn(payload)
}
/**获取区域列表 */
const fetchAreaList = async () => {
const params = {
regionId: regionCode.value
}
const { pager, getLists } = usePaging({
fetchFun: getAreaListByLocation,
params
})
await getLists()
base.value = Object.assign(pager, {
getLists
})
}
/**初始化当前位置 */
const initPosition = async () => {
const params = { key: VITE_MAP_KEY }
const { runFn } = useRequest({
apiFn: apiMapLocation,
onSuccess(response) {
const { result: { location, ad_info } } = response
searchCommon({ location, address_components: ad_info, ad_info })
}
})
runFn(params)
isInited.value = inited
}
onMounted(initPosition)
return {
tcMap,
areaSearch,
zone,
regionCode,
increment,
searchCommon,
handleSearch,
base,
address,
isInited
}
}
/**表格操作 */
export function useAreaTableOperation({ tcMap, base, aTable }: { tcMap: any, base: Ref<Pager>, aTable: any }) {
/**选中 */
const toggleRowSelection = (selectData: any[]) => {
const tableData = base.value.lists
const selectedIds = selectData?.map(item => item.id) as number[]
const selectedList = tableData.filter(data => selectedIds.includes(data.id))
tableData.forEach(data => {
aTable.value.tableRef.toggleRowSelection(data, false)
})
selectedList.forEach(row => {
aTable.value.tableRef.toggleRowSelection(row, true)
})
}
/**定位 */
const handleLocation = (row: any) => {
const convertPolygons = row.polygongeo.replace("POLYGON((", '').replace("))", '').split(',')
const polygonPaths = convertPolygons.map((path: string) => {
const [lng, lat] = path.split(' ')
return {
lat: parseFloat(lat),
lng: parseFloat(lng)
}
})
tcMap.value.initPolygon({
polygonId: row.id,
polygonPaths
})
}
/**删除 */
const handleDelete = async (id: number) => {
const { runFn } = useRequest({
apiFn: delArea,
onSuccess(response) {
toast('删除成功', 'success')
base.value.getLists()
}
})
runFn({ id })
}
return {
handleLocation,
handleDelete,
toggleRowSelection,
}
}
/**地图 */
export function useAreaMapOperation(parentApi: any) {
let map, polygon, editor;
const TMap = (window as any).TMap
const mapRef = ref()
const drawId = ref([])
/**初始化地图 */
function initMap() {
map = new TMap.Map(mapRef.value, {
zoom: 12,
viewMode: '2D'
})
}
/**设置地图中心 */
function setMapCenter(location: Location) {
const { lat, lng } = location
map!.setCenter(new TMap.LatLng(lat, lng))
}
/**绘制多边形 */
const drawPolygon = () => {
polygon = new TMap.MultiPolygon({
map: map
})
editor = new TMap.tools.GeometryEditor({
map: map,
overlayList: [
{
overlay: polygon,
id: 'polygon',
}
],
actionMode: TMap.tools.constants.EDITOR_ACTION.DRAW, // 编辑器的工作模式
activeOverlayId: 'polygon', // 激活图层
snappable: true,
})
editor.on('draw_complete', geometry => {
drawId.value.push(geometry.id)
geometry.paths.splice(geometry.paths.length, 0, geometry.paths[0])
parentApi?.showDialog({
polygonPaths: geometry.paths
})
})
}
/**表格定位=>初始化多边形 */
function initPolygon({ polygonId, polygonPaths }: { polygonId: number, polygonPaths: Location[] }) {
if (polygonId === polygon?.id) return
polygon = new TMap.MultiPolygon({
id: polygonId, // 图层id
map: map, // 显示多边形图层的底图
styles: {
// 多边形的相关样式
polygon: new TMap.PolygonStyle({
color: 'rgb(250, 250, 122)', // 面填充色
showBorder: false, // 是否显示拔起面的边线
borderColor: '#00FFFF', // 边线颜色
}),
},
geometries: [
{
id: 'polygon', // 多边形图形数据的标志信息
styleId: 'polygon', // 样式id
paths: polygonPaths, // 多边形的位置信息
properties: {
// 多边形的属性数据
title: 'polygon',
},
},
],
})
}
/**移除多边形 (先选中再删除)*/
function removePolygon() {
editor!.setActionMode(TMap.tools.constants.EDITOR_ACTION.INTERACT).select(drawId.value).setSelectable(true)
editor!.delete()
}
onMounted(() => {
nextTick(initMap)
})
return {
mapRef,
setMapCenter,
drawPolygon,
removePolygon,
initPolygon
}
}
/**弹框 */
export function useDialogOperation(regionCode: Ref<number>) {
const infoDialogRef = ref()
function showDialog(payload: any) {
const params = {
title: '绘制确认',
rawData: { ...payload, regionCode: regionCode.value }
}
infoDialogRef.value.acceptParams(params)
}
return {
infoDialogRef,
showDialog
}
}

View File

@ -1,12 +0,0 @@
.area {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 50px minmax(100px, auto);
gap: 20px;
&__part {
display: grid;
grid-template-columns: 1fr minmax(400px, 1fr);
gap: 20px;
}
}

View File

@ -1,36 +0,0 @@
.map {
position: relative;
flex: 1;
&__inner {
width: 100%;
height: 100%;
}
#toolControl {
position: absolute;
top: 10px;
left: 0px;
right: 0px;
margin: auto;
width: 252px;
z-index: 1001;
.toolItem {
width: 30px;
height: 30px;
float: left;
margin: 1px;
padding: 4px;
border-radius: 3px;
background-size: 30px 30px;
background-position: 4px 4px;
background-repeat: no-repeat;
box-shadow: 0 1px 2px 0 #e4e7ef;
background-color: #ffffff;
border: 1px solid #ffffff;
background-image: url('https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/polygon.png');
background-position: center;
}
}
}

View File

@ -1,55 +0,0 @@
<template>
<div class="area-select">
<el-cascader :style="{ width }" v-model="areaValue" :options="options" :props="props2" clearable></el-cascader>
</div>
</template>
<script lang="ts" setup>
import area from '@/utils/area'
import { ref, computed } from 'vue'
/** Emit Start **/
const emit = defineEmits(['update:province', 'update:city', 'update:district'])
/** Emit End **/
/** Props Start **/
const props = withDefaults(
defineProps<{
province?: any
city: any
district: any
width?: string
checkStrictly?: boolean
}>(),
{
province: null,
city: null,
district: null,
width: '340px',
checkStrictly: true
}
)
const props2 = {
checkStrictly: true
}
/** Props End **/
/** Data End **/
const options = ref<any>(area) //
/** Data Start **/
/** Computed Start **/
//
const areaValue = computed({
get: () => {
return [props.province, props.city, props.district]
},
set: (value: any) => {
emit('update:province', value ? value[0] : '')
emit('update:city', value ? value[1] : '')
emit('update:district', value ? value[2] : '')
}
})
/** Computed Start **/
</script>

View File

@ -1,87 +0,0 @@
<template>
<popup class="inline mr-3" :clickModalClose="false" :title="`选择${setTitle}`" :center="true"
@close="handleClose(channelFormRef)" @open="handleOpen" @confirm="handleConfirm" width="1200px">
<template #trigger>
<slot></slot>
</template>
<component :is="setComponent" ref="componentRef" />
</popup>
</template>
<script lang="ts" setup>
import { computed, ref, type PropType } from 'vue'
import type { ElForm, FormInstance } from 'element-plus'
import Popup from '@/components/popup/index.vue'
import distributeTable from './distributeTable.vue'
import userTable from './userTable.vue'
import { CHANNEL_INJECTION_KEY } from '@/config/symbol'
import { ChannelEnum } from '@/enums/modeEnum'
const props = defineProps({
modelValue: Object as PropType<any>
})
const emit = defineEmits(['update:modelValue'])
const parent = inject(CHANNEL_INJECTION_KEY)
const channel = computed(() => parent?.channel.value)
const condition = computed(() => channel.value === ChannelEnum.DISTBUTOR)
const setTitle = computed(() => unref(condition) ? '分销员' : '指定用户')
const setComponent = computed(() => unref(condition) ? distributeTable : userTable) /**根据渠道切换组件 */
const selectObj = computed(() => parent?.selectObj?.value)
const selectData = ref<Record<number, any[]>>({})
const channelFormRef = ref<InstanceType<typeof ElForm>>()
const componentRef = ref()
//
const handleClose = (formEl: FormInstance | undefined): void => {
if (!formEl) return
formEl.resetFields()
}
//
const handleConfirm = (): void => {
//
selectData.value = {}
selectData.value[unref(channel)!] = selectObj.value![unref(channel)!]
emit('update:modelValue', selectData.value)
}
const handleOpen = () => {
selectedTable()
}
/**表格选中效果 */
function selectedTable() {
setTimeout(() => {
if (componentRef.value) {
const tableData = componentRef.value.pager.lists as any[]
const selectedIds = selectData.value[unref(channel)!]?.map(item => item.id) as number[]
if (selectedIds) {
const selectedList = tableData.filter(data => selectedIds.includes(data.id))
tableData.forEach(data => {
componentRef.value.tableDataRef?.toggleRowSelection(data, false)
})
selectedList.forEach(item => {
componentRef.value.tableDataRef?.toggleRowSelection(item, true)
})
}
}
}, 50)
}
watch(() => unref(selectData), () => selectedTable(), { deep: true })
watch(() => componentRef.value && unref(componentRef).pager.page, () => {
selectData.value[unref(channel)!]?.length && selectedTable()
})
</script>
<style lang="scss" scoped>
.ls-input {
width: 240px;
}
:deep(.el-table__inner-wrapper) {
height: 365px;
overflow-y: scroll;
overflow-x: hidden;
}
</style>

View File

@ -1,107 +0,0 @@
<!--
* @Author: micky 1254597151@qq.com
* @Date: 2023-09-16 16:26:07
* @LastEditors: micky 1254597151@qq.com
* @LastEditTime: 2023-09-18 15:15:05
* @FilePath: \housekeeping-admin\src\components\channel-select-user\distributeTable.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div>
<el-form :model="channelForm" ref="channelFormRef" :inline="true" label-width="auto">
<el-form-item label="组别">
<el-select v-model="channelForm.groupId" placeholder="请选择" class="ls-input">
<el-option label="全部" value></el-option>
<el-option
v-for="group in groupLists"
:key="group.id"
:label="group.groupName"
:value="group.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="分销员名称">
<el-input
class="ls-input"
v-model="channelForm.name"
placeholder="请输入"
clearable
></el-input>
</el-form-item>
<el-form-item label="分销员ID">
<el-input
class="ls-input"
v-model="channelForm.distNum"
placeholder="请输入"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getLists"></el-button>
<el-button @click="resetParams"></el-button>
</el-form-item>
</el-form>
<div>
<el-table
ref="tableDataRef"
:data="pager.lists"
row-key="id"
border
style="width: 100%"
height="500"
@selection-change="parent?.handleSelectionChange"
>
<el-table-column
type="selection"
width="50"
:reserve-selection="true"
></el-table-column>
<el-table-column property="groupName" label="组别" min-width="200" />
<el-table-column property="name" label="分销员名称" min-width="160" />
<el-table-column property="distNum" label="分销员ID" min-width="160" />
</el-table>
</div>
<div class="flex justify-end mt-3">
<pagination v-model="pager" @change="getLists" />
</div>
</div>
</template>
<script setup lang="ts">
import type { ElTable } from 'element-plus'
import Pagination from '@/components/pagination/index.vue'
import { usePaging } from '@/hooks/usePaging'
import { useCommon } from '@/hooks/useCommon'
import { apiDistributorLists } from '@/api/distributor/lists'
import { CHANNEL_INJECTION_KEY } from '@/config/symbol'
const tableDataRef = ref<InstanceType<typeof ElTable>>()
const channelForm = reactive({
name: '',
groupId: '',
distNum: ''
})
const { pager, getLists, resetPage, resetParams } = usePaging({
size: 10,
fetchFun: apiDistributorLists,
params: channelForm
})
const { groupLists, fetchGroupList } = useCommon()
const parent = inject(CHANNEL_INJECTION_KEY)
onMounted(() => {
getLists()
fetchGroupList()
})
defineExpose({
tableDataRef,
pager
})
</script>
<style scoped>
.ls-input {
width: 210px;
}
</style>

View File

@ -1,35 +0,0 @@
<template>
<div class="flex flex-col">
<channel-popup v-model="selectData">
<slot name="popup"></slot>
</channel-popup>
<table-detail v-model="selectData"></table-detail>
</div>
</template>
<script lang="ts" setup>
import type { PropType } from 'vue'
import channelPopup from './channel-popup.vue'
import tableDetail from './table-detail.vue'
import { CHANNEL_INJECTION_KEY } from '@/config/symbol'
const props = defineProps({
modelValue: {
type: Array as PropType<any>,
default: () => []
}
})
const emit = defineEmits(['update:modelValue'])
const parent = inject(CHANNEL_INJECTION_KEY)
// const channel = computed(() => parent?.channel.value)
const selectData = ref<Record<number, any[]>>({})
watch(
() => unref(selectData),
val => {
emit('update:modelValue', unref(val))
// emit('update:modelValue', val[unref(channel)!])
}
)
</script>

View File

@ -1,84 +0,0 @@
<!--
* @Author: micky 1254597151@qq.com
* @Date: 2023-09-16 16:26:07
* @LastEditors: micky 1254597151@qq.com
* @LastEditTime: 2023-09-18 16:46:02
* @FilePath: \housekeeping-admin\src\components\channel-select-user\table-detail.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div class="mt-5" v-if="selectData.length">
<el-table ref="tableDataRef" :data="selectData" height="200">
<el-table-column
v-for="column in columns"
:key="column.prop"
:prop="column.prop"
:label="column.label"
width="160"
:formatter="row => parseEmpty(row, column.prop)"
/>
<el-table-column label="操作" width="120" fixed="right">
<template #default="scope">
<div class="flex">
<el-button type="primary" link @click="handleDeleteItem(scope.$index)">
移除
</el-button>
</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { CHANNEL_INJECTION_KEY } from '@/config/symbol';
import { parseEmpty } from '@/utils/util'
import { ChannelEnum } from '@/enums/modeEnum';
const props = withDefaults(
defineProps<{
modelValue?: any
}>(),
{
modelValue: {},
}
)
const emit = defineEmits(['update:modelValue'])
const parent = inject(CHANNEL_INJECTION_KEY)
const channel = computed(() => parent?.channel.value)
const selectData: any = computed(() => props.modelValue[unref(channel)!] || [])
const columns = ref<any[]>([])
/**生成column字段 */
function generateColumns() {
if (channel.value === ChannelEnum.DISTBUTOR) {
columns.value = [
{ prop: 'groupName', label: '组别' },
{ prop: 'name', label: '分销员名称' },
]
} else {
columns.value = [
{ prop: 'nickname', label: '用户名称' },
{ prop: 'username', label: '用户账号' },
{ prop: 'mobile', label: '手机号码' },
]
}
}
/**切换渠道生成不同的column */
watch(() => unref(channel), () => generateColumns(), { immediate: true })
const handleDeleteItem = (index: number) => {
selectData.value.splice(index, 1)
}
</script>
<style lang="scss" scoped>
.move {
@media screen and (max-width: 1536px) {
@apply overflow-scroll;
}
}
</style>

View File

@ -1,74 +0,0 @@
<!--
* @Author: micky 1254597151@qq.com
* @Date: 2023-09-16 16:26:07
* @LastEditors: micky 1254597151@qq.com
* @LastEditTime: 2023-09-18 15:14:26
* @FilePath: \housekeeping-admin\src\components\channel-select-user\userTable.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div>
<el-form :model="userForm" ref="channelFormRef" :inline="true" label-width="auto">
<el-form-item label="用户信息">
<el-input class="w-[300px]" v-model="userForm.keyword" placeholder="用户名称/用户账号/手机号码" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getLists"></el-button>
<el-button @click="resetParams"></el-button>
</el-form-item>
</el-form>
<div>
<el-table
ref="tableDataRef"
:data="pager.lists"
row-key="id"
border
style="width: 100%"
height="480"
@selection-change="parent?.handleSelectionChange"
>
<el-table-column type="selection" width="50" :reserve-selection="true"></el-table-column>
<el-table-column property="nickname" label="用户名称" min-width="200" />
<el-table-column property="username" label="用户账号" min-width="160" />
<el-table-column property="mobile" label="手机号码" min-width="160" :formatter="row => parseEmpty(row, 'mobile')" />
</el-table>
</div>
<div class="flex justify-end mt-3">
<pagination v-model="pager" @change="getLists" />
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
import type { ElTable } from 'element-plus'
import Pagination from '@/components/pagination/index.vue'
import { usePaging } from '@/hooks/usePaging'
import { apiUserLists } from '@/api/user'
import { parseEmpty } from '@/utils/util'
import { CHANNEL_INJECTION_KEY } from '@/config/symbol'
const tableDataRef = ref<InstanceType<typeof ElTable>>()
const userForm = reactive({
keyword: '',
type: 0
})
const { pager, getLists, resetPage, resetParams } = usePaging({
size: 10,
fetchFun: apiUserLists,
params: userForm
})
const parent = inject(CHANNEL_INJECTION_KEY)
onMounted(getLists)
defineExpose({
tableDataRef,
pager
})
</script>
<style scoped>
.ls-input {
width: 210px;
}
</style>

View File

@ -1,30 +0,0 @@
<template>
<div class="footer-btns">
<div class="footer-btns__content" :style="fixed ? 'position: fixed' : ''">
<slot></slot>
</div>
</div>
</template>
<script lang="ts" setup>
defineProps({
fixed: {
type: Boolean,
default: true
}
})
</script>
<style scoped lang="scss">
.footer-btns {
height: 65px;
&__content {
bottom: 0;
height: 65px;
right: 0;
left: var(--aside-width);
z-index: 999;
@apply flex justify-center items-center shadow bg-body;
}
}
</style>

View File

@ -1,191 +0,0 @@
<template>
<popup
class="inline mr-3"
:clickModalClose="false"
title="选择服务"
:center="true"
@close="handleClose(serviceFormRef)"
@confirm="handleConfirm"
@open="handleOpen"
width="1050px"
>
<template #trigger>
<slot></slot>
</template>
<el-form :model="serviceForm" ref="serviceFormRef" :inline="true" label-width="auto">
<el-form-item label="服务名称">
<el-input
class="ls-input"
v-model="serviceForm.name"
placeholder="请输入"
clearable
></el-input>
</el-form-item>
<el-form-item label="服务分类">
<el-select
v-model="serviceForm.categoryId"
placeholder="请选择"
class="ls-input"
clearable
>
<el-option
v-for="category in categoryLists"
:key="category.id"
:label="category.name"
:value="category.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getLists"></el-button>
<el-button @click="resetParams"></el-button>
</el-form-item>
</el-form>
<div>
<el-table
ref="tableDataRef"
:data="pager.lists"
row-key="id"
border
style="width: 100%"
@selection-change="handleSelectionChange"
height="500"
>
<el-table-column
type="selection"
width="50"
:reserve-selection="true"
></el-table-column>
<el-table-column
property="name"
label="服务名称"
min-width="200"
show-overflow-tooltip
/>
<el-table-column property="image" label="服务图片" min-width="100">
<template #default="scope">
<div class="flex items-center">
<el-image
style="width: 48px; height: 48px"
:src="scope.row.image"
:fit="'cover'"
/>
</div>
</template>
</el-table-column>
<el-table-column property="category" label="服务分类" min-width="160" />
</el-table>
</div>
<div class="flex justify-end mt-3">
<pagination v-model="pager" @change="getLists" />
</div>
</popup>
</template>
<script lang="ts" setup>
import { computed, watchEffect, ref, reactive } from 'vue'
import type { ElForm, ElTable, FormInstance } from 'element-plus'
import Popup from '@/components/popup/index.vue'
import Pagination from '@/components/pagination/index.vue'
import { usePaging } from '@/hooks/usePaging'
import { apiServiceLists } from '@/api/service/lists'
import { deepClone } from '@/utils/util'
import { CHANNEL_INJECTION_KEY } from '@/config/symbol'
interface serviceFormObj {
name?: string
status?: number | string
categoryId: number | string
}
const props = withDefaults(
defineProps<{
modelValue: any
}>(),
{
modelValue: []
}
)
const emit = defineEmits(['update:modelValue'])
const parent = inject(CHANNEL_INJECTION_KEY)
const categoryLists = computed(() => parent?.categoryLists.value)
const serviceFormRef = ref<InstanceType<typeof ElForm>>()
const tableDataRef = ref<InstanceType<typeof ElTable>>()
const selectData = ref<Array<object> | null>(props.modelValue)
const serviceForm = reactive<serviceFormObj>({
name: '',
status: '',
categoryId: ''
})
const { pager, getLists, resetPage, resetParams } = usePaging({
size: 10,
fetchFun: apiServiceLists,
params: serviceForm
})
//
const handleSelectionChange = (val: Event | any) => {
selectData.value = val
}
//
const handleClose = (formEl: FormInstance | undefined): void => {
if (!formEl) return
formEl.resetFields()
}
//
const handleConfirm = (): void => {
//
emit('update:modelValue', deepClone(selectData.value))
}
getLists()
watchEffect(() => {
selectData.value = props.modelValue
})
const handleOpen = () => {
nextTick(() => selectTable())
}
/**表格选中效果 */
function selectTable() {
setTimeout(() => {
const tableData = pager.lists
const selectedIds = props.modelValue?.map((item: any) => item.id) as number[]
const selectedList = tableData.filter(data => selectedIds.includes(data.id))
/**避免tableDataRef为undefined */
tableData.forEach(data => {
tableDataRef.value?.toggleRowSelection(data, false)
})
selectedList.forEach(item => {
tableDataRef.value?.toggleRowSelection(item, true)
})
}, 50)
}
watch(
() => props.modelValue,
() => selectTable(),
{ deep: true }
)
watch(
() => pager.page,
() => props.modelValue.length && selectTable()
)
</script>
<style lang="scss" scoped>
.ls-input {
width: 240px;
}
:deep(.el-table__inner-wrapper) {
height: 365px;
overflow-y: scroll;
overflow-x: hidden;
}
</style>

View File

@ -1,41 +0,0 @@
<template>
<div class="flex flex-col">
<good-popup v-model="selectData">
<slot name="popup"></slot>
</good-popup>
<table-detail v-model="selectData" :disabled="disabled"></table-detail>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import goodPopup from './good-popup.vue'
import tableDetail from './table-detail.vue'
const props = withDefaults(
defineProps<{
modelValue?: any
selectData: any
disabled?: boolean
}>(),
{
modelValue: [],
selectData: [],
disabled: false
}
)
const emit = defineEmits(['update:modelValue', 'update:selectData'])
const selectData: any = computed({
get: () => {
return props.selectData || []
},
set: (value) => {
emit(
'update:modelValue',
value.map((item: Event | any) => item.id)
)
emit('update:selectData', value)
}
})
</script>

View File

@ -1,71 +0,0 @@
<!--
* @Author: micky 1254597151@qq.com
* @Date: 2023-09-16 16:26:07
* @LastEditors: micky 1254597151@qq.com
* @LastEditTime: 2023-09-18 16:48:12
* @FilePath: \housekeeping-admin\src\components\good-select\table-detail.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div class="mt-5" v-if="selectData.length">
<el-table ref="tableDataRef" :data="selectData" height="200">
<el-table-column label="服务名称" width="240">
<template #default="scope">
<div class="flex items-center">
<div class="w-[60px] h-[60px]">
<el-image
style="width: 60px; height: 60px"
:src="scope.row.image"
:fit="'cover'"
/>
</div>
<el-tooltip :content="scope.row.name" placement="top">
<div class="ml-2 truncate">{{ scope.row.name }}</div>
</el-tooltip>
</div>
</template>
</el-table-column>
<el-table-column property="category" label="服务分类" width="200" />
<el-table-column label="操作" width="120" fixed="right">
<template #default="scope">
<div class="flex">
<el-button type="primary" link @click="handleDeleteItem(scope.$index)"
:disabled="disabled">移除</el-button>
</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
const props = withDefaults(
defineProps<{
modelValue: any
disabled: boolean
}>(),
{
modelValue: [],
disabled: false
}
)
const emit = defineEmits(['update:modelValue'])
const selectData: any = computed(() => {
return props.modelValue || []
})
const handleDeleteItem = (index: number) => {
selectData.value.splice(index, 1)
emit('update:modelValue', selectData.value)
}
</script>
<style lang="scss" scoped>
.move {
@media screen and (max-width: 1536px) {
@apply overflow-scroll;
}
}
</style>

View File

@ -1,55 +0,0 @@
<template>
<popup class="mr-2 flex" :clickModalClose="false" :title="title" :center="true" width="450px" confirmButtonText="" cancelButtonText="关闭">
<template #trigger>
<div>
<el-button type="primary" link>{{ btnText }}</el-button>
</div>
</template>
<el-form :model="dataForm" ref="formRef" :inline="true" label-width="auto" :disabled="true">
<el-form-item label="已提现金额">
<el-input v-model="dataForm.alreadyWithdraw">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="可提现金额">
<el-input v-model="dataForm.canWithdrawCommission">
<template #append></template>
</el-input>
</el-form-item>
<el-form-item label="待结算金额">
<el-input v-model="dataForm.toBeSettledMoney">
<template #append></template>
</el-input>
</el-form-item>
</el-form>
</popup>
</template>
<script lang="ts" setup>
import { ref, reactive, toRefs, onMounted } from 'vue'
const title = ref('查看金额详情')
const dataForm = reactive({
alreadyWithdraw: '',
canWithdrawCommission: '',
toBeSettledMoney: ''
})
const props = withDefaults(
defineProps<{
rowData: any
btnText: string
}>(),
{
rowData: {},
btnText: ''
}
)
const showDetail = (row: any) => {
const keys = Object.keys(dataForm)
keys.map(key => {
dataForm[key] = row[key] || '0'
})
title.value = `${row.name}-金额详情`
}
showDetail(props.rowData)
</script>

View File

@ -1,54 +0,0 @@
<!--
* @Author: micky 1254597151@qq.com
* @Date: 2023-08-14 15:56:31
* @LastEditors: micky 1254597151@qq.com
* @LastEditTime: 2023-09-04 17:26:11
* @FilePath: \housekeeping-admin\src\components\service-area\index.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div class="flex flex-col">
<!-- 服务选择框 Start -->
<area-popup v-model="selectData">
<slot name="popup"></slot>
</area-popup>
<!-- 服务选择框 End -->
<!-- Table Start -->
<table-detail v-model="selectData" :disabled="disabled"></table-detail>
<!-- Table End -->
</div>
</template>
<script lang="ts" setup>
import { withDefaults, computed } from 'vue'
// import areaPopup from './area-popup.vue'
import tableDetail from './table-detail.vue'
const props = withDefaults(
defineProps<{
modelValue?: any
selectData: any
disabled?: boolean
}>(),
{
modelValue: [],
selectData: [],
disabled: false
}
)
const emit = defineEmits(['update:modelValue', 'update:selectData'])
const selectData: any = computed({
get: () => {
return props.selectData || []
},
set: value => {
emit(
'update:modelValue',
value.map((item: Event | any) => item.id)
)
emit('update:selectData', value)
}
})
</script>

View File

@ -1,43 +0,0 @@
<template>
<div class="mt-5" v-if="selectData.length">
<el-table ref="tableDataRef" :data="selectData">
<el-table-column property="name" label="服务区名称" width="240">
</el-table-column>
<el-table-column label="操作" width="120" fixed="right">
<template #default="scope">
<div class="flex">
<el-button type="primary" link @click="handleDeleteItem(scope.$index)"
:disabled="disabled">移除</el-button>
</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script lang="ts" setup>
import { computed, withDefaults } from 'vue'
const props = withDefaults(
defineProps<{
modelValue: any
disabled: boolean
}>(),
{
modelValue: [],
disabled: false
}
)
const emit = defineEmits(['update:modelValue'])
const selectData: any = computed(() => {
return props.modelValue || []
})
const handleDeleteItem = (index: number) => {
selectData.value.splice(index, 1)
emit('update:modelValue', selectData.value)
}
</script>
<style lang="scss" scoped></style>

View File

@ -1,61 +0,0 @@
<template>
<div class="flex flex-col">
<!-- 服务选择框 Start -->
<service-popup v-model="selectData">
<slot name="popup"></slot>
</service-popup>
<!-- 服务选择框 End -->
<!-- Table Start -->
<table-detail v-model="selectData" :disabled="disabled"></table-detail>
<!-- Table End -->
</div>
</template>
<script lang="ts" setup>
import { withDefaults, computed } from 'vue'
import servicePopup from './service-popup.vue'
import tableDetail from './table-detail.vue'
/** Props Start **/
const props = withDefaults(
defineProps<{
modelValue?: any
selectData: any
disabled?: boolean
}>(),
{
modelValue: [],
selectData: [],
disabled: false
}
)
/** Props End **/
/** Emit Start **/
const emit = defineEmits(['update:modelValue', 'update:selectData'])
/** Emit End **/
/** Computed Start **/
const selectData: any = computed({
get: () => {
return props.selectData || []
},
set: (value) => {
emit(
'update:modelValue',
value.map((item: Event | any) => item.id)
)
emit('update:selectData', value)
}
})
/** Computed End **/
</script>
<!-- <style lang="scss" scoped>
.move {
@media screen and (max-width: 1536px) {
@apply overflow-scroll;
}
}
</style> -->

View File

@ -1,170 +0,0 @@
<template>
<popup class="inline mr-3" :clickModalClose="false" title="选择服务" :center="true" @close="handleClose(serviceFormRef)"
@confirm="handleConfirm" @open="toggleSelection" width="1150px">
<!-- Trigger Start -->
<template #trigger>
<!-- trigger -->
<slot></slot>
</template>
<!-- Trigger End -->
<!-- Form Start -->
<el-form :model="serviceForm" ref="serviceFormRef" :inline="true" label-width="auto">
<el-form-item label="服务名称">
<el-input class="ls-input" v-model="serviceForm.name" placeholder="请输入"></el-input>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="serviceForm.status" placeholder="请选择" class="ls-input">
<el-option label="全部" value></el-option>
<el-option label="销售中" value="1"></el-option>
<el-option label="仓库中" value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getLists"></el-button>
<el-button @click="resetParams"></el-button>
</el-form-item>
</el-form>
<!-- Form End -->
<!-- Table Start -->
<div>
<el-table ref="tableDataRef" :data="pager.lists" :row-key="getRowKeys" border style="width: 100%">
<el-table-column type="selection" width="50" :reserve-selection="true"></el-table-column>
<el-table-column label="服务名称" min-width="200">
<template #default="scope">
<div class="flex items-center">
<el-image style="width: 48px; height: 48px" :src="scope.row.image" :fit="'cover'" />
<el-tooltip :content="scope.row.name" placement="top">
<div class="w-16 ml-2 truncate">{{ scope.row.name }}</div>
</el-tooltip>
</div>
</template>
</el-table-column>
<el-table-column property="category" label="服务分类" min-width="160" />
<el-table-column property="price" label="价格" min-width="100" />
<el-table-column property="unit" label="单位" min-width="100" />
<el-table-column property="statusDesc" label="状态" min-width="120">
<template #default="scope">
<el-tag type="success" v-if="scope.row.status == 1"></el-tag>
<el-tag type="info" v-if="scope.row.status == 0"></el-tag>
</template>
</el-table-column>
<el-table-column property="createTime" label="创建日期" min-width="170" />
</el-table>
</div>
<!-- Table End -->
<!-- Footer Pagination Start -->
<div class="flex justify-end mt-2">
<pagination v-model="pager" @change="getLists" />
</div>
<!-- Footer Pagination End -->
</popup>
</template>
<script lang="ts" setup>
import { apiServiceLists } from '@/api/service/lists'
import Popup from '@/components/popup/index.vue'
import Pagination from '@/components/pagination/index.vue'
import type { ElForm } from 'element-plus'
import { ElTable } from 'element-plus'
import { usePaging } from '@/hooks/usePaging'
import { deepClone } from '@/utils/util'
import { computed, withDefaults, watchEffect, ref, reactive } from 'vue'
interface serviceFormObj {
name?: string
status?: number | string
}
type FormInstance = InstanceType<typeof ElForm>
const serviceFormRef = ref<FormInstance>()
const tableDataRef = ref<InstanceType<typeof ElTable>>()
const props = withDefaults(
defineProps<{
modelValue: any
}>(),
{
modelValue: []
}
)
const emit = defineEmits(['update:modelValue'])
const selectData = ref<Array<object> | null>(props.modelValue)
const serviceForm = reactive<serviceFormObj>({
name: '',
status: '1'
})
const toggleSelection = () => {
if (selectData.value!.length !== 0) {
pager.lists.forEach(item => {
tableDataRef.value?.toggleRowSelection(item, false)
})
; (selectData.value as []).forEach((item: any) => {
try {
pager.lists.forEach(listItem => {
setTimeout(() => {
if (listItem.id == item.id) {
tableDataRef?.value?.toggleRowSelection(listItem, true) //
// throw Error() //foreach
}
})
})
} catch { }
})
} else {
tableDataRef.value?.clearSelection()
}
}
const { pager, getLists, resetPage, resetParams } = usePaging({
size: 10,
fetchFun: apiServiceLists,
params: serviceForm,
nextFetchFun: toggleSelection
})
//
// const handleSelectionChange = (val: Event | any) => {
// selectData.value = [...val]
// console.log('selectData.value', val)
// }
//
const handleClose = (formEl: FormInstance | undefined): void => {
if (!formEl) return
formEl.resetFields()
}
//
const handleConfirm = (): void => {
//
emit('update:modelValue', tableDataRef?.value?.getSelectionRows())
}
getLists()
watchEffect(() => {
selectData.value = props.modelValue
})
//
const getRowKeys = row => {
return row.id
}
</script>
<style lang="scss" scoped>
.ls-input {
width: 240px;
}
:deep(.el-table__inner-wrapper) {
height: 565px;
overflow-y: scroll;
overflow-x: hidden;
}
</style>

View File

@ -1,91 +0,0 @@
<!--
* @Author: micky 1254597151@qq.com
* @Date: 2023-08-14 15:56:31
* @LastEditors: micky 1254597151@qq.com
* @LastEditTime: 2023-09-12 12:13:41
* @FilePath: \housekeeping-admin\src\components\service-select\table-detail.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<div class="mt-5" v-if="selectData.length">
<el-table ref="tableDataRef" :data="selectData">
<el-table-column label="服务名称" width="240">
<template #default="scope">
<div class="flex items-center">
<div class="w-[60px] h-[60px]">
<el-image style="width: 60px; height: 60px" :src="scope.row.image" :fit="'cover'" />
</div>
<el-tooltip :content="scope.row.name" placement="top">
<div class="ml-2 truncate">{{ scope.row.name }}</div>
</el-tooltip>
</div>
</template>
</el-table-column>
<el-table-column property="category" label="服务分类" width="200" />
<el-table-column property="price" label="价格" width="120" />
<el-table-column property="unit" label="单位" width="220" />
<el-table-column property="statusDesc" label="销售状态" width="200">
<template #default="scope">
<el-tag type="success" v-if="scope.row.status == 1"></el-tag>
<el-tag type="info" v-if="scope.row.status == 0"></el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建日期" min-width="205" />
<el-table-column label="操作" width="120" fixed="right">
<template #default="scope">
<div class="flex">
<el-button type="primary" link @click="handleDeleteItem(scope.$index)" :disabled="disabled">移除</el-button>
</div>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script lang="ts" setup>
import { computed, withDefaults } from 'vue'
/** Props Start **/
const props = withDefaults(
defineProps<{
modelValue: any
disabled: boolean
}>(),
{
modelValue: [],
disabled: false
}
)
/** Props End **/
/** Emit Start **/
const emit = defineEmits(['update:modelValue'])
/** Emit End **/
/** Computed Start **/
const selectData: any = computed(() => {
return props.modelValue || []
})
/** Computed End **/
/** Methods Start **/
const handleDeleteItem = (index: number) => {
selectData.value.splice(index, 1)
emit('update:modelValue', selectData.value)
}
/** Methods End **/
</script>
<style lang="scss" scoped>
.move {
@media screen and (max-width: 1536px) {
@apply overflow-scroll;
}
}
:deep(.el-table) {
max-height: 565px;
overflow-y: scroll;
overflow-x: hidden;
}
</style>