huangxw 4 månader sedan
förälder
incheckning
4110a15475

+ 1 - 0
package.json

@@ -23,6 +23,7 @@
     "url": "https://gitee.com/JavaLionLi/plus-ui.git"
   },
   "dependencies": {
+    "@amap/amap-jsapi-loader": "^1.0.1",
     "@element-plus/icons-vue": "2.3.1",
     "@gausszhou/vue3-drag-resize-rotate": "^3.0.2",
     "@highlightjs/vue-plugin": "2.1.0",

+ 82 - 0
src/components/SelectWepArea/SelectWepArea.vue

@@ -0,0 +1,82 @@
+<template>
+    <el-select filterable remote v-model="keywords" reserve-keyword :placeholder="placeholder" :remote-method="remoteMethod" @change="searchKeywords" :loading="loading" clearable style="width: 440px">
+        <el-option v-for="item in options" :key="item.id" :label="item.district + item.address.toString()" :value="item.id" />
+    </el-select>
+</template>
+<script setup lang="ts">
+import { debounce } from 'lodash';
+import AMapLoader from '@amap/amap-jsapi-loader';
+const props = defineProps<{
+    modelValue: any;
+    placeholder?: string;
+}>();
+const emit = defineEmits<{
+    (e: 'update:modelValue', value: string): void;
+}>();
+import { httpRequests } from '@/utils/httpRequests';
+const keywords = ref<string>('');
+const options = ref<any[]>([]);
+const loading = ref<boolean>(false);
+const remoteMethod = debounce((keywords: string) => {
+    if (!keywords) {
+        return;
+    }
+    loading.value = true;
+    let autoComplete = new mapData.AMap.Autocomplete();
+    autoComplete.search(keywords, function (status: string, result: any) {
+        console.log(result.tips);
+        if (!result.tips?.length) {
+            options.value = [];
+            loading.value = false;
+            return;
+        }
+        const tips = result.tips?.filter((item: any) => item.id);
+        options.value = [...tips];
+        loading.value = false;
+    });
+}, 1000);
+const mapData: any = {
+    AMap: null,
+    map: null,
+    marker: null,
+    circle: null
+};
+const initMap = (positions: any[] = []) => {
+    window._AMapSecurityConfig = {
+        securityJsCode: '059c519d3546bc48566ecca0b38f22ae',
+    };
+    AMapLoader.load({
+        key: '26b919a68880ad60637f5cabd6c94a76', // 申请好的Web端开发者Key,首次调用 load 时必填
+        version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
+        plugins: [
+            'AMap.PlaceSearch',
+            'AMap.AutoComplete'
+        ] // 需要使用的的插件列表,如比例尺'AMap.Scale'等
+    })
+        .then((AMap) => {
+            mapData.AMap = AMap;
+        })
+        .catch((e) => {
+            console.log(e);
+        });
+};
+const searchKeywords = (val: string) => {
+    console.log(val);
+    const item = options.value.find(i => i.id === val);
+    if (item) {
+        emit('update:modelValue', item);
+    } else {
+        emit('update:modelValue', '');
+    }
+};
+watch(() => props.modelValue, (val) => {
+    if (val && val.name) {
+        keywords.value = (val?.name || '') + (val?.district || '');
+    } else {
+        keywords.value = '';
+    }
+}, { immediate: true });
+onMounted(() => {
+    initMap();
+});
+</script>

+ 49 - 22
src/views/training/models/meeting-tpl-events.vue

@@ -31,9 +31,25 @@
                     </div>
                 </el-form-item>
             </template>
+            <template v-if="form.eventName === 'navigateEvent'">
+                <el-form-item label="地址导航" prop="params.wepArea">
+                    <SelectWepArea v-model="form.params.wepArea" placeholder="选择地址"></SelectWepArea>
+                </el-form-item>
+            </template>
+            <template v-if="form.eventName === 'linkEvent'">
+                <el-form-item label="跳转链接" prop="params.linkType">
+                    <el-radio-group v-model="form.params.linkType">
+                        <el-radio label="内链">内部链接</el-radio>
+                        <el-radio label="外链">外链链接</el-radio>
+                    </el-radio-group>
+                </el-form-item>
+                <el-form-item label="链接地址" prop="params.url">
+                    <el-input v-model="form.params.url" placeholder="请输入链接地址"></el-input>
+                </el-form-item>
+            </template>
             <el-form-item>
                 <div class="flex1 d-flex j-ed pt-40">
-                    <el-button>清除</el-button>
+                    <el-button @click="clearForm">清除</el-button>
                     <el-button @click="save" type="primary">保存</el-button>
                 </div>
             </el-form-item>
@@ -43,50 +59,61 @@
 </template>
 <script setup lang="ts">
 import { SelectMeetingTplPage } from '.';
-
 const props = defineProps<{
-    modelValue: any,
-    dict: any,
-    list: any[]
+    modelValue: any;
+    dict: any;
+    list: any[];
 }>();
-const { page_event } = toRefs<any>(props.dict)
+const { page_event } = toRefs<any>(props.dict);
 const enentFormRef = ref<any>(null);
 const showSelectMeeting = ref(false);
 const emit = defineEmits<{
-    (e: 'update:modelValue', value: any): void
-    (e: 'save', value: any): void
+    (e: 'update:modelValue', value: any): void;
+    (e: 'save', value: any): void;
 }>();
 const rules = ref<any>({
-    eventName: [
-        { required: true, message: '请选择触发事件', trigger: 'change' },
-    ],
+    eventName: [{ required: true, message: '请选择触发事件', trigger: 'change' }],
     'params.phone': [
         { required: true, message: '请输入电话号码', trigger: 'blur' },
         { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的电话号码', trigger: 'blur' }
     ],
+    'params.file': [{ required: true, message: '请上传文件', trigger: 'change' }],
+    'params.pageId': [{ required: true, message: '请选择页面', trigger: 'change' }],
+    'params.wepArea': [{ required: true, message: '请选择地址', trigger: 'change' }],
+    'params.linkType': [{ required: true, message: '请选择链接类型', trigger: 'change' }],
     'params.url': [
         { required: true, message: '请输入跳转链接', trigger: 'blur' },
         { type: 'url', message: '请输入正确的链接地址', trigger: 'blur' }
     ]
-})
+});
 const form = ref<any>(props.modelValue || {});
-const save = () => {
-    emit('update:modelValue', form.value);
-    emit('save', form.value);
+const save = async () => {
+    await enentFormRef.value.validate();
+    const value = {  ...form.value, id: form.value?.id || new Date().getTime() + '_btn_drap', isSave: '1' };
+    emit('update:modelValue', value);
+    emit('save', value);
 };
-const selectPageInfo = ref<any>(null);
+const selectPageInfo = computed<any>(() => {
+    if (!form.value.params || !form.value.params.pageId) return null;
+    return props.list.find((item) => item.id === form.value.params.pageId) || null;
+});
 const selectSuccess = (pageId: string) => {
     form.value.params.pageId = pageId;
-    // 找到对应的页面信息
-    const page = props.list.find(item => item.id === pageId);
-    selectPageInfo.value = page || null;
 };
+
 const changeEventName = (val: string) => {
     form.value.params = {};
 };
-watch(() => props.modelValue, (val) => {
-    form.value = val || {};
-}, { deep: true });
+const clearForm = () => {
+    enentFormRef.value.resetFields();
+};
+watch(
+    () => props.modelValue,
+    (val) => {
+        form.value = val || {};
+    },
+    { deep: true }
+);
 </script>
 <style lang="scss" scoped>
 .bg-img-item_view {

+ 3 - 0
src/views/training/models/meeting-tpl-h5.vue

@@ -72,5 +72,8 @@ const addImgBg = async () => {
         });
     }
 }
+watch(() => props.modelValue, (val) => {
+    form.value = val || { img: '', events: [] };
+}, { deep: true });
 </script>
 <style scoped lang="scss"></style>

+ 17 - 3
src/views/training/models/meeting-tpl-list.vue

@@ -3,10 +3,18 @@
         <template v-for="(item, index) in list" :key="index">
             <div class="border-bottom pd-10 c-s-p item-hover" @click="clickItem(item)">
                 <div v-if="+item.homeFlag" class="f-s-14 f-w-6 c-333 mb-10">门户页面</div>
-                <div>
+                <div class="d-flex">
                     <div class="w-140 h-180 bg-#ccc bg-img-item_view" :style="{ backgroundImage: 'url('+ item?.img +')' }"></div>
+                    <div class="flex1 ov-hd d-flex flex-cln j-sb">
+                        <div class="pd-10">
+                            <el-icon v-if="item?.events?.some(item => item.eventName)"><Sunny /></el-icon>
+                        </div>
+                        <div class="f-s-18 c-danger u-s-n c-s-p pd2-0-10" @click.stop="$emit('delete', item)">
+                            <el-icon><DeleteFilled /></el-icon>
+                        </div>
+                    </div>
                 </div>
-                <div class="c-666 f-s-14 pd2-10-0 u-s-n c-s-p d-flex a-c">
+                <div @click.stop="changeLabel(item)" class="c-666 f-s-14 pd2-10-0 u-s-n c-s-p d-flex a-c">
                     <span class="c-666 f-s-14 mr-6">{{ item?.label }}</span>
                     <el-icon><EditPen /></el-icon>
                 </div>
@@ -24,7 +32,9 @@
 import { httpRequests } from '@/utils/httpRequests';
 const emit = defineEmits<{
     (e: 'selectItem', value: any): void,
-    (e: 'addMeetingTpls'): void
+    (e: 'addMeetingTpls'): void,
+    (e: 'delete', value: any): void,
+    (e: 'changeLabel', value: any): void
 }>();
 const props = defineProps<{
     meetid: string,
@@ -40,6 +50,10 @@ const addMeetingTpls = async () => {
 const clickItem = (item: any) => {
     emit('selectItem', item);
 };
+// 更换页面名称
+const changeLabel = async (item: any) => {
+   emit('changeLabel', item);
+};
 </script>
 <style scoped lang="scss">
 .item-hover:hover {

+ 73 - 7
src/views/training/ptpl/edit/index.vue

@@ -5,7 +5,9 @@
                 <div class="flex1 ov-hd">
                     <span class="f-s-18 c-333 f-w-6">编辑会议宣传门户</span>
                     <el-button @click="router.go(-1)" text type="primary">
-                        <el-icon><Back /></el-icon>
+                        <el-icon>
+                            <Back />
+                        </el-icon>
                         返回上一级
                     </el-button>
                 </div>
@@ -17,12 +19,14 @@
             </div>
             <div class="flex1 ov-hd d-flex">
                 <div class="bg-#f8f8f8 w-200 box-sizing-border over-auto">
-                    <MeetingTplList v-if="meetid" :meetid="meetid" @selectItem="selectItem" :list="list"></MeetingTplList>
+                    <MeetingTplList v-if="meetid" :meetid="meetid" @selectItem="selectItem" :list="list" @addMeetingTpls="addMeetingTpls" @delete="deleteListTpl" @changeLabel="changeLabel"></MeetingTplList>
                 </div>
                 <div class="flex1 ov-hd d-flex flex-cln a-c">
-                    <div v-if="form.id" class="w-750 pd2-10-0 f-w-5">
-                        页面名称
-                        <el-icon><EditPen /></el-icon>
+                    <div v-if="form.id" @click="changeLabel(form)" class="w-750 pd2-10-0 f-w-5">
+                        {{ form?.label }}
+                        <el-icon>
+                            <EditPen />
+                        </el-icon>
                     </div>
                     <MeetingTplH5 v-if="form.id" v-model="form" @activated="activated" @deleteItemEvents="deleteItemEvents"></MeetingTplH5>
                 </div>
@@ -38,6 +42,8 @@ import router from '@/router';
 import { MeetingTplH5, MeetingTplList, MeetingTplEvents } from '../../models';
 import { useRoute } from 'vue-router';
 import { httpRequests } from '@/utils/httpRequests';
+import { importFileGetUrls } from '@/utils/models';
+import { it } from 'node:test';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const dict = proxy?.useDict('page_event')
 const { page_event } = toRefs<any>(dict);
@@ -53,10 +59,9 @@ const activated = (item: any) => {
     curEvent.value = item;
 };
 const selectItem = (item: any) => {
-    form.value = item;
+    form.value = { ...item };
 };
 const saveEevent = (item: any) => {
-    console.log(item);
     if (!form.value?.events || !form.value?.events.length) return;
     const index = form.value.events.findIndex((it: any) => it.id === item.id);
     if (index === -1) return;
@@ -80,6 +85,67 @@ const getList = async () => {
     if (!res || res.code !== 200) return;
     list.value = res.data;
 };
+const addMeetingTpls = async () => {
+    const res: any[] = await importFileGetUrls(['png', 'jpg', 'jpeg'], true);
+    // 过滤掉code不为200的
+    if (!res || !res.length) return;
+    const datas = res.filter(item => item.code === 200).map(item => item.data);
+    const promises = datas.map(item => {
+        return httpRequests.post('/dgtmedicine/trainpage/add', {
+            trainId: meetid.value,
+            label: '页面名称',
+            img: item.url,
+            homeFlag: 0,
+            events: []
+        });
+    });
+    const results = await Promise.all(promises);
+    const successResults = results.filter(item => item && item.code === 200).map(item => item.data);
+    if (!successResults.length) return;
+    getList();
+}
+const deleteListTpl = async (item: any) => {
+     ElMessageBox({
+        title: '删除提示',
+        cancelButtonText: '我再看看',
+        confirmButtonText: '确认删除',
+        showCancelButton: true,
+        confirmButtonClass: 'el-button--danger',
+        message: h('p', null, [h('div', null, ``), h('div', null, [h('span', null, '删除后页面和触发事件将同步删除,无法撤回,请谨慎操作!')])]),
+        callback: async (action: string) => {
+            if (action === 'confirm') {
+                const res = await httpRequests.get(`/dgtmedicine/trainpage/remove/${item.id}`);
+                if (res) {
+                    ElMessage.success('删除成功');
+                    if (item.id === form.value.id) {
+                        form.value = {};
+                        curEvent.value = null;
+                    }
+                    getList();
+                }
+            }
+        }
+    });
+};
+const changeLabel = async (item: any) => {
+    const { value: label } = await ElMessageBox.prompt('请输入页面名称', '修改页面名称', {
+        confirmButtonText: '保存',
+        cancelButtonText: '取消',
+        inputValue: item.label,
+        inputPattern: /^(?!\s*$).+/,
+        inputErrorMessage: '页面名称不能为空'
+    });
+    if (label !== undefined) {
+        const res = await httpRequests.post('/dgtmedicine/trainpage/edit', { ...item, label });
+        if (res && res.code === 200) {
+            ElMessage.success('修改成功');
+            getList();
+            if (item.id === form.value.id) {
+                form.value.label = label;
+            }
+        }
+    }
+};
 onMounted(() => {
     getList();
 });