liveDrawer.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. <template>
  2. <BasicDrawer
  3. v-bind="$attrs"
  4. @register="registerDrawer"
  5. showFooter
  6. :title="getTitle"
  7. :showDetailBack="false"
  8. width="60%"
  9. @ok="handleSubmit"
  10. @close="handleClose"
  11. >
  12. <div class="entry-x">
  13. <BasicForm @register="registerForm">
  14. <template #map>
  15. <!-- <Card style="width: 300px; height: 300px"> -->
  16. <div ref="wrapRef" style="width: 100%; height: 400px"></div>
  17. <!-- </Card> -->
  18. </template>
  19. <!-- ="{ model, field }" -->
  20. <template #detailAddr>
  21. <a-input
  22. class="live-drawer"
  23. v-bind="$attrs"
  24. v-model:value="detailAddr"
  25. :allowClear="true"
  26. placeholder=""
  27. >
  28. <template #addonAfter>
  29. <a-button type="primary" class="mr-10px" @click="handleMapSearch">
  30. {{ t('common.queryText') }}
  31. </a-button>
  32. <a-button @click="handleMapReset"> {{ t('common.resetText') }}</a-button>
  33. </template>
  34. </a-input>
  35. </template>
  36. <template #sceneNum="{ model, field }">
  37. <Select
  38. :disabled="isUpdate"
  39. v-bind="$attrs"
  40. v-model:value="model[field]"
  41. @change="handleChange"
  42. @search="handleSearch"
  43. showSearch
  44. placeholder="请选择场景链接"
  45. :options="getOptions"
  46. :filterOption="filterOption"
  47. />
  48. </template>
  49. </BasicForm>
  50. </div>
  51. </BasicDrawer>
  52. </template>
  53. <script lang="ts">
  54. import { defineComponent, ref, computed, unref, nextTick, reactive } from 'vue';
  55. import { BasicForm, useForm, FormSchema } from '/@/components/Form/index';
  56. // import { Card } from 'ant-design-vue';
  57. import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  58. import { useMessage } from '/@/hooks/web/useMessage';
  59. import { useI18n } from '/@/hooks/web/useI18n';
  60. import { useUserStore } from '/@/store/modules/user';
  61. import { data as CascaderData, getCode } from '/@/utils/cascaderData';
  62. import { ListApi } from '/@/api/scene/list';
  63. import { Select } from 'ant-design-vue';
  64. import {
  65. brandTypeListApi,
  66. uploadLiveApi,
  67. getAllSceneApi,
  68. // uploadLiveVideoApi,
  69. addSave,
  70. getLiveInfoApi,
  71. brandUpdateApi,
  72. // LiveSceneDeleteApi,
  73. } from '/@/api/scene/live';
  74. import { useScript } from '/@/hooks/web/useScript';
  75. import { staffListApi } from '/@/api/staff/list';
  76. const A_MAP_URL = 'https://webapi.amap.com/maps?v=2.0&key=e661b00bdf2c44cccf71ef6070ef41b8';
  77. // const A_MAP_URL = 'https://webapi.amap.com/maps?v=2.0&key=5a2d384532ae531bf99bd8487c4f03d2';
  78. // const A_MAP_URL = 'https://webapi.amap.com/maps?v=1.4.10&key=e661b00bdf2c44cccf71ef6070ef41b8';
  79. //webapi.amap.com/maps?v=1.4.10&key=e661b00bdf2c44cccf71ef6070ef41b8
  80. // Card
  81. export default defineComponent({
  82. name: 'MenuDrawer',
  83. components: { BasicDrawer, BasicForm, Select },
  84. emits: ['success', 'register'],
  85. setup(_, { emit }) {
  86. const isUpdate = ref(true);
  87. const detailAddr = ref('');
  88. const userStore = useUserStore();
  89. const token = userStore.getToken;
  90. const userinfo = computed(() => userStore.getUserInfo);
  91. const wrapRef = ref<HTMLDivElement | null>(null);
  92. const sceneNumOption = reactive({
  93. list: [],
  94. allList: [],
  95. });
  96. const getOptions = computed(() => {
  97. return sceneNumOption.list;
  98. });
  99. interface AddressComponentType {
  100. city: string;
  101. district: string;
  102. province: string;
  103. }
  104. interface GeocodesType {
  105. adcode: string;
  106. addressComponent: AddressComponentType;
  107. formattedAddress: string;
  108. location: {
  109. lng: number;
  110. lat: number;
  111. };
  112. }
  113. interface infoItem {
  114. province?: string;
  115. city?: string;
  116. address?: string;
  117. district?: string;
  118. picList?: string[];
  119. appListPicUrl?: string[];
  120. introduceVideo?: string[];
  121. location?: string[];
  122. }
  123. let map;
  124. // Lat(120.262337, 30.178285),
  125. const myData = reactive({
  126. sceneUrl: '',
  127. id: '',
  128. introduceVideoCover: '',
  129. });
  130. const filterOption = (input, option) => {
  131. return option.sceneName.includes(input.toLowerCase());
  132. };
  133. const defaultAddress = reactive({
  134. address: '山阴路688号恒隆广场B座1217',
  135. // address: '权晖花园21栋',
  136. lng: 120.262337,
  137. lat: 30.178285,
  138. location: ['浙江省', '杭州市', '滨江区'],
  139. province: '浙江省',
  140. city: '杭州市',
  141. district: '萧山区',
  142. });
  143. const { toPromise } = useScript({ src: A_MAP_URL });
  144. const { t } = useI18n();
  145. const { createMessage } = useMessage();
  146. const schemas: FormSchema[] = [
  147. {
  148. field: 'type',
  149. label: t('routes.scenes.liveType'),
  150. component: 'ApiSelect',
  151. required: true,
  152. itemProps: {
  153. validateTrigger: 'blur',
  154. },
  155. componentProps: {
  156. api: brandTypeListApi,
  157. resultField: 'list',
  158. labelField: 'name',
  159. valueField: 'brandType',
  160. params: {
  161. page: 1,
  162. limit: 1000,
  163. },
  164. },
  165. },
  166. {
  167. field: 'name',
  168. component: 'Input',
  169. label: t('routes.scenes.liveName'),
  170. required: true,
  171. helpMessage: '仅能输入 英文大小写和中文,最多可输入50个字',
  172. componentProps: {
  173. maxLength: 25,
  174. },
  175. },
  176. {
  177. field: 'appListPicUrl',
  178. label: t('routes.scenes.appListPicUrl'),
  179. component: 'Upload',
  180. helpMessage: '推荐大小:400 * 400 像素',
  181. required: true,
  182. colProps: {
  183. span: 10,
  184. },
  185. componentProps: {
  186. accept: ['jpg', 'jpeg', 'gif', 'png'],
  187. maxSize: 5,
  188. maxNumber: 1,
  189. api: uploadLiveApi,
  190. onChange: async () => {
  191. await validateFields(['appListPicUrl']);
  192. },
  193. maxgoodsNumber: 1,
  194. afterFetch: function (data) {
  195. Reflect.set(data, 'url', data.message.url);
  196. return data;
  197. },
  198. },
  199. },
  200. {
  201. field: 'simpleDesc',
  202. component: 'InputTextArea',
  203. label: t('routes.scenes.simpleDesc'),
  204. required: true,
  205. },
  206. {
  207. field: 'sceneNum',
  208. label: t('routes.scenes.sceneUrl'),
  209. component: 'Input',
  210. colProps: {
  211. span: 10,
  212. },
  213. itemProps: {
  214. validateTrigger: 'blur',
  215. },
  216. required: true,
  217. helpMessage: '直播间绑定后,将无法修改',
  218. slot: 'sceneNum',
  219. // componentProps: {
  220. // api: getAllSceneApi,
  221. // immediate: true,
  222. // resultField: 'list',
  223. // labelField: 'sceneName',
  224. // valueField: 'num',
  225. // onChange: function (_, item) {
  226. // console.log('onChange', item);
  227. // myData.sceneUrl = item.webSite || item.sceneUrl || item.liveRoomUrl;
  228. // },
  229. // onSearch:function(vale,item) {
  230. // console.log('onChange', vale,item);
  231. // },
  232. // params: {
  233. // page: 1,
  234. // limit: 100,
  235. // },
  236. // },
  237. },
  238. {
  239. field: 'location',
  240. label: '直播间位置',
  241. component: 'ApiCascader',
  242. itemProps: {
  243. validateTrigger: 'blur',
  244. },
  245. componentProps: {
  246. api: () => {
  247. return CascaderData;
  248. },
  249. apiParamKey: 'provinceCode',
  250. dataField: 'children',
  251. labelField: 'name',
  252. valueField: 'name',
  253. // numberToString: true,
  254. isLeaf: (record) => {
  255. return !(record.levelType < 3);
  256. },
  257. onChange: (data) => {
  258. try {
  259. console.log('data', data);
  260. let location: string[] = data;
  261. // [a,b,c].map(ele => {
  262. // return ele && ele.code
  263. // } ),
  264. let province = data[0],
  265. city = data[1],
  266. district = data[2];
  267. defaultAddress.location = location;
  268. defaultAddress.province = province;
  269. defaultAddress.city = city;
  270. defaultAddress.district = district;
  271. } catch (error) {
  272. console.error('error', error);
  273. }
  274. },
  275. },
  276. colProps: {
  277. span: 20,
  278. },
  279. },
  280. {
  281. field: 'detailAddr',
  282. label: t('routes.scenes.detailAddr'),
  283. component: 'Input',
  284. slot: 'detailAddr',
  285. colProps: {
  286. span: 10,
  287. },
  288. },
  289. {
  290. field: 'map',
  291. label: '地图位置',
  292. component: 'Input',
  293. slot: 'map',
  294. colProps: {
  295. span: 20,
  296. },
  297. },
  298. {
  299. field: 'picList',
  300. label: '直播间图片',
  301. component: 'Upload',
  302. helpMessage: '推荐大小:400 * 400 像素',
  303. componentProps: {
  304. api: uploadLiveApi,
  305. maxSize: 5,
  306. emptyHidePreview: true,
  307. maxNumber: 15,
  308. accept: ['jpg', 'jpeg', 'gif', 'png'],
  309. afterFetch: function (data) {
  310. Reflect.set(data, 'url', data.message.url);
  311. return data;
  312. },
  313. },
  314. colProps: {
  315. span: 20,
  316. },
  317. },
  318. // {
  319. // field: 'introduceVideo',
  320. // label: '视频',
  321. // component: 'Upload',
  322. // componentProps: {
  323. // api: uploadLiveVideoApi,
  324. // maxSize: 100,
  325. // emptyHidePreview: true,
  326. // maxNumber: 1,
  327. // accept: ['video/*'],
  328. // afterFetch: function (data) {
  329. // Reflect.set(data, 'url', data.message.video);
  330. // myData.introduceVideoCover = data.message.image;
  331. // return data;
  332. // },
  333. // },
  334. // colProps: {
  335. // span: 20,
  336. // },
  337. // },
  338. {
  339. field: 'sortOrder',
  340. component: 'InputNumber',
  341. label: t('routes.scenes.sortOrder'),
  342. // required: true,
  343. defaultValue: 1,
  344. componentProps: {
  345. min: 0,
  346. },
  347. },
  348. {
  349. field: 'livestreamStatus',
  350. component: 'RadioGroup',
  351. label: t('routes.scenes.livestream'),
  352. required: true,
  353. defaultValue: 0,
  354. componentProps: {
  355. options: [
  356. {
  357. label: '是',
  358. value: 1,
  359. key: 1,
  360. },
  361. {
  362. label: '否',
  363. value: 0,
  364. key: 0,
  365. },
  366. ],
  367. },
  368. },
  369. // {
  370. // field: 'contractPhone',
  371. // component: 'Input',
  372. // label: t('routes.scenes.contractPhone'),
  373. // required: true,
  374. // helpMessage: ['支持填写400(400-xxx-xxxx)热线、手机号等联系方式'],
  375. // },
  376. {
  377. field: 'contactId',
  378. component: 'ApiSelect',
  379. label: '联系人',
  380. required: true,
  381. componentProps: {
  382. api: staffListApi,
  383. resultField: 'list',
  384. labelField: 'nickName',
  385. valueField: 'id',
  386. immediate: true,
  387. showSearch: true,
  388. optionFilterProp: 'label',
  389. onChange: function (_, opt) {
  390. console.log('opt', opt.value);
  391. // Reflect.set(modalRecord, 'shippingName', opt.label);
  392. },
  393. params: {
  394. page: 1,
  395. limit: 1000,
  396. },
  397. required: true,
  398. },
  399. },
  400. ];
  401. // updateSchema, validate
  402. const [
  403. registerForm,
  404. { resetFields, setFieldsValue, updateSchema, validate, validateFields },
  405. ] = useForm({
  406. labelWidth: 120,
  407. schemas: schemas,
  408. showActionButtonGroup: false,
  409. baseColProps: { lg: 24, md: 24 },
  410. });
  411. const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
  412. resetFields();
  413. setDrawerProps({ confirmLoading: false });
  414. isUpdate.value = !!data?.isUpdate;
  415. const { record } = data;
  416. let Option = await getAllSceneApi({
  417. page: 1,
  418. limit: 100,
  419. sceneNum: record && record.sceneNum,
  420. });
  421. // @ts-ignore
  422. sceneNumOption.list = Option.list.map((ele) => {
  423. return {
  424. ...ele,
  425. label: ele.sceneName,
  426. // @ts-ignore
  427. value: ele.num,
  428. };
  429. });
  430. sceneNumOption.allList = sceneNumOption.list;
  431. console.log('isUpdate', isUpdate.value, Option.list);
  432. await updateSchema({
  433. field: 'sceneNum',
  434. componentProps: {
  435. api: getAllSceneApi,
  436. disabled: isUpdate.value,
  437. immediate: true,
  438. resultField: 'list',
  439. labelField: 'sceneName',
  440. valueField: 'num',
  441. onChange: function (_, item) {
  442. myData.sceneUrl = item.webSite || item.sceneUrl || item.liveRoomUrl;
  443. },
  444. params: {
  445. page: 1,
  446. limit: 100,
  447. sceneNum: record && record.sceneNum,
  448. },
  449. },
  450. });
  451. if (unref(isUpdate)) {
  452. try {
  453. const res = await getLiveInfoApi({ id: record.id, token });
  454. // console.log('edit', res);
  455. let setDAta = reactive<infoItem>({
  456. province: '',
  457. city: '',
  458. district: '',
  459. address: '',
  460. picList: [],
  461. appListPicUrl: [],
  462. introduceVideo: [],
  463. });
  464. let ssq = res.address?.split(' ');
  465. try {
  466. let ssqlist = ssq[0].split(',');
  467. setDAta.province = ssqlist[0];
  468. setDAta.city = ssqlist[1];
  469. setDAta.district = ssqlist[2];
  470. setDAta.address = ssq[1];
  471. setDAta.location = ssqlist;
  472. setDAta.picList = res.picList?.split('#$#') || [];
  473. setDAta.appListPicUrl = [res.appListPicUrl];
  474. setDAta.introduceVideo = [res.introduceVideo];
  475. defaultAddress.address = ssq[1];
  476. defaultAddress.province = ssqlist[0];
  477. defaultAddress.city = ssqlist[1];
  478. defaultAddress.district = ssqlist[2];
  479. defaultAddress.location = ssqlist;
  480. defaultAddress.lng = res.longitude;
  481. defaultAddress.lat = res.latitude;
  482. detailAddr.value = ssq[2];
  483. } catch (error) {
  484. console.warn('edit-error', error);
  485. }
  486. myData.introduceVideoCover = res.introduceVideoCover || '';
  487. myData.sceneUrl = res.sceneUrl;
  488. await setFieldsValue({
  489. ...res,
  490. ...setDAta,
  491. });
  492. myData.introduceVideoCover = res.introduceVideoCover;
  493. } catch (error) {
  494. console.error(error);
  495. }
  496. }
  497. myData.id = (record && record.id) || false;
  498. initMap();
  499. });
  500. async function initMap() {
  501. console.log('initMap');
  502. await toPromise();
  503. await nextTick();
  504. const wrapEl = unref(wrapRef);
  505. if (!wrapEl) return;
  506. // center: [this.longitude || 120.262337, this.latitude || 30.178285],
  507. // const geocoder = new AMap.Geocoder({});
  508. let searchCity = getCode(defaultAddress.location);
  509. const AMap = (window as any).AMap;
  510. let center = [defaultAddress.lng, defaultAddress.lat];
  511. map = new AMap.Map(wrapEl, {
  512. zoom: 18,
  513. center: center,
  514. viewMode: '3D',
  515. resizeEnable: true,
  516. floorControl: true,
  517. showIndoorMap: true,
  518. });
  519. AMap.plugin('AMap.Geocoder', function () {
  520. var geocoder = new AMap.Geocoder({
  521. // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
  522. city: searchCity[2] || searchCity[1] || searchCity[0],
  523. });
  524. geocoder.getLocation(defaultAddress.address, async function (status, result) {
  525. if (status === 'complete' && result.info === 'OK') {
  526. // result中对应详细地理坐标信息
  527. const { geocodes } = result;
  528. if (geocodes?.length > 0) {
  529. const { addressComponent } = geocodes[0] as any as GeocodesType;
  530. defaultAddress.location = getCodeArray(addressComponent);
  531. await updateSchema({
  532. field: 'location',
  533. componentProps: {
  534. displayRenderArray: [
  535. addressComponent.province,
  536. addressComponent.city,
  537. addressComponent.district,
  538. ],
  539. },
  540. });
  541. await setFieldsValue({
  542. location: defaultAddress.location,
  543. // detailAddr: defaultAddress.address,
  544. });
  545. detailAddr.value = defaultAddress.address;
  546. }
  547. } else {
  548. createMessage.error('查询地址异常');
  549. }
  550. });
  551. // const marker = new AMap.Marker({
  552. // position: new AMap.LngLat(defaultAddress.lng, defaultAddress.lat),
  553. // title: 'lala',
  554. // });
  555. // map && map.add(marker);
  556. });
  557. }
  558. function handleChange(value, item) {
  559. console.log('handleChange', value, item);
  560. console.log('myData.sceneUrl', myData.sceneUrl);
  561. setFieldsValue({
  562. sceneNum: value,
  563. });
  564. }
  565. async function handleSearch(value) {
  566. if (!value) {
  567. return (sceneNumOption.list = sceneNumOption.allList);
  568. }
  569. let { list } = await ListApi({
  570. sceneName: value,
  571. limit: 100,
  572. page: 1,
  573. });
  574. // @ts-ignore
  575. sceneNumOption.list = list.map((ele) => {
  576. return {
  577. ...ele,
  578. // @ts-ignore
  579. value: ele.num,
  580. label: ele.sceneName,
  581. };
  582. });
  583. console.log('handleSearch', value, list);
  584. }
  585. function getCodeArray(addressComponent) {
  586. let { province, city, district } = addressComponent;
  587. return [province, city, district];
  588. }
  589. const getTitle = computed(() => (!unref(isUpdate) ? '新增直播间' : '编辑直播间'));
  590. async function handleMapSearch() {
  591. console.log('handleMapSearch');
  592. console.log('detailAddr', detailAddr.value, defaultAddress);
  593. if (detailAddr.value?.length > 0) {
  594. let searchCity = getCode(defaultAddress.location);
  595. const AMap = (window as any).AMap;
  596. AMap.plugin('AMap.Geocoder', function () {
  597. const geocoder = new AMap.Geocoder({
  598. // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
  599. city: searchCity[2] || searchCity[1] || searchCity[0],
  600. // adcode: defaultAddress.location[2],
  601. // citycode: '0571',
  602. });
  603. geocoder.getLocation(detailAddr.value, async function (status, result) {
  604. if (status === 'complete' && result.info === 'OK') {
  605. // result中对应详细地理坐标信息
  606. const { geocodes } = result;
  607. if (geocodes?.length > 0) {
  608. // map.setCenter([lng, lat]);
  609. const { addressComponent, formattedAddress, location } =
  610. geocodes[0] as any as GeocodesType;
  611. map.setCenter(location);
  612. const marker = new AMap.Marker({
  613. position: new AMap.LngLat(location.lng, location.lat),
  614. title: formattedAddress,
  615. });
  616. map.add(marker);
  617. defaultAddress.lng = location.lng;
  618. defaultAddress.lat = location.lat;
  619. defaultAddress.location = getCodeArray(addressComponent);
  620. await updateSchema({
  621. field: 'location',
  622. componentProps: {
  623. displayRenderArray: [
  624. addressComponent.province,
  625. addressComponent.city,
  626. addressComponent.district,
  627. ],
  628. },
  629. });
  630. await setFieldsValue({
  631. location: defaultAddress.location,
  632. // detailAddr: defaultAddress.address,
  633. });
  634. // detailAddr.value = defaultAddress.address;
  635. }
  636. } else {
  637. createMessage.error('查询地址异常');
  638. }
  639. });
  640. });
  641. }
  642. }
  643. async function handleMapReset() {
  644. defaultAddress.location = ['33', '3301', '330109'];
  645. detailAddr.value = '山阴路688号恒隆广场B座1217';
  646. handleMapSearch();
  647. }
  648. async function handleSubmit() {
  649. const { companyId, id } = userinfo.value;
  650. const { lng, lat } = defaultAddress;
  651. let requestApi = isUpdate.value ? brandUpdateApi : addSave;
  652. try {
  653. map && map.destroy();
  654. const values = await validate();
  655. const { location, picList, appListPicUrl = [], introduceVideo = [] } = values;
  656. let address = unref(location);
  657. let apiData = {
  658. ...values,
  659. // contractPhone:phone,
  660. createUserDeptId: companyId,
  661. latitude: lat,
  662. longitude: lng,
  663. createUserId: id,
  664. address: address.join(',') + ' ' + detailAddr.value,
  665. picList: picList && picList.join('#$#'),
  666. appListPicUrl: appListPicUrl[0],
  667. introduceVideo: introduceVideo[0],
  668. sceneUrl: myData.sceneUrl,
  669. introduceVideoCover: myData.introduceVideoCover,
  670. };
  671. if (myData.id) {
  672. apiData.id = myData.id;
  673. }
  674. await requestApi(apiData);
  675. resetFields();
  676. closeDrawer();
  677. createMessage.success(t('common.optSuccess'));
  678. emit('success');
  679. } catch (error) {
  680. console.error(error);
  681. }
  682. }
  683. async function handleClose() {
  684. map && map.destroy();
  685. resetFields();
  686. closeDrawer();
  687. }
  688. return {
  689. detailAddr,
  690. myData,
  691. registerDrawer,
  692. registerForm,
  693. getTitle,
  694. handleSubmit,
  695. wrapRef,
  696. handleMapSearch,
  697. handleMapReset,
  698. handleClose,
  699. t,
  700. token,
  701. sceneNumOption,
  702. isUpdate,
  703. handleChange,
  704. handleSearch,
  705. getOptions,
  706. filterOption,
  707. };
  708. },
  709. });
  710. </script>
  711. <style lang="less">
  712. .live-drawer {
  713. .ant-input-group-addon {
  714. padding-right: 0;
  715. background-color: transparent;
  716. border: none;
  717. button {
  718. font-size: 14px;
  719. }
  720. }
  721. }
  722. </style>