123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742 |
- <template>
- <BasicDrawer
- v-bind="$attrs"
- @register="registerDrawer"
- showFooter
- :title="getTitle"
- :showDetailBack="false"
- width="60%"
- @ok="handleSubmit"
- @close="handleClose"
- >
- <div class="entry-x">
- <BasicForm @register="registerForm">
- <template #map>
- <!-- <Card style="width: 300px; height: 300px"> -->
- <div ref="wrapRef" style="width: 100%; height: 400px"></div>
- <!-- </Card> -->
- </template>
- <!-- ="{ model, field }" -->
- <template #detailAddr>
- <a-input
- class="live-drawer"
- v-bind="$attrs"
- v-model:value="detailAddr"
- :allowClear="true"
- placeholder=""
- >
- <template #addonAfter>
- <a-button type="primary" class="mr-10px" @click="handleMapSearch">
- {{ t('common.queryText') }}
- </a-button>
- <a-button @click="handleMapReset"> {{ t('common.resetText') }}</a-button>
- </template>
- </a-input>
- </template>
- <template #sceneNum="{ model, field }">
- <Select
- :disabled="isUpdate"
- v-bind="$attrs"
- v-model:value="model[field]"
- @change="handleChange"
- @search="handleSearch"
- showSearch
- placeholder="请选择场景链接"
- :options="getOptions"
- :filterOption="filterOption"
- />
- </template>
- </BasicForm>
- </div>
- </BasicDrawer>
- </template>
- <script lang="ts">
- import { defineComponent, ref, computed, unref, nextTick, reactive } from 'vue';
- import { BasicForm, useForm, FormSchema } from '/@/components/Form/index';
- // import { Card } from 'ant-design-vue';
- import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
- import { useMessage } from '/@/hooks/web/useMessage';
- import { useI18n } from '/@/hooks/web/useI18n';
- import { useUserStore } from '/@/store/modules/user';
- import { data as CascaderData, getCode } from '/@/utils/cascaderData';
- import { ListApi } from '/@/api/scene/list';
- import { Select } from 'ant-design-vue';
- import {
- brandTypeListApi,
- uploadLiveApi,
- getAllSceneApi,
- // uploadLiveVideoApi,
- addSave,
- getLiveInfoApi,
- brandUpdateApi,
- // LiveSceneDeleteApi,
- } from '/@/api/scene/live';
- import { useScript } from '/@/hooks/web/useScript';
- import { staffListApi } from '/@/api/staff/list';
- const A_MAP_URL = 'https://webapi.amap.com/maps?v=2.0&key=e661b00bdf2c44cccf71ef6070ef41b8';
- // const A_MAP_URL = 'https://webapi.amap.com/maps?v=2.0&key=5a2d384532ae531bf99bd8487c4f03d2';
- // const A_MAP_URL = 'https://webapi.amap.com/maps?v=1.4.10&key=e661b00bdf2c44cccf71ef6070ef41b8';
- //webapi.amap.com/maps?v=1.4.10&key=e661b00bdf2c44cccf71ef6070ef41b8
- // Card
- export default defineComponent({
- name: 'MenuDrawer',
- components: { BasicDrawer, BasicForm, Select },
- emits: ['success', 'register'],
- setup(_, { emit }) {
- const isUpdate = ref(true);
- const detailAddr = ref('');
- const userStore = useUserStore();
- const token = userStore.getToken;
- const userinfo = computed(() => userStore.getUserInfo);
- const wrapRef = ref<HTMLDivElement | null>(null);
- const sceneNumOption = reactive({
- list: [],
- allList: [],
- });
- const getOptions = computed(() => {
- return sceneNumOption.list;
- });
- interface AddressComponentType {
- city: string;
- district: string;
- province: string;
- }
- interface GeocodesType {
- adcode: string;
- addressComponent: AddressComponentType;
- formattedAddress: string;
- location: {
- lng: number;
- lat: number;
- };
- }
- interface infoItem {
- province?: string;
- city?: string;
- address?: string;
- district?: string;
- picList?: string[];
- appListPicUrl?: string[];
- introduceVideo?: string[];
- location?: string[];
- }
- let map;
- // Lat(120.262337, 30.178285),
- const myData = reactive({
- sceneUrl: '',
- id: '',
- introduceVideoCover: '',
- });
- const filterOption = (input, option) => {
- return option.sceneName.includes(input.toLowerCase());
- };
- const defaultAddress = reactive({
- address: '山阴路688号恒隆广场B座1217',
- // address: '权晖花园21栋',
- lng: 120.262337,
- lat: 30.178285,
- location: ['浙江省', '杭州市', '滨江区'],
- province: '浙江省',
- city: '杭州市',
- district: '萧山区',
- });
- const { toPromise } = useScript({ src: A_MAP_URL });
- const { t } = useI18n();
- const { createMessage } = useMessage();
- const schemas: FormSchema[] = [
- {
- field: 'type',
- label: t('routes.scenes.liveType'),
- component: 'ApiSelect',
- required: true,
- itemProps: {
- validateTrigger: 'blur',
- },
- componentProps: {
- api: brandTypeListApi,
- resultField: 'list',
- labelField: 'name',
- valueField: 'brandType',
- params: {
- page: 1,
- limit: 1000,
- },
- },
- },
- {
- field: 'name',
- component: 'Input',
- label: t('routes.scenes.liveName'),
- required: true,
- helpMessage: '仅能输入 英文大小写和中文,最多可输入50个字',
- componentProps: {
- maxLength: 25,
- },
- },
- {
- field: 'appListPicUrl',
- label: t('routes.scenes.appListPicUrl'),
- component: 'Upload',
- helpMessage: '推荐大小:400 * 400 像素',
- required: true,
- colProps: {
- span: 10,
- },
- componentProps: {
- accept: ['jpg', 'jpeg', 'gif', 'png'],
- maxSize: 5,
- maxNumber: 1,
- api: uploadLiveApi,
- onChange: async () => {
- await validateFields(['appListPicUrl']);
- },
- maxgoodsNumber: 1,
- afterFetch: function (data) {
- Reflect.set(data, 'url', data.message.url);
- return data;
- },
- },
- },
- {
- field: 'simpleDesc',
- component: 'InputTextArea',
- label: t('routes.scenes.simpleDesc'),
- required: true,
- },
- {
- field: 'sceneNum',
- label: t('routes.scenes.sceneUrl'),
- component: 'Input',
- colProps: {
- span: 10,
- },
- itemProps: {
- validateTrigger: 'blur',
- },
- required: true,
- helpMessage: '直播间绑定后,将无法修改',
- slot: 'sceneNum',
- // componentProps: {
- // api: getAllSceneApi,
- // immediate: true,
- // resultField: 'list',
- // labelField: 'sceneName',
- // valueField: 'num',
- // onChange: function (_, item) {
- // console.log('onChange', item);
- // myData.sceneUrl = item.webSite || item.sceneUrl || item.liveRoomUrl;
- // },
- // onSearch:function(vale,item) {
- // console.log('onChange', vale,item);
- // },
- // params: {
- // page: 1,
- // limit: 100,
- // },
- // },
- },
- {
- field: 'location',
- label: '直播间位置',
- component: 'ApiCascader',
- itemProps: {
- validateTrigger: 'blur',
- },
- componentProps: {
- api: () => {
- return CascaderData;
- },
- apiParamKey: 'provinceCode',
- dataField: 'children',
- labelField: 'name',
- valueField: 'name',
- // numberToString: true,
- isLeaf: (record) => {
- return !(record.levelType < 3);
- },
- onChange: (data) => {
- try {
- console.log('data', data);
- let location: string[] = data;
- // [a,b,c].map(ele => {
- // return ele && ele.code
- // } ),
- let province = data[0],
- city = data[1],
- district = data[2];
- defaultAddress.location = location;
- defaultAddress.province = province;
- defaultAddress.city = city;
- defaultAddress.district = district;
- } catch (error) {
- console.error('error', error);
- }
- },
- },
- colProps: {
- span: 20,
- },
- },
- {
- field: 'detailAddr',
- label: t('routes.scenes.detailAddr'),
- component: 'Input',
- slot: 'detailAddr',
- colProps: {
- span: 10,
- },
- },
- {
- field: 'map',
- label: '地图位置',
- component: 'Input',
- slot: 'map',
- colProps: {
- span: 20,
- },
- },
- {
- field: 'picList',
- label: '直播间图片',
- component: 'Upload',
- helpMessage: '推荐大小:400 * 400 像素',
- componentProps: {
- api: uploadLiveApi,
- maxSize: 5,
- emptyHidePreview: true,
- maxNumber: 15,
- accept: ['jpg', 'jpeg', 'gif', 'png'],
- afterFetch: function (data) {
- Reflect.set(data, 'url', data.message.url);
- return data;
- },
- },
- colProps: {
- span: 20,
- },
- },
- // {
- // field: 'introduceVideo',
- // label: '视频',
- // component: 'Upload',
- // componentProps: {
- // api: uploadLiveVideoApi,
- // maxSize: 100,
- // emptyHidePreview: true,
- // maxNumber: 1,
- // accept: ['video/*'],
- // afterFetch: function (data) {
- // Reflect.set(data, 'url', data.message.video);
- // myData.introduceVideoCover = data.message.image;
- // return data;
- // },
- // },
- // colProps: {
- // span: 20,
- // },
- // },
- {
- field: 'sortOrder',
- component: 'InputNumber',
- label: t('routes.scenes.sortOrder'),
- // required: true,
- defaultValue: 1,
- componentProps: {
- min: 0,
- },
- },
- {
- field: 'livestreamStatus',
- component: 'RadioGroup',
- label: t('routes.scenes.livestream'),
- required: true,
- defaultValue: 0,
- componentProps: {
- options: [
- {
- label: '是',
- value: 1,
- key: 1,
- },
- {
- label: '否',
- value: 0,
- key: 0,
- },
- ],
- },
- },
- // {
- // field: 'contractPhone',
- // component: 'Input',
- // label: t('routes.scenes.contractPhone'),
- // required: true,
- // helpMessage: ['支持填写400(400-xxx-xxxx)热线、手机号等联系方式'],
- // },
- {
- field: 'contactId',
- component: 'ApiSelect',
- label: '联系人',
- required: true,
- componentProps: {
- api: staffListApi,
- resultField: 'list',
- labelField: 'nickName',
- valueField: 'id',
- immediate: true,
- showSearch: true,
- optionFilterProp: 'label',
- onChange: function (_, opt) {
- console.log('opt', opt.value);
- // Reflect.set(modalRecord, 'shippingName', opt.label);
- },
- params: {
- page: 1,
- limit: 1000,
- },
- required: true,
- },
- },
- ];
- // updateSchema, validate
- const [
- registerForm,
- { resetFields, setFieldsValue, updateSchema, validate, validateFields },
- ] = useForm({
- labelWidth: 120,
- schemas: schemas,
- showActionButtonGroup: false,
- baseColProps: { lg: 24, md: 24 },
- });
- const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
- resetFields();
- setDrawerProps({ confirmLoading: false });
- isUpdate.value = !!data?.isUpdate;
- const { record } = data;
- let Option = await getAllSceneApi({
- page: 1,
- limit: 100,
- sceneNum: record && record.sceneNum,
- });
- // @ts-ignore
- sceneNumOption.list = Option.list.map((ele) => {
- return {
- ...ele,
- label: ele.sceneName,
- // @ts-ignore
- value: ele.num,
- };
- });
- sceneNumOption.allList = sceneNumOption.list;
- console.log('isUpdate', isUpdate.value, Option.list);
- await updateSchema({
- field: 'sceneNum',
- componentProps: {
- api: getAllSceneApi,
- disabled: isUpdate.value,
- immediate: true,
- resultField: 'list',
- labelField: 'sceneName',
- valueField: 'num',
- onChange: function (_, item) {
- myData.sceneUrl = item.webSite || item.sceneUrl || item.liveRoomUrl;
- },
- params: {
- page: 1,
- limit: 100,
- sceneNum: record && record.sceneNum,
- },
- },
- });
- if (unref(isUpdate)) {
- try {
- const res = await getLiveInfoApi({ id: record.id, token });
- // console.log('edit', res);
- let setDAta = reactive<infoItem>({
- province: '',
- city: '',
- district: '',
- address: '',
- picList: [],
- appListPicUrl: [],
- introduceVideo: [],
- });
- let ssq = res.address?.split(' ');
- try {
- let ssqlist = ssq[0].split(',');
- setDAta.province = ssqlist[0];
- setDAta.city = ssqlist[1];
- setDAta.district = ssqlist[2];
- setDAta.address = ssq[1];
- setDAta.location = ssqlist;
- setDAta.picList = res.picList?.split('#$#') || [];
- setDAta.appListPicUrl = [res.appListPicUrl];
- setDAta.introduceVideo = [res.introduceVideo];
- defaultAddress.address = ssq[1];
- defaultAddress.province = ssqlist[0];
- defaultAddress.city = ssqlist[1];
- defaultAddress.district = ssqlist[2];
- defaultAddress.location = ssqlist;
- defaultAddress.lng = res.longitude;
- defaultAddress.lat = res.latitude;
- detailAddr.value = ssq[2];
- } catch (error) {
- console.warn('edit-error', error);
- }
- myData.introduceVideoCover = res.introduceVideoCover || '';
- myData.sceneUrl = res.sceneUrl;
- await setFieldsValue({
- ...res,
- ...setDAta,
- });
- myData.introduceVideoCover = res.introduceVideoCover;
- } catch (error) {
- console.error(error);
- }
- }
- myData.id = (record && record.id) || false;
- initMap();
- });
- async function initMap() {
- console.log('initMap');
- await toPromise();
- await nextTick();
- const wrapEl = unref(wrapRef);
- if (!wrapEl) return;
- // center: [this.longitude || 120.262337, this.latitude || 30.178285],
- // const geocoder = new AMap.Geocoder({});
- let searchCity = getCode(defaultAddress.location);
- const AMap = (window as any).AMap;
- let center = [defaultAddress.lng, defaultAddress.lat];
- map = new AMap.Map(wrapEl, {
- zoom: 18,
- center: center,
- viewMode: '3D',
- resizeEnable: true,
- floorControl: true,
- showIndoorMap: true,
- });
- AMap.plugin('AMap.Geocoder', function () {
- var geocoder = new AMap.Geocoder({
- // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
- city: searchCity[2] || searchCity[1] || searchCity[0],
- });
- geocoder.getLocation(defaultAddress.address, async function (status, result) {
- if (status === 'complete' && result.info === 'OK') {
- // result中对应详细地理坐标信息
- const { geocodes } = result;
- if (geocodes?.length > 0) {
- const { addressComponent } = geocodes[0] as any as GeocodesType;
- defaultAddress.location = getCodeArray(addressComponent);
- await updateSchema({
- field: 'location',
- componentProps: {
- displayRenderArray: [
- addressComponent.province,
- addressComponent.city,
- addressComponent.district,
- ],
- },
- });
- await setFieldsValue({
- location: defaultAddress.location,
- // detailAddr: defaultAddress.address,
- });
- detailAddr.value = defaultAddress.address;
- }
- } else {
- createMessage.error('查询地址异常');
- }
- });
- // const marker = new AMap.Marker({
- // position: new AMap.LngLat(defaultAddress.lng, defaultAddress.lat),
- // title: 'lala',
- // });
- // map && map.add(marker);
- });
- }
- function handleChange(value, item) {
- console.log('handleChange', value, item);
- console.log('myData.sceneUrl', myData.sceneUrl);
- setFieldsValue({
- sceneNum: value,
- });
- }
- async function handleSearch(value) {
- if (!value) {
- return (sceneNumOption.list = sceneNumOption.allList);
- }
- let { list } = await ListApi({
- sceneName: value,
- limit: 100,
- page: 1,
- });
- // @ts-ignore
- sceneNumOption.list = list.map((ele) => {
- return {
- ...ele,
- // @ts-ignore
- value: ele.num,
- label: ele.sceneName,
- };
- });
- console.log('handleSearch', value, list);
- }
- function getCodeArray(addressComponent) {
- let { province, city, district } = addressComponent;
- return [province, city, district];
- }
- const getTitle = computed(() => (!unref(isUpdate) ? '新增直播间' : '编辑直播间'));
- async function handleMapSearch() {
- console.log('handleMapSearch');
- console.log('detailAddr', detailAddr.value, defaultAddress);
- if (detailAddr.value?.length > 0) {
- let searchCity = getCode(defaultAddress.location);
- const AMap = (window as any).AMap;
- AMap.plugin('AMap.Geocoder', function () {
- const geocoder = new AMap.Geocoder({
- // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
- city: searchCity[2] || searchCity[1] || searchCity[0],
- // adcode: defaultAddress.location[2],
- // citycode: '0571',
- });
- geocoder.getLocation(detailAddr.value, async function (status, result) {
- if (status === 'complete' && result.info === 'OK') {
- // result中对应详细地理坐标信息
- const { geocodes } = result;
- if (geocodes?.length > 0) {
- // map.setCenter([lng, lat]);
- const { addressComponent, formattedAddress, location } =
- geocodes[0] as any as GeocodesType;
- map.setCenter(location);
- const marker = new AMap.Marker({
- position: new AMap.LngLat(location.lng, location.lat),
- title: formattedAddress,
- });
- map.add(marker);
- defaultAddress.lng = location.lng;
- defaultAddress.lat = location.lat;
- defaultAddress.location = getCodeArray(addressComponent);
- await updateSchema({
- field: 'location',
- componentProps: {
- displayRenderArray: [
- addressComponent.province,
- addressComponent.city,
- addressComponent.district,
- ],
- },
- });
- await setFieldsValue({
- location: defaultAddress.location,
- // detailAddr: defaultAddress.address,
- });
- // detailAddr.value = defaultAddress.address;
- }
- } else {
- createMessage.error('查询地址异常');
- }
- });
- });
- }
- }
- async function handleMapReset() {
- defaultAddress.location = ['33', '3301', '330109'];
- detailAddr.value = '山阴路688号恒隆广场B座1217';
- handleMapSearch();
- }
- async function handleSubmit() {
- const { companyId, id } = userinfo.value;
- const { lng, lat } = defaultAddress;
- let requestApi = isUpdate.value ? brandUpdateApi : addSave;
- try {
- map && map.destroy();
- const values = await validate();
- const { location, picList, appListPicUrl = [], introduceVideo = [] } = values;
- let address = unref(location);
- let apiData = {
- ...values,
- // contractPhone:phone,
- createUserDeptId: companyId,
- latitude: lat,
- longitude: lng,
- createUserId: id,
- address: address.join(',') + ' ' + detailAddr.value,
- picList: picList && picList.join('#$#'),
- appListPicUrl: appListPicUrl[0],
- introduceVideo: introduceVideo[0],
- sceneUrl: myData.sceneUrl,
- introduceVideoCover: myData.introduceVideoCover,
- };
- if (myData.id) {
- apiData.id = myData.id;
- }
- await requestApi(apiData);
- resetFields();
- closeDrawer();
- createMessage.success(t('common.optSuccess'));
- emit('success');
- } catch (error) {
- console.error(error);
- }
- }
- async function handleClose() {
- map && map.destroy();
- resetFields();
- closeDrawer();
- }
- return {
- detailAddr,
- myData,
- registerDrawer,
- registerForm,
- getTitle,
- handleSubmit,
- wrapRef,
- handleMapSearch,
- handleMapReset,
- handleClose,
- t,
- token,
- sceneNumOption,
- isUpdate,
- handleChange,
- handleSearch,
- getOptions,
- filterOption,
- };
- },
- });
- </script>
- <style lang="less">
- .live-drawer {
- .ant-input-group-addon {
- padding-right: 0;
- background-color: transparent;
- border: none;
- button {
- font-size: 14px;
- }
- }
- }
- </style>
|