feat:首页联调

This commit is contained in:
du.meimei
2025-03-12 18:20:30 +08:00
parent 0b5d08e3b9
commit e30652902e
31 changed files with 450 additions and 282 deletions

4
auto-imports.d.ts vendored
View File

@@ -5,6 +5,4 @@
// Generated by unplugin-auto-import
// biome-ignore lint: disable
export {}
declare global {
}
declare global {}

11
components.d.ts vendored
View File

@@ -10,28 +10,20 @@ declare module 'vue' {
Contenteditable: typeof import('./src/components/contenteditable.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
'Van-': typeof import('vant/es')['-']
VanActionSheet: typeof import('vant/es')['ActionSheet']
VanButton: typeof import('vant/es')['Button']
VanCell: typeof import('vant/es')['Cell']
VanCellGroup: typeof import('vant/es')['CellGroup']
VanCheck: typeof import('vant/es')['Check']
VanCheckbo: typeof import('vant/es')['Checkbo']
VanCheckbox: typeof import('vant/es')['Checkbox']
VanCheckboxGroup: typeof import('vant/es')['CheckboxGroup']
VanCol: typeof import('vant/es')['Col']
VanDatePicker: typeof import('vant/es')['DatePicker']
VanDatetimePicker: typeof import('vant/es')['DatetimePicker']
VanDialog: typeof import('vant/es')['Dialog']
VanDivider: typeof import('vant/es')['Divider']
VanFiel: typeof import('vant/es')['Fiel']
VanField: typeof import('vant/es')['Field']
VanGrid: typeof import('vant/es')['Grid']
VanGridItem: typeof import('vant/es')['GridItem']
VanIcon: typeof import('vant/es')['Icon']
VanNavBar: typeof import('vant/es')['NavBar']
VanPicker: typeof import('vant/es')['Picker']
VanPikcer: typeof import('vant/es')['Pikcer']
VanPopup: typeof import('vant/es')['Popup']
VanRadio: typeof import('vant/es')['Radio']
VanRadioGroup: typeof import('vant/es')['RadioGroup']
@@ -39,9 +31,10 @@ declare module 'vue' {
VanSearch: typeof import('vant/es')['Search']
VanStepper: typeof import('vant/es')['Stepper']
VanSwitch: typeof import('vant/es')['Switch']
VanTab: typeof import('vant/es')['Tab']
VanTabbar: typeof import('vant/es')['Tabbar']
VanTabbarItem: typeof import('vant/es')['TabbarItem']
VanTimePicker: typeof import('vant/es')['TimePicker']
VanTabs: typeof import('vant/es')['Tabs']
YLPicker: typeof import('./src/components/YLPicker.vue')['default']
YLSelect: typeof import('./src/components/YLSelect.vue')['default']
}

View File

@@ -4,7 +4,7 @@ import { onMounted } from 'vue';
import appBridge from '@/assets/js/appBridge';
import utils from '@/assets/js/common';
onMounted(async() => {
onMounted(async () => {
if (utils.getParameter('digitalYiliToken')) {
// 隐藏/显示 header
appBridge.setHeaderShown(false);

View File

@@ -17,3 +17,18 @@ export function consoleSurveys(params) {
}
});
}
export function getListScene(params) {
return request({
url: 'console/list_scene',
method: 'get',
params
});
}
//
export function getSurveyTemplates(params) {
return request({
url: '/console/survey_templates',
method: 'get',
params
});
}

View File

@@ -16,11 +16,10 @@ export default {
*/
_string2json(value) {
try {
value = JSON.parse(value);
return JSON.parse(value);
} catch (e) {
// 以后再说
}
return value;
},
/**

View File

@@ -167,8 +167,8 @@ const getMaxDateLimit = computed(() => {
props.format
);
const tempStr = '0000-12-31 23:59:59';
const result
= props.maxDate.length !== 0 && thisMax.length > props.maxDate.length
const result =
props.maxDate.length !== 0 && thisMax.length > props.maxDate.length
? thisMax.slice(0, props.maxDate.length) + tempStr.slice(props.maxDate.length)
: thisMax;
return result.slice(0, props.format.length);
@@ -191,8 +191,8 @@ function onChange({ selectedValues, columnIndex }) {
renderMinuteColumns,
renderSecondColumns
];
updateColumns[columnIndex]
&& updateColumns[columnIndex](changeValue, getMinDateLimit.value, getMaxDateLimit.value, false);
updateColumns[columnIndex] &&
updateColumns[columnIndex](changeValue, getMinDateLimit.value, getMaxDateLimit.value, false);
}
// 渲染全部列

View File

@@ -51,12 +51,14 @@ const router = createRouter({
name: 'preview',
meta: {},
component: Preview
}, {
},
{
path: '/create',
name: 'create',
meta: { title: '问卷编辑' },
component: () => import('../views/Survey/views/Create/Index.vue')
}, {
},
{
path: '/publish',
name: 'publish',
meta: { title: '问卷发布' },

View File

@@ -42,10 +42,10 @@ service.interceptors.request.use(
service.interceptors.response.use(
(response) => {
if (
response.status === 200
|| response.status === 201
|| response.status === 202
|| response.status === 204
response.status === 200 ||
response.status === 201 ||
response.status === 202 ||
response.status === 204
) {
if (response.config.method === 'put') {
// message.success('保存中...');

View File

@@ -1,6 +1,5 @@
<script setup lang="ts">
import PreviewIndex from './Index.vue';
</script>
<template>

View File

@@ -233,8 +233,8 @@ const getSkipTypeText = (skipType) => {
const ls = [];
logics.map((item) => {
if (
item.skip_type === skipType
&& item.question_index === activeQuestion.value.question_index
item.skip_type === skipType &&
item.question_index === activeQuestion.value.question_index
) {
ls.push(item);
}

View File

@@ -108,9 +108,9 @@ function isSurplus() {
return false;
} else {
return (
parseFloat(((localConfig.value.max - localConfig.value.min) * 1000).toFixed(4, 10))
% parseFloat((localConfig.value.score_interval * 1000).toFixed(4, 10))
=== 0
parseFloat(((localConfig.value.max - localConfig.value.min) * 1000).toFixed(4, 10)) %
parseFloat((localConfig.value.score_interval * 1000).toFixed(4, 10)) ===
0
);
}
}

View File

@@ -11,7 +11,8 @@
class="iconfont active-icon"
:style="{ marginRight: isLastPage ? '0' : '16px' }"
@click="activePage"
>&#xe86c;</i>
>&#xe86c;</i
>
<template v-if="!isLastPage">
<i class="iconfont moverQues" style="margin-right: 16px">&#xe71b;</i>
<i class="iconfont" @click="deleteHandle">&#xe6c5;</i>

View File

@@ -8,7 +8,7 @@ import utils from '@/assets/js/common';
import { getUserInfo } from '@/api/common/index.js';
import { showFailToast } from 'vant';
onMounted(async() => {
onMounted(async () => {
if (utils.getParameter('digitalYiliToken')) {
const query = {
xToken: utils.getParameter('digitalYiliToken')

View File

@@ -1,8 +1,7 @@
<script setup lang="ts">
// import { ref } from 'vue';
import { consoleSurveys } from '@/api/home/index.js';
<script setup>
import { ref, onMounted } from 'vue';
import { consoleSurveys, getQuestionList } from '@/api/home/index.js';
import { snQuestions, saveQuestions } from '@/api/design/index.js';
import { surveys } from './Hooks/useRequestHooks';
import { useRouter } from 'vue-router';
import { useCounterStore } from '@/stores/counter';
import { storeToRefs } from 'pinia';
@@ -11,6 +10,7 @@ const counterStore = useCounterStore();
const store = storeToRefs(counterStore);
const router = useRouter();
const surveys = ref([]);
const createdQuestion = (item) => {
const query = {
@@ -44,6 +44,28 @@ const createdQuestion = (item) => {
}
});
};
// 添加获取问卷列表的方法
const getList = () => {
getQuestionList().then((res) => {
if (res.data.code === 0) {
if (res.data.data) {
res.data.data.forEach((item) => {
if (item.parentCode && item.parentCode === 1) {
surveys.value.push(item);
}
});
surveys.value.push({});
}
}
});
};
// 在组件挂载时调用
onMounted(() => {
getList();
});
</script>
<template>
@@ -57,7 +79,7 @@ const createdQuestion = (item) => {
class="survey"
@click="createdQuestion(survey)"
>
<img width="45px" :src="survey.icon" alt=" " />
<img :src="survey.image" alt="" width="40" />
<span>{{ survey.title }}</span>
</van-col>
</van-row>

View File

@@ -1,11 +1,3 @@
<script setup lang="ts">
import { ref, h } from 'vue';
import { tables } from './hooks/useMarketHooks';
import TestComponent from './components/TestComponent.vue';
const activeComponet = ref(h(TestComponent, { cn: '报名签到' }));
</script>
<template>
<!-- 模板 -->
<div class="market">
@@ -15,15 +7,63 @@ const activeComponet = ref(h(TestComponent, { cn: '报名签到' }));
</div>
<div class="market_table">
<div v-for="item in tables" :key="item.title" @click="activeComponet = item.component">
<div v-for="item in tables" :key="item.title" @click="getMarketInfo(item)">
{{ item.title }}
</div>
</div>
<van-cell class="market_items">
<component :is="activeComponet" />
<market-item :info="marketInfo"></market-item>
<!-- <component :is="TestComponent" />-->
</van-cell>
<p class="more">-更多模板期待您的探索-</p>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import MarketItem from './components/MarketItem.vue';
import { getListScene, getSurveyTemplates } from '@/api/home';
interface SceneItem {
parentCode: number;
title: string;
component: any;
code: number;
}
const tables = ref<SceneItem[]>([]);
const marketInfo = ref([]);
const getTableList = async () => {
const res = await getListScene();
if (res.data.code === 0) {
res.data.data.forEach((item: SceneItem) => {
if (item.parentCode && item.parentCode === 1) {
tables.value.push(item);
}
});
getMarketInfo(tables.value[0]);
}
};
const getMarketInfo = async (item: SceneItem) => {
const params = {
page: 1,
per_page: 10,
group_id: 0,
is_public: 1,
scene_code_info: item.code,
sort: 'quote_nums, desc'
};
const res = await getSurveyTemplates(params);
if (res.data.code === 0) {
marketInfo.value = res.data.data;
}
};
onMounted(() => {
getTableList();
});
</script>
<style scoped>
.market {
@@ -70,5 +110,12 @@ const activeComponet = ref(h(TestComponent, { cn: '报名签到' }));
background-color: white;
}
}
.more {
margin: 10px 0;
color: #666;
font-size: 14px;
text-align: center;
}
}
</style>

View File

@@ -0,0 +1,57 @@
<template>
<van-row :gutter="12">
<van-col v-for="(item, index) in info" :key="index" :span="12" class="market-item">
<div class="content">
<div class="title">
<span>{{ item.title }}</span>
<img
src="https://files.axshare.com/gsc/DR6075/63/4d/77/634d77293a4d41d1b3d145974a8fb6a7/images/首页_1/u42.svg"
/>
</div>
<div class="desc">
<span>引用{{ item.quote_nums }}</span> |
<span>创建人: {{ item.creator }}</span>
</div>
</div>
</van-col>
</van-row>
</template>
<script setup lang="ts">
const { info } = defineProps({
info: {
type: Object,
required: true,
default: () => ({})
}
});
</script>
<style lang="scss" scoped>
.market-item {
margin-bottom: 12px;
.content {
padding: 12px;
border-radius: 8px;
background: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
.title {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
img {
width: 20px;
height: 20px;
}
}
.desc {
color: #666;
font-size: 12px;
}
}
}
</style>

View File

@@ -1,36 +0,0 @@
<script setup lang="ts">
const { cn } = defineProps({
cn: {
type: String,
required: false,
deault: 'default'
}
});
</script>
<template>
<van-row :gutter="4">
<van-col
v-for="item in 2"
:key="item"
:span="10"
style="
display: flex;
flex-direction: column;
align-items: start;
box-shadow: 0 3px 3px rgba(0, 0, 0, 0.1);
"
>
<div style="display: flex; align-items: center; justify-content: space-evenly; width: 100%">
<span>{{ cn }} 模板</span>
<img
src="https://files.axshare.com/gsc/DR6075/63/4d/77/634d77293a4d41d1b3d145974a8fb6a7/images/首页_1/u42.svg?pageId=5cc10b9f-56eb-48dc-943a-bfe7afb18a64"
/>
</div>
<div><span>引用10次</span> | <span>创建人: 张三</span></div>
</van-col>
</van-row>
</template>
<style lang="sass" scoped></style>

View File

@@ -1,4 +1,4 @@
import TestComponent from '../components/TestComponent.vue';
import TestComponent from '../components/MarketItem.vue';
import { h } from 'vue';
export const tables = [

View File

@@ -3,7 +3,9 @@
<div v-for="item in 10" :key="item" class="template">
<img src="https://picsum.photos/131/128" width="110" height="100" alt="" />
<span>报名/签到模板</span>
<span style="color: rgb(127, 127, 127)">报名签到 | 引用 {{ item }} | 创建人: {{ '张三' }}</span>
<span style="color: rgb(127, 127, 127)"
>报名签到 | 引用 {{ item }} | 创建人: {{ '张三' }}</span
>
</div>
</div>
</template>

View File

@@ -597,8 +597,8 @@ const previewQuestion = () => {
router.push({ name: 'preview', query: { ...route.query } });
};
onMounted(async() => {
await getQuestionDetail(); // 等待接口返回数据
onMounted(async () => {
await getQuestionDetail();
});
</script>

View File

@@ -84,7 +84,7 @@ interface PublishInfo {
const publishInfo = ref<PublishInfo>({} as PublishInfo);
type OperateItem = (typeof operateList)[0];
onMounted(async() => {
onMounted(async () => {
getQrcode('Xxgdr5EN')
.then((res) => {
if (res.data) {

View File

@@ -0,0 +1,69 @@
// vite.config.ts
import {
defineConfig,
loadEnv
} from 'file:///E:/yijiaofu/yili/GIT/ylst-survey-h5/node_modules/vite/dist/node/index.js';
import vue from 'file:///E:/yijiaofu/yili/GIT/ylst-survey-h5/node_modules/@vitejs/plugin-vue/dist/index.mjs';
import { fileURLToPath, URL } from 'node:url';
import vueJsx from 'file:///E:/yijiaofu/yili/GIT/ylst-survey-h5/node_modules/@vitejs/plugin-vue-jsx/dist/index.mjs';
import AutoImport from 'file:///E:/yijiaofu/yili/GIT/ylst-survey-h5/node_modules/unplugin-auto-import/dist/vite.js';
import Components from 'file:///E:/yijiaofu/yili/GIT/ylst-survey-h5/node_modules/unplugin-vue-components/dist/vite.js';
import { VantResolver } from 'file:///E:/yijiaofu/yili/GIT/ylst-survey-h5/node_modules/unplugin-vue-components/dist/resolvers.js';
import postCssPxToRem from 'file:///E:/yijiaofu/yili/GIT/ylst-survey-h5/node_modules/postcss-pxtorem/index.js';
var __vite_injected_original_import_meta_url =
'file:///E:/yijiaofu/yili/GIT/ylst-survey-h5/vite.config.ts';
var vite_config_default = defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd());
const proxyUrl = env.VITE_APP_BASEURL;
const proxyUrlDelivery = env.VITE_APP_DELIVERY_BASEURL;
return {
// 必须 return 配置对象
server: {
host: '0.0.0.0',
port: 3e3,
proxy: {
'/backend-api': {
target: proxyUrl,
changeOrigin: true,
pathRewrite: {
'^/backend-api': ''
// 路径重写
},
// bypass: (req) => req.headers.accept?.indexOf('html') !== -1, // 跳过 HTML 请求
cookieDomainRewrite: 'localhost'
},
'/request-java': {
target: `${proxyUrlDelivery}/api`,
changeOrigin: true,
pathRewrite: { '^/request-java': '' }
}
}
},
css: {
postcss: {
plugins: [
postCssPxToRem({
rootValue: 37.5,
propList: ['*']
})
]
},
preprocessorOptions: {
scss: { api: 'modern-compiler' }
}
},
plugins: [
vue(),
vueJsx(),
AutoImport({ resolvers: [VantResolver()] }),
Components({ resolvers: [VantResolver()] })
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', __vite_injected_original_import_meta_url))
}
}
};
});
export { vite_config_default as default };
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJFOlxcXFx5aWppYW9mdVxcXFx5aWxpXFxcXEdJVFxcXFx5bHN0LXN1cnZleS1oNVwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiRTpcXFxceWlqaWFvZnVcXFxceWlsaVxcXFxHSVRcXFxceWxzdC1zdXJ2ZXktaDVcXFxcdml0ZS5jb25maWcudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0U6L3lpamlhb2Z1L3lpbGkvR0lUL3lsc3Qtc3VydmV5LWg1L3ZpdGUuY29uZmlnLnRzXCI7Ly8gdml0ZS5jb25maWcudHNcclxuaW1wb3J0IHsgZGVmaW5lQ29uZmlnLCBsb2FkRW52IH0gZnJvbSAndml0ZSc7IC8vIFx1NEVDRSB2aXRlIFx1NUJGQ1x1NTE2NSBsb2FkRW52XHJcbmltcG9ydCB2dWUgZnJvbSAnQHZpdGVqcy9wbHVnaW4tdnVlJztcclxuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCwgVVJMIH0gZnJvbSAnbm9kZTp1cmwnO1xyXG5pbXBvcnQgdnVlSnN4IGZyb20gJ0B2aXRlanMvcGx1Z2luLXZ1ZS1qc3gnO1xyXG5pbXBvcnQgQXV0b0ltcG9ydCBmcm9tICd1bnBsdWdpbi1hdXRvLWltcG9ydC92aXRlJztcclxuaW1wb3J0IENvbXBvbmVudHMgZnJvbSAndW5wbHVnaW4tdnVlLWNvbXBvbmVudHMvdml0ZSc7XHJcbmltcG9ydCB7IFZhbnRSZXNvbHZlciB9IGZyb20gJ3VucGx1Z2luLXZ1ZS1jb21wb25lbnRzL3Jlc29sdmVycyc7XHJcbmltcG9ydCBwb3N0Q3NzUHhUb1JlbSBmcm9tICdwb3N0Y3NzLXB4dG9yZW0nO1xyXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoKHsgbW9kZSB9KSA9PiB7XHJcbiAgLy8gXHU2M0E1XHU2NTM2IG1vZGUgXHU1M0MyXHU2NTcwXHJcbiAgLy8gXHU2QjYzXHU3ODZFXHU1MkEwXHU4RjdEXHU3M0FGXHU1ODgzXHU1M0Q4XHU5MUNGXHJcbiAgY29uc3QgZW52ID0gbG9hZEVudihtb2RlLCBwcm9jZXNzLmN3ZCgpKTtcclxuXHJcbiAgLy8gXHU0RUNFIGVudiBcdTVCRjlcdThDNjFcdTRFMkRcdTgzQjdcdTUzRDZcdTUzRDhcdTkxQ0ZcclxuICBjb25zdCBwcm94eVVybCA9IGVudi5WSVRFX0FQUF9CQVNFVVJMO1xyXG4gIGNvbnN0IHByb3h5VXJsRGVsaXZlcnkgPSBlbnYuVklURV9BUFBfREVMSVZFUllfQkFTRVVSTDtcclxuICByZXR1cm4ge1xyXG4gICAgLy8gXHU1RkM1XHU5ODdCIHJldHVybiBcdTkxNERcdTdGNkVcdTVCRjlcdThDNjFcclxuICAgIHNlcnZlcjoge1xyXG4gICAgICBob3N0OiAnMC4wLjAuMCcsXHJcbiAgICAgIHBvcnQ6IDMwMDAsXHJcbiAgICAgIHByb3h5OiB7XHJcbiAgICAgICAgJy9iYWNrZW5kLWFwaSc6IHtcclxuICAgICAgICAgIHRhcmdldDogcHJveHlVcmwsXHJcbiAgICAgICAgICBjaGFuZ2VPcmlnaW46IHRydWUsXHJcbiAgICAgICAgICBwYXRoUmV3cml0ZToge1xyXG4gICAgICAgICAgICAnXi9iYWNrZW5kLWFwaSc6ICcnIC8vIFx1OERFRlx1NUY4NFx1OTFDRFx1NTE5OVxyXG4gICAgICAgICAgfSxcclxuICAgICAgICAgIC8vIGJ5cGFzczogKHJlcSkgPT4gcmVxLmhlYWRlcnMuYWNjZXB0Py5pbmRleE9mKCdodG1sJykgIT09IC0xLCAvLyBcdThERjNcdThGQzcgSFRNTCBcdThCRjdcdTZDNDJcclxuICAgICAgICAgIGNvb2tpZURvbWFpblJld3JpdGU6ICdsb2NhbGhvc3QnXHJcbiAgICAgICAgfSxcclxuICAgICAgICAnL3JlcXVlc3QtamF2YSc6IHtcclxuICAgICAgICAgIHRhcmdldDogYCR7cHJveHlVcmxEZWxpdmVyeX0vYXBpYCxcclxuICAgICAgICAgIGNoYW5nZU9yaWdpbjogdHJ1ZSxcclxuICAgICAgICAgIHBhdGhSZXdyaXRlOiB7ICdeL3JlcXVlc3QtamF2YSc6ICcnIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0sXHJcbiAgICBjc3M6IHtcclxuICAgICAgcG9zdGNzczoge1xyXG4gICAgICAgIHBsdWdpbnM6IFtcclxuICAgICAgICAgIHBvc3RDc3NQeFRvUmVtKHtcclxuICAgICAgICAgICAgcm9vdFZhbHVlOiAzNy41LFxyXG4gICAgICAgICAgICBwcm9wTGlzdDogWycqJ11cclxuICAgICAgICAgIH0pXHJcbiAgICAgICAgXVxyXG4gICAgICB9LFxyXG4gICAgICBwcmVwcm9jZXNzb3JPcHRpb25zOiB7XHJcbiAgICAgICAgc2NzczogeyBhcGk6ICdtb2Rlcm4tY29tcGlsZXInIH1cclxuICAgICAgfVxyXG4gICAgfSxcclxuICAgIHBsdWdpbnM6IFtcclxuICAgICAgdnVlKCksXHJcbiAgICAgIHZ1ZUpzeCgpLFxyXG4gICAgICBBdXRvSW1wb3J0KHsgcmVzb2x2ZXJzOiBbVmFudFJlc29sdmVyKCldIH0pLFxyXG4gICAgICBDb21wb25lbnRzKHsgcmVzb2x2ZXJzOiBbVmFudFJlc29sdmVyKCldIH0pXHJcbiAgICBdLFxyXG4gICAgcmVzb2x2ZToge1xyXG4gICAgICBhbGlhczoge1xyXG4gICAgICAgICdAJzogZmlsZVVSTFRvUGF0aChuZXcgVVJMKCcuL3NyYycsIGltcG9ydC5tZXRhLnVybCkpXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9O1xyXG59KTtcclxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUNBLFNBQVMsY0FBYyxlQUFlO0FBQ3RDLE9BQU8sU0FBUztBQUNoQixTQUFTLGVBQWUsV0FBVztBQUNuQyxPQUFPLFlBQVk7QUFDbkIsT0FBTyxnQkFBZ0I7QUFDdkIsT0FBTyxnQkFBZ0I7QUFDdkIsU0FBUyxvQkFBb0I7QUFDN0IsT0FBTyxvQkFBb0I7QUFSNEosSUFBTSwyQ0FBMkM7QUFTeE8sSUFBTyxzQkFBUSxhQUFhLENBQUMsRUFBRSxLQUFLLE1BQU07QUFHeEMsUUFBTSxNQUFNLFFBQVEsTUFBTSxRQUFRLElBQUksQ0FBQztBQUd2QyxRQUFNLFdBQVcsSUFBSTtBQUNyQixRQUFNLG1CQUFtQixJQUFJO0FBQzdCLFNBQU87QUFBQTtBQUFBLElBRUwsUUFBUTtBQUFBLE1BQ04sTUFBTTtBQUFBLE1BQ04sTUFBTTtBQUFBLE1BQ04sT0FBTztBQUFBLFFBQ0wsZ0JBQWdCO0FBQUEsVUFDZCxRQUFRO0FBQUEsVUFDUixjQUFjO0FBQUEsVUFDZCxhQUFhO0FBQUEsWUFDWCxpQkFBaUI7QUFBQTtBQUFBLFVBQ25CO0FBQUE7QUFBQSxVQUVBLHFCQUFxQjtBQUFBLFFBQ3ZCO0FBQUEsUUFDQSxpQkFBaUI7QUFBQSxVQUNmLFFBQVEsR0FBRyxnQkFBZ0I7QUFBQSxVQUMzQixjQUFjO0FBQUEsVUFDZCxhQUFhLEVBQUUsa0JBQWtCLEdBQUc7QUFBQSxRQUN0QztBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsSUFDQSxLQUFLO0FBQUEsTUFDSCxTQUFTO0FBQUEsUUFDUCxTQUFTO0FBQUEsVUFDUCxlQUFlO0FBQUEsWUFDYixXQUFXO0FBQUEsWUFDWCxVQUFVLENBQUMsR0FBRztBQUFBLFVBQ2hCLENBQUM7QUFBQSxRQUNIO0FBQUEsTUFDRjtBQUFBLE1BQ0EscUJBQXFCO0FBQUEsUUFDbkIsTUFBTSxFQUFFLEtBQUssa0JBQWtCO0FBQUEsTUFDakM7QUFBQSxJQUNGO0FBQUEsSUFDQSxTQUFTO0FBQUEsTUFDUCxJQUFJO0FBQUEsTUFDSixPQUFPO0FBQUEsTUFDUCxXQUFXLEVBQUUsV0FBVyxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUM7QUFBQSxNQUMxQyxXQUFXLEVBQUUsV0FBVyxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUM7QUFBQSxJQUM1QztBQUFBLElBQ0EsU0FBUztBQUFBLE1BQ1AsT0FBTztBQUFBLFFBQ0wsS0FBSyxjQUFjLElBQUksSUFBSSxTQUFTLHdDQUFlLENBQUM7QUFBQSxNQUN0RDtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQ0YsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K