master
lzq 2026-02-06 17:43:46 +08:00
parent dfcad17fb4
commit 824d2402a9
20 changed files with 538 additions and 161 deletions

2
.env
View File

@ -8,6 +8,8 @@ VITE_APP_BASE_URL=/
# 服务器基础地址
VITE_HTTP_SERVER_BASE_URL=/api
VITE_HTTP_PROXY_TARGET=http://127.0.0.1:10086
VITE_HTTP_MAP_SERVER_BASE_URL=/api/map
VITE_HTTP_MAP_SERVER_PROXY_TARGET=https://apis.map.qq.com
VITE_WS_SERVER_BASE_URL=/api/fdx
VITE_WS_PROXY_TARGET=ws://127.0.0.1:10086

12
package-lock.json generated
View File

@ -11,7 +11,7 @@
"axios": "^1.11.0",
"decimal.js": "^10.6.0",
"echarts": "^5.4.1",
"element-plus": "^2.11.8",
"element-plus": "^2.13.2",
"luxon": "^3.7.1",
"mitt": "^3.0.1",
"nanoid": "^5.1.5",
@ -2971,9 +2971,9 @@
"license": "ISC"
},
"node_modules/element-plus": {
"version": "2.13.1",
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.13.1.tgz",
"integrity": "sha512-eG4BDBGdAsUGN6URH1PixzZb0ngdapLivIk1meghS1uEueLvQ3aljSKrCt5x6sYb6mUk8eGtzTQFgsPmLavQcA==",
"version": "2.13.2",
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.13.2.tgz",
"integrity": "sha512-Zjzm1NnFXGhV4LYZ6Ze9skPlYi2B4KAmN18FL63A3PZcjhDfroHwhtM6RE8BonlOPHXUnPQynH0BgaoEfvhrGw==",
"license": "MIT",
"dependencies": {
"@ctrl/tinycolor": "^3.4.1",
@ -2985,8 +2985,8 @@
"@vueuse/core": "^10.11.0",
"async-validator": "^4.2.5",
"dayjs": "^1.11.19",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"lodash": "^4.17.23",
"lodash-es": "^4.17.23",
"lodash-unified": "^1.0.3",
"memoize-one": "^6.0.0",
"normalize-wheel-es": "^1.2.0"

View File

@ -13,7 +13,7 @@
"axios": "^1.11.0",
"decimal.js": "^10.6.0",
"echarts": "^5.4.1",
"element-plus": "^2.11.8",
"element-plus": "^2.13.2",
"luxon": "^3.7.1",
"mitt": "^3.0.1",
"nanoid": "^5.1.5",

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -51,7 +51,7 @@
box-sizing border-box !important
& > .el-scrollbar > .el-scrollbar__wrap {
max-height calc(100vh - 400px)
max-height 850px
height unset
}
}

View File

@ -7,6 +7,14 @@ export const useAppSettingStore = defineStore('AppSetting', () => {
const language = ref<'zh' | 'en'>('zh')
const logo = ref<string | null>(null)
const collectedMenus = ref<AppTypes.Menu[]>([])
const defaultAddress = reactive({
lat: 31.96873,
lng: 118.798171,
province: '320000',
city: '320100',
provinceName: '江苏省',
cityName: '南京市',
})
const menus = ref<AppTypes.Menu[]>([])
const menuTree = ref<AppTypes.Menu[]>([])
@ -29,6 +37,7 @@ export const useAppSettingStore = defineStore('AppSetting', () => {
logo,
language,
stationId,
defaultAddress,
$reset,
}
}, {

View File

@ -13,6 +13,7 @@ export const appTitle = import.meta.env.VITE_APP_TITLE
*
*/
export const serverBaseUrl = import.meta.env.VITE_HTTP_SERVER_BASE_URL ?? ''
export const mapServerBaseUrl = import.meta.env.VITE_HTTP_MAP_SERVER_BASE_URL ?? ''
export const wsServerBaseUrl = import.meta.env.VITE_WS_SERVER_BASE_URL ?? '/'

View File

@ -21,6 +21,7 @@ type RuleType<T extends object> = Partial<Record<keyof T | string, Arrayable<For
export interface FormPanelType<T extends object> {
title: string
defaultFormData: T
detailsLoader: (id?: string) => Promise<T | undefined | null | void>
doSubmit: (data: T) => Promise<boolean | undefined | null | void>
rules: RuleType<T> | ((formData: T) => RuleType<T>)
@ -40,7 +41,7 @@ const component = defineComponent(
const showDialog = ref(false)
const loading = ref(false)
const formData = Utils.resetAble(reactive<T>({} as T))
const formData = Utils.resetAble(reactive<T>(props.defaultFormData))
function dialogCloseHandler() {
formData.$reset()
@ -134,7 +135,7 @@ const component = defineComponent(
},
{
name: 'AFormPanel',
props: [ 'title', 'detailsLoader', 'doSubmit', 'rules', 'watchForm', 'labelWidth', 'width', 'modal', 'appendToBody' ],
props: [ 'title', 'defaultFormData', 'detailsLoader', 'doSubmit', 'rules', 'watchForm', 'labelWidth', 'width', 'modal', 'appendToBody' ],
})
export interface AFormPanelInstance extends InstanceType<typeof component> {
@ -167,6 +168,10 @@ export function buildFormPanelProps<T extends object>(props: Partial<Exclude<For
props.watchForm.formItems = '_none_'
}
if (props.defaultFormData == null) {
props.defaultFormData = {} as T
}
return reactive({
title: props.title!,
detailsLoader: props.detailsLoader!,
@ -176,6 +181,7 @@ export function buildFormPanelProps<T extends object>(props: Partial<Exclude<For
labelWidth: props.labelWidth!,
width: props.width!,
modal: props.modal!,
defaultFormData: props.defaultFormData!,
appendToBody: props.appendToBody!,
} as FormPanelType<T>)
}

View File

@ -1,92 +0,0 @@
import { defineComponent } from 'vue'
import Types from '@/common/utils/types.ts'
const key = '3TGBZ-ZK7K5-CMNIK-ICIGZ-K6TYQ-HTBTZ'
// 32.087182, 118.797109
interface InitOption {
/**
*
*/
el: string | HTMLDivElement
/**
*
*/
center?: {
/**
*
*/
lat: number
/**
*
*/
lng: number
}
/**
*
*/
zoom?: number
/**
*
*/
pitch?: number
/**
*
*/
rotation?: number
}
function initMap({
el,
center,
zoom = 15,
pitch = 0,
rotation = 0,
}: InitOption) {
let centerLatLng: TMap.LatLng | undefined = undefined
if (center != null) {
centerLatLng = new TMap.LatLng(center.lat, center.lng)
}
if (Types.isString(el)) {
const htmlNode = document.getElementById(el as string)
if (htmlNode == null) {
throw new Error('地图容器不存在')
}
el = htmlNode as HTMLDivElement
}
return new TMap.Map(el, {
center: centerLatLng,
zoom,
pitch,
rotation,
})
}
export interface AMapType {
init: () => void
}
const component = defineComponent(
(_, ctx) => {
const el = ref<HTMLDivElement | undefined>(undefined)
const init = () => {
initMap({
el: el.value as HTMLDivElement,
center: {
lat: 32.087182,
lng: 118.797109,
},
})
}
ctx.expose({init})
return () => {
return (
<div ref={el}>
</div>)
}
},
)
export default component

View File

@ -0,0 +1,229 @@
<script lang="ts" setup>
import {
defineExpose,
defineProps,
reactive,
ref,
watchEffect,
} from 'vue'
import AmapApi, {
type Poi,
type SearchPlaceResult,
} from '@/components/a-map/amap-api.ts'
import {
ElOption,
ElPagination,
ElSelect,
} from 'element-plus'
import Strings from '@/common/utils/strings.ts'
const key = '3TGBZ-ZK7K5-CMNIK-ICIGZ-K6TYQ-HTBTZ'
interface AMapPropsType {
width?: string
mapConfig: {
lat: number
lng: number
/**
* 缩放级别
*/
zoom?: number
/**
* 俯仰角
*/
pitch?: number
/**
* 旋转角度
*/
rotation?: number
}
}
const props = withDefaults(
defineProps<AMapPropsType>(),
{
width: '500px',
},
)
const addressModel = defineModel<string>('address', {required: false})
const latModel = defineModel<number>('lat', {required: false})
const lngModel = defineModel<number>('lng', {required: false})
const areaModel = defineModel<number | string>('area', {required: false})
const areaNameModel = defineModel<string>('areaName', {required: false})
const mapWrapper = useTemplateRef<HTMLDivElement>('mapRef')
let map: TMap.Map | null = null
let multiMarker: TMap.MultiMarker | null = null
const paginationData = reactive<{
current: number
size: number
total: number
}>({
current: 1,
size: 10,
total: 0,
})
const pois = ref<Poi[]>([])
let keywords: string | undefined = undefined
const currentPoi = ref<string>('')
function onSelected(value: string) {
const poi = pois.value.find((it) => it.id === value)
if (!poi) return
addressModel.value = poi.title + '(' + poi.address + ')'
latModel.value = poi.location.lat
lngModel.value = poi.location.lng
areaModel.value = poi.ad_info.adcode
areaNameModel.value = poi.ad_info.city
}
function createMap() {
if (mapWrapper.value == null) {
console.error('地图容器不存在')
return null
}
if (map != null) return map
return new TMap.Map(mapWrapper.value, {
center: new TMap.LatLng(props.mapConfig.lat, props.mapConfig.lng),
zoom: props.mapConfig.zoom ?? 16,
pitch: props.mapConfig.pitch ?? 0,
rotation: props.mapConfig.rotation ?? 0,
})
}
function createMarkerLayer() {
if (map == null) return null
if (multiMarker != null) return multiMarker
return new TMap.MultiMarker({
map,
geometries: [
{
id: '1',
position: new TMap.LatLng(props.mapConfig.lat, props.mapConfig.lng),
},
],
})
}
watchEffect(() => {
if (Strings.isBlank(currentPoi.value)) return
const poi = pois.value.find((it) => it.id === currentPoi.value)
if (!poi) return
map?.setCenter(new TMap.LatLng(poi.location.lat, poi.location.lng))
multiMarker?.updateGeometries([
{
id: '1',
position: new TMap.LatLng(poi.location.lat, poi.location.lng),
},
])
})
function paginationChange() {
doSearch()
}
function doSearch(queryStr?: string) {
if (!Strings.isBlank(queryStr)) keywords = queryStr
if (Strings.isBlank(keywords)) return
AmapApi.searchPlace({
key,
keyword: keywords!,
boundary: {lat: props.mapConfig.lat, lng: props.mapConfig.lng},
page_size: paginationData.size,
page_index: paginationData.current,
get_subpois: 1,
}).then((res) => {
if (!res) return
const result = res as SearchPlaceResult
paginationData.total = result.count
pois.value = result.data
})
}
function init() {
if (mapWrapper.value == null) return
try {
map = createMap()
multiMarker = createMarkerLayer()
} catch (e) {
console.log(e)
}
}
function destroy() {
multiMarker?.destroy()
map?.destroy()
multiMarker = null
map = null
}
onMounted(() => {
nextTick(init)
})
onBeforeUnmount(destroy)
defineExpose({init, destroy})
</script>
<template>
<div class="a-map">
<ElSelect
v-model="currentPoi"
:placeholder="addressModel??'请搜索地点'"
:remote-method="doSearch"
filterable
no-data-text="暂无数据"
no-match-text="暂无数据"
remote
@change="onSelected">
<ElOption
v-for="item in pois"
:key="item.id"
:label="item.title+'('+item.address+')'"
:value="item.id"
/>
<template #footer>
<ElPagination
:background="true"
:current-page="paginationData.current"
:hide-on-single-page="false"
:page-size="paginationData.size"
:teleported="false"
:total="paginationData.total"
layout="total, prev, pager, next,"
@change="paginationChange"
@update:current-page="(val) => paginationData.current = val"
@update:page-size="(val) => paginationData.size = val"
/>
</template>
</ElSelect>
<div ref="mapRef" class="map-wrapper"></div>
</div>
</template>
<style lang="stylus" scoped>
.a-map {
width v-bind('props.width');
height 100%;
display flex;
flex-direction column;
gap 10px
:deep(.el-select) {
height 32px
width 100%;
}
}
.map-wrapper {
flex 1
width 100%;
}
:deep(.el-pagination) {
justify-content center
}
</style>

View File

@ -1 +1,113 @@
// https://apis.map.qq.com/ws/place/v1/search?boundary=nearby(40.040589,116.273543,1000)&keyword=公园&page_size=10&page_index=1&key=OB4BZ-D4W3U-*****
import axios from 'axios'
import { mapServerBaseUrl } from '@/common'
import mime from '@/common/utils/mime.ts'
import qs from 'qs'
const httpUtil = axios.create({
timeout: 10000,
baseURL: mapServerBaseUrl,
headers: {
Accept: mime.JSON,
},
})
interface SearchPlaceParam {
/**
*
*/
key: string;
/**
* UTF-896
*/
keyword: string;
/**
* nearby(,,[])
*/
boundary: {
lat: number
lng: number
radius?: number
auto_extend?: 0 | 1
};
/**
*
* 0 []1
*/
get_subpois?: 0 | 1;
filter?: string; // 筛选条件(分类筛选/排除分类/筛选有电话),可选
added_fields?: string; // 附加字段仅支持category_code可选
orderby?: '_distance'; // 排序方式,仅支持按距离排序,可选
page_size?: number; // 每页条目数1-20默认10可选
page_index?: number; // 页码默认1可选
output?: 'json' | 'jsonp'; // 返回格式默认json可选
callback?: string; // JSONP回调函数名可选
}
// 坐标类型
interface Location {
lat: number; // 纬度
lng: number; // 经度
}
// 行政区划信息类型
interface AdInfo {
adcode: number; // 行政区划代码
province: string; // 省份
city: string; // 城市(省直辖县级区划返回空)
district: string; // 区/县
}
export interface Poi {
id: string; // POI唯一标识
title: string; // POI名称
address: string; // 地址
tel: string; // 电话
category: string; // POI分类
category_code?: number; // 分类编码added_fields=category_code时返回
type: 0 | 1 | 2 | 3 | 4; // POI类型
location: Location; // 坐标
_distance: number; // 直线距离(米)
ad_info: AdInfo; // 行政区划信息
}
// 子地点类型
interface SubPoi extends Exclude<Poi, '_distance'> {
parent_id: string; // 主地点ID
}
// 周边搜索响应类型
export interface SearchPlaceResult {
status: number; // 状态码0为正常
message: string; // 状态说明
count: number; // 搜索结果总数最多返回200条
request_id: string; // 请求唯一标识
data: Poi[];
sub_pois?: SubPoi[]; // 子地点列表get_subpois=1时返回
}
const paramsSerializer = (params: any) => {
return qs.stringify(params, {indices: false, allowDots: true})
}
function searchPlace(params: SearchPlaceParam) {
return httpUtil.get<SearchPlaceResult>('/ws/place/v1/search', {
params: {
...params,
boundary: `nearby(${params.boundary.lat},${params.boundary.lng},${params.boundary.radius == null || params.boundary.radius < 10 ? 1000 : params.boundary.radius},${params.boundary.auto_extend ?? 1})`,
},
paramsSerializer,
responseType: 'json',
})
.then(res => {
if (res.data.status !== 0) return Promise.reject({message: res.data.message})
return res.data
})
.catch(err => {
ElMessage.error(err.message)
})
}
export default {
searchPlace,
}

View File

@ -8,6 +8,8 @@ interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
readonly VITE_APP_BASE_URL: string
readonly VITE_HTTP_SERVER_BASE_URL: string
readonly VITE_HTTP_MAP_SERVER_BASE_URL: string
readonly VITE_HTTP_MAP_SERVER_PROXY_TARGET: string
readonly VITE_HTTP_PROXY_TARGET: string
readonly VITE_WS_SERVER_BASE_URL: string
readonly VITE_WS_PROXY_TARGET: string

View File

@ -4,10 +4,8 @@
v-bind="tablePageProps">
<template #simpleFormItem="formData">
<ElFormItem label="站点名称">
<ElInput
v-model="formData.stationName"
placeholder="站点名称"/>
<ElFormItem>
<ElInput v-model="formData.stationName" clearable placeholder="站点名称" @clear="research"/>
</ElFormItem>
</template>
<template #columns>
@ -64,22 +62,22 @@ const tablePageProps = buildTablePageProps<StationTypes.SearchStationParam, Stat
stationFormIns.value?.open(row)
},
},
{
icon: 'Delete',
loading: false,
type: 'danger',
tooltip: '删除',
confirm: {
title: '是否删除当前数据',
},
action({row}) {
return StationApi.del([ row.id! ])
.then(() => {
ElMessage.success('删除成功')
return true
})
},
},
/* {
icon: 'Delete',
loading: false,
type: 'danger',
tooltip: '删除',
confirm: {
title: '是否删除当前数据',
},
action({row}) {
return StationApi.del([ row.id! ])
.then(() => {
ElMessage.success('删除成功')
return true
})
},
}, */
],
},
},

View File

@ -7,26 +7,35 @@
<ElFormItem label="站点名称" prop="stationName">
<ElInput v-model="formData.stationName" placeholder="站点名称"/>
</ElFormItem>
<ElFormItem label="管理员账号" prop="userId">
<UserDropTable v-model="formData.userId"/>
<ElFormItem label="企业代码" prop="uscc">
<ElInput v-model="formData.uscc" placeholder="统一社会信用代码"/>
</ElFormItem>
<ElFormItem label="企业名称" prop="orgName">
<ElInput v-model="formData.orgInfo.orgName" placeholder="企业名称"/>
<ElInput v-model="formData.orgName" placeholder="企业名称"/>
</ElFormItem>
<ElFormItem label="管理员账号" prop="userId">
<UserDropTable v-model="formData.userId" :placeholder="formData.username"/>
</ElFormItem>
<ElFormItem label="管理员姓名" prop="customerName">
<ElInput v-model="formData.customerName" placeholder="管理员姓名"/>
</ElFormItem>
<ElFormItem label="企业代码" prop="uscc">
<ElInput v-model="formData.orgInfo.uscc" placeholder="统一社会信用代码"/>
</ElFormItem>
<ElFormItem label="管理员电话" prop="phone">
<ElInput v-model="formData.phone" placeholder="管理员电话"/>
</ElFormItem>
<ElFormItem label="地址" prop="address">
<ElInput v-model="formData.address" placeholder="详细地址"/>
<AMap
ref="amap"
v-model:address="formData.address"
v-model:area="formData.area"
v-model:areaName="formData.areaName"
v-model:lat="formData.lat"
v-model:lng="formData.lng"
:map-config="{
lat:appSettingStore.defaultAddress.lat,
lng:appSettingStore.defaultAddress.lng,
}"
class="amap" width="700px"/>
</ElFormItem>
<AMap ref="amap" class="amap"/>
</div>
</template>
</AFormPanel>
@ -40,7 +49,10 @@ import AFormPanel, {
buildFormPanelProps,
} from '@/components/a-form-panel/AFormPanel.tsx'
import UserDropTable from '@/pages/sys/user/UserDropTable.vue'
import AMap, { type AMapType } from '@/components/a-map/AMap.tsx'
import AMap from '@/components/a-map/AMap.vue'
import { useAppSettingStore } from '@/common/app/app-setting-store.ts'
const appSettingStore = useAppSettingStore()
const props = withDefaults(defineProps<{
research?: () => void
@ -49,32 +61,116 @@ const props = withDefaults(defineProps<{
},
})
const amapIns = useTemplateRef<AMapType>('amap')
interface StationFormType {
id?: string
//
stationName?: string
//
province?: string
//
city?: string
//
area?: string
//
town?: string
//
provinceName?: string
//
cityName?: string
//
areaName?: string
//
townName?: string
//
address?: string
//
lng?: number
//
lat?: number
//
userId?: string
username?: string
customerName?: string
phone?: string
//
uscc?: string
//
orgName?: string
}
const formPanelIns = useTemplateRef<AFormPanelInstance>('formPanel')
const status = ref<'add' | 'modify'>('add')
type T = StationTypes.SearchStationResult & StationTypes.AddStationParam
const formPanelProps = buildFormPanelProps<T>({
const formPanelProps = buildFormPanelProps<StationFormType>({
title: status.value === 'add' ? '新建站点' : '修改站点',
labelWidth: '100px',
detailsLoader(id?: string) {
if (Strings.isBlank(id)) {
status.value = 'add'
return Promise.resolve({
orgInfo: {},
} as T)
return Promise.resolve()
} else {
status.value = 'modify'
return StationApi
.detail(id!)
.then(res => res.data)
.then(res => {
return {
id: res.data.id,
stationName: res.data.stationName,
province: res.data.province,
city: res.data.city,
area: res.data.area,
town: res.data.town,
provinceName: res.data.provinceName,
cityName: res.data.cityName,
areaName: res.data.areaName,
townName: res.data.townName,
address: res.data.address,
lng: res.data.lng,
lat: res.data.lat,
userId: res.data.customer.userId,
username: res.data.customer.username,
customerName: res.data.customer.customerName,
phone: res.data.customer.phone,
uscc: res.data.customer.uscc,
orgName: res.data.customer.orgName,
}
})
}
},
doSubmit(data) {
if (status.value === 'add') {
return StationApi.add(data)
return StationApi.add({
stationName: data.stationName,
area: data.area,
areaName: data.areaName,
address: data.address,
lng: data.lng,
lat: data.lat,
userId: data.userId,
customerName: data.customerName,
phone: data.phone,
orgInfo: {
uscc: data.uscc,
orgName: data.orgName,
},
})
.then(props.research)
} else {
return StationApi.modify(data)
return StationApi.modify({
id: data.id,
stationName: data.stationName,
area: data.area,
areaName: data.areaName,
address: data.address,
lng: data.lng,
lat: data.lat,
userId: data.userId,
customerName: data.customerName,
phone: data.phone,
orgInfo: {
uscc: data.uscc,
orgName: data.orgName,
},
})
.then(props.research)
}
},
@ -93,33 +189,25 @@ const formPanelProps = buildFormPanelProps<T>({
defineExpose({
open(data?: ProjectTypes.SearchProjectResult) {
formPanelIns.value?.open(data?.id)
nextTick(() => {
amapIns.value?.init()
})
},
})
</script>
<style lang="stylus" scoped>
.form-items {
grid-template-columns: 1fr 1fr;
grid-template-areas ". address" \
". map" \
". map" \
". map" \
". map" \
". map" \
". map";
grid-template-areas "a1 a4" \
"a2 a5" \
"a3 a6" \
"a7 a7";
gap 10px
:deep(.el-form-item):nth-child(7) {
grid-area address
:deep(.el-form-item) {
align-items start
}
for val, i in (a1 a2 a3 a4 a5 a6 a7) {
:deep(.el-form-item):nth-child({i+1}) {
grid-area val
}
}
}
.amap {
width 500px
height 232px
grid-area map
}
</style>

View File

@ -9,7 +9,9 @@ declare global {
interface CustomerInfo {
id?: string
userId?: string
username?: string
uscc?: string
// 客户姓名
customerName?: string
// 客户联系电话
@ -134,6 +136,11 @@ declare global {
lng?: number
// 纬度
lat?: number
// 账号
userId?: string
customerName?: string
phone?: string
orgInfo?: OrgInfo
}
}
}

View File

@ -50,15 +50,17 @@ const formPanelIns = useTemplateRef<AFormPanelInstance>('formPanel')
const uploaderIns = useTemplateRef<InstanceType<typeof Uploader>>('uploader')
const status = ref<'add' | 'modify'>('add')
const formPanelProps = buildFormPanelProps<GoodsCategoryTypes.SearchGoodsCategoryResult>({
title: status.value === 'add' ? '新建产品分类' : '修改产品分类',
title: '新建产品分类',
detailsLoader(id?: string) {
if (Strings.isBlank(id)) {
status.value = 'add'
formPanelProps.title = '新建产品分类'
return Promise.resolve({
bizType: props.defaultBizType,
sort: 0,
} as GoodsCategoryTypes.SearchGoodsCategoryResult)
} else {
formPanelProps.title = '修改产品分类'
status.value = 'modify'
return GoodsCategoryApi.detail(id!)
.then((res) => {
@ -72,6 +74,7 @@ const formPanelProps = buildFormPanelProps<GoodsCategoryTypes.SearchGoodsCategor
return GoodsCategoryApi.add({
bizType: data.bizType,
categoryName: data.categoryName,
sn: data.bizType === bizType.HuiShouPin ? data.sn : undefined,
picture: data.picture,
sort: data.sort,
memo: data.memo,

View File

@ -44,6 +44,7 @@ declare global {
id?: string
// 业务类型字典代码biz_typeZaiShengPin-->再生品、HuiShouPin-->回收品、QiTa-->其他
bizType?: string
sn?: string
// 分类名称
categoryName?: string
// 图片

View File

@ -2,6 +2,9 @@
import ADropTable from '@/components/a-drop-table/ADropTable.vue'
import UserApi from '@/pages/sys/user/user-api.ts'
defineProps<{
placeholder?: string
}>()
const model = defineModel<string | undefined | null>()
const dropTableColumns = [
{
@ -23,5 +26,6 @@ const dropTableLoader = (param: UserTypes.SearchUserParam) => {
<ADropTable v-model="model"
:columns="dropTableColumns"
:loader="dropTableLoader"
:placeholder="placeholder"
display-field="username"/>
</template>

View File

@ -64,6 +64,13 @@ export default defineConfig((configEnv) => {
host: '0.0.0.0',
port: 5173,
proxy: {
[env.VITE_HTTP_MAP_SERVER_BASE_URL]: {
proxyTimeout: 10000,
target: env.VITE_HTTP_MAP_SERVER_PROXY_TARGET,
secure: false,
changeOrigin: true,
rewrite: (path) => (env.VITE_HTTP_MAP_SERVER_BASE_URL == null || env.VITE_HTTP_MAP_SERVER_BASE_URL == '/' ? path : path.replace(new RegExp(env.VITE_HTTP_MAP_SERVER_BASE_URL), '')),
} as ProxyOptions,
[env.VITE_HTTP_SERVER_BASE_URL]: {
proxyTimeout: 10000,
target: env.VITE_HTTP_PROXY_TARGET,