Browse Source

BUG修复

master
wxc 2 years ago
parent
commit
8fe13b9834
  1. 1
      .env
  2. 1
      .env.dev
  3. 1
      .env.prod
  4. 2
      .gitignore
  5. 19
      nginx.conf
  6. 8
      package.json
  7. 7
      src/assets/style/style.scss
  8. 116
      src/components/FileList.vue
  9. 44
      src/components/ImgPreview.vue
  10. 6
      src/main.js
  11. 46
      src/permission.js
  12. 10
      src/store/wx.js
  13. 174
      src/views/Home.vue
  14. 101
      src/views/RealNameAuth.vue
  15. 56
      src/views/mail/MailDetail.vue
  16. 5
      src/views/mail/MailEvaluate.vue
  17. 60
      src/views/mail/components/MyMail.vue
  18. 1109
      src/views/mail/components/Write.vue
  19. 95
      vite.config.js

1
.env

@ -0,0 +1 @@
VITE_WX_REDIRECT_URI=https://mailbox.biutag.com/

1
.env.dev

@ -0,0 +1 @@
VITE_WX_REDIRECT_URI=https://mailbox.biutag.com/

1
.env.prod

@ -0,0 +1 @@
VITE_WX_REDIRECT_URI=https://jzxx.biutag.com/

2
.gitignore vendored

@ -6,3 +6,5 @@ node_modules
dist dist
.history .history
*.zip

19
nginx.conf

@ -1,19 +0,0 @@
client_max_body_size 10M;
server {
listen 80;
server_name mailbox.biutag.com;
location / {
root /usr/share/nginx/html/mailbox;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://172.31.217.20:30784/;
}
}

8
package.json

@ -6,19 +6,25 @@
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "vite build", "build": "vite build",
"build:prod": "vite build --mode prod",
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"crypto-js": "^4.2.0", "crypto-js": "^4.2.0",
"install": "^0.13.0",
"npm": "^10.5.0",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"vant": "^4.8.2", "vant": "^4.8.2",
"vue": "^3.3.11", "vue": "^3.3.11",
"vue-router": "^4.2.5" "vue-router": "^4.2.5",
"vue-touch": "^2.0.0-beta.4",
"vue3-touch-events": "^4.1.8"
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-vue": "^4.5.2", "@vitejs/plugin-vue": "^4.5.2",
"sass": "^1.69.7", "sass": "^1.69.7",
"unplugin-auto-import": "^0.17.3", "unplugin-auto-import": "^0.17.3",
"vconsole": "^3.15.1",
"vite": "^5.0.8", "vite": "^5.0.8",
"vite-svg-loader": "^5.1.0" "vite-svg-loader": "^5.1.0"
} }

7
src/assets/style/style.scss

@ -79,7 +79,7 @@ svg+span {
} }
.flex.gap-10 { .flex.gap-10 {
gap: 0 10px; gap: 10px;
} }
.flex.gap-16 { .flex.gap-16 {
@ -187,6 +187,11 @@ svg+span {
margin-top: 16px; margin-top: 16px;
font-size: 17px; font-size: 17px;
font-weight: bold; font-weight: bold;
.state {
font-size: 14px;
font-weight: 500;
color: var(--primary-color);
}
} }
.content { .content {

116
src/components/FileList.vue

@ -0,0 +1,116 @@
<template>
<div class="attachments" v-if="files.length">
<template v-for="(file, index) in files" :key="index">
<div
:style="{
backgroundImage: `url(/api/file/stream/${file.filepath})`,
}"
class="file"
@click="handlePreview(file, index)"
></div>
</template>
</div>
<van-empty v-else description="无附件" style="padding-top: 0" />
<div
v-if="show"
class="img-preview-container flex v-center center"
@click="show = false"
>
<img :src="filepath" v-touch:swipe.left="swipeleft" v-touch:swipe.right="swiperight" />
<div class="dots flex-inline gap">
<span
v-for="(item, index) in Array.from({ length: files.length })"
:key="index"
:active="activeIndex === index"
></span>
</div>
</div>
</template>
<script setup>
const props = defineProps({
files: {
type: Array,
default: [],
},
});
const show = ref(false);
const filepath = ref("");
const activeIndex = ref(-1);
function handlePreview(file, index) {
activeIndex.value = index;
filepath.value = `/api/file/stream/${file.filepath}`;
show.value = true;
}
function swipeleft() {
if (activeIndex.value === props.files.length - 1) {
activeIndex.value = 0
} else {
activeIndex.value += 1;
}
filepath.value = `/api/file/stream/${
props.files[activeIndex.value].filepath
}`;
}
function swiperight() {
if (activeIndex.value === 0) {
activeIndex.value = props.files.length - 1
} else {
activeIndex.value -= 1;
}
filepath.value = `/api/file/stream/${
props.files[activeIndex.value].filepath
}`;
}
</script>
<style lang="scss" scoped>
.attachments {
margin-top: 10px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 10px;
.file {
background-color: #f3faff;
height: 108px;
background-size: cover;
.name {
width: 100%;
max-width: 108px;
text-align: center;
max-height: 38px;
overflow: hidden;
word-break: break-word;
}
}
}
.img-preview-container {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #0e0e0e;
z-index: 2;
img {
max-width: 100%;
}
.dots {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
span {
display: block;
width: 8px;
height: 8px;
background-color: #777;
border-radius: 50%;
&[active="true"] {
background-color: #fff;
}
}
}
}
</style>

44
src/components/ImgPreview.vue

@ -1,44 +0,0 @@
<template>
<div v-if="show" @click="hide" class="img-preview-container flex v-center center">
<img :src="filepath" alt="" />
</div>
</template>
<script setup>
import { watch } from "vue"
const props = defineProps({
filepath: {
type: String,
default: ''
},
show: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['update:show'])
const show = ref(false)
watch(() => props.show, (val) => {
show.value = val
})
function hide() {
emit('update:show', false)
}
</script>
<style lang="scss" scoped>
.img-preview-container {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #000;
z-index: 2;
img {
max-width: 100%;
}
}
</style>

6
src/main.js

@ -7,6 +7,7 @@ import App from './App.vue'
import { Button, Tab, Tabs, Form, Field, CellGroup, Cell, RadioGroup, Radio, Uploader, Icon, Popup, Loading, Overlay, Empty, List, Picker } from 'vant'; import { Button, Tab, Tabs, Form, Field, CellGroup, Cell, RadioGroup, Radio, Uploader, Icon, Popup, Loading, Overlay, Empty, List, Picker } from 'vant';
import IconComponent from '@/components/Icon.vue' import IconComponent from '@/components/Icon.vue'
import LoadingComponent from '@/components/Loading.vue' import LoadingComponent from '@/components/Loading.vue'
import Vue3TouchEvents from "vue3-touch-events";
import './permission' // 权限控制 import './permission' // 权限控制
@ -15,7 +16,7 @@ import './assets/style/style.scss'
import './assets/style/vant.scss' import './assets/style/vant.scss'
// import VConsole from 'vconsole'; // import VConsole from 'vconsole';
//
// const vConsole = new VConsole(); // const vConsole = new VConsole();
const app = createApp(App) const app = createApp(App)
@ -38,6 +39,7 @@ const app = createApp(App)
.use(Empty) .use(Empty)
.use(List) .use(List)
.use(Picker) .use(Picker)
.use(Vue3TouchEvents)
.component('Icon', IconComponent) .component('Icon', IconComponent)
.component('Loading', LoadingComponent); .component('Loading', LoadingComponent);
app.mount('#app') app.mount('#app')

46
src/permission.js

@ -2,10 +2,17 @@ import router from './router'
import UserStore from "@/store/user" import UserStore from "@/store/user"
import { showToast } from 'vant'; import { showToast } from 'vant';
import { getToken } from '@/util/cookie' import { getToken } from '@/util/cookie'
import { showLoadingToast } from "vant";
// 白名单 // 白名单
const whiteList = ['/']; const whiteList = ['/'];
let toast;
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
toast = showLoadingToast({
message: "加载中...",
forbidClick: true,
duration: 0,
});
const whiteFlag = whiteList.indexOf(to.path) !== -1; const whiteFlag = whiteList.indexOf(to.path) !== -1;
const userStore = UserStore(); const userStore = UserStore();
const token = getToken(); const token = getToken();
@ -21,33 +28,26 @@ router.beforeEach((to, from, next) => {
} }
// 已有用户信息 // 已有用户信息
if (userStore.user.id) { if (userStore.user.id) {
// 判断用户是否进行了人脸认证 if (to.path === '/realName/auth' || userStore.user.faceAuth) {
if (userStore.user.idCard || to.path === '/realName/auth') { next()
// 判断是否是从信件页面回退到人脸认证界面的,如果是则返回首页 } else {
if (to.path === '/realName/auth' && from.path === '/mail') { next('/realName/auth')
next('/'); }
return
}
next();
return
}
next('/realName/auth');
return return
} }
// 获取用户信息 // 获取用户信息
userStore.getUser().then(() => { userStore.getUser().then(() => {
// 判断用户是否进行了人脸认证 // 解决人脸认证页面回退空白页
if (userStore.user.idCard || to.path === '/realName/auth') { if (to.path === '/realName/auth' || userStore.user.faceAuth) {
// 判断是否是从信件页面回退到人脸认证界面的,如果是则返回首页 next()
if (to.path === '/realName/auth' && from.path === '/mail') { } else {
next('/'); next('/realName/auth')
return }
} }).catch(() => {
next();
return
}
next('/realName/auth');
}).catch((res) => {
next('/') next('/')
}) })
})
router.afterEach(() => {
toast.close()
}) })

10
src/store/wx.js

@ -20,7 +20,7 @@ const WxStore = defineStore(
nonceStr: data.nonceStr, // 必填,生成签名的随机串 nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature, // 必填,签名 signature: data.signature, // 必填,签名
jsApiList: ["chooseImage", 'getLocalImgData', 'previewImage'], // 必填,需要使用的JS接口列表 jsApiList: ["chooseImage", 'getLocalImgData', 'previewImage'], // 必填,需要使用的JS接口列表
openTagList: ["wx-open-launch-weapp"], openTagList: ["wx-open-launch-weapp"]
}); });
wx.ready(function () { wx.ready(function () {
_this.signInitFlag = true _this.signInitFlag = true
@ -31,7 +31,13 @@ const WxStore = defineStore(
console.log('签名失败') console.log('签名失败')
reject(res) reject(res)
}); });
resolve() setTimeout(() => {
if (_this.signInitFlag) {
resolve()
} else {
reject('签名加载失败')
}
}, 1000)
}).catch((res) => { }).catch((res) => {
reject(res) reject(res)
}); });

174
src/views/Home.vue

@ -1,45 +1,45 @@
<template> <template>
<div class="wrapper"> <div class="wrapper">
<header> <header>
<img src="/imgs/bg1.png" alt=""/> <img src="/imgs/bg1.png" alt="" />
</header> </header>
<main> <main>
<div class="flex gap-10 center mt-20"> <div class="flex gap-10 center mt-20">
<a <a
class="flex v-center center gap-16" class="flex v-center center gap-16"
@click="router.push('/realName/auth')" @click="go('/mail?active=write')"
> >
<div style="width: 48px"> <div style="width: 48px">
<img src="/imgs/write.png" alt=""/> <img src="/imgs/write.png" alt="" />
</div> </div>
<span>我要写信</span> <span>我要写信</span>
</a> </a>
<a <a
class="flex v-center center gap-16" class="flex v-center center gap-16"
@click="router.push('/mail?active=my')" @click="go('/mail?active=my')"
> >
<div style="width: 48px"> <div style="width: 48px">
<img src="/imgs/search.png" alt=""/> <img src="/imgs/search.png" alt="" />
</div> </div>
<span>回复查询</span> <span>回复查询</span>
</a> </a>
</div> </div>
<p class="text-center mt-20"> <p class="text-center mt-20">
局长信箱只接受实名举报投诉不受理报警业务 局长信箱只接受实名举报投诉不受理报警业务
</p> </p>
<p class="text-center">如遇紧急情况请拨打110</p> <p class="text-center">如遇紧急情况请拨打110</p>
</main>
</main> <footer class="text-center">
</div> <a href="https://beian.miit.gov.cn" target="_blank">湘ICP备19012776号-1</a>
</footer>
<Loading :loading="loading"/> </div>
</template> </template>
<script setup> <script setup>
import {useRoute, useRouter} from "vue-router"; import { showLoadingToast } from "vant";
import {auth, authOpenid} from "@/api/auth"; import { useRoute, useRouter } from "vue-router";
import { auth, authOpenid } from "@/api/auth";
import UserStore from "@/store/user"; import UserStore from "@/store/user";
import {setToken, getToken} from "@/util/cookie"; import { setToken, getToken } from "@/util/cookie";
import WxStore from "@/store/wx"; import WxStore from "@/store/wx";
const wxStore = WxStore(); const wxStore = WxStore();
@ -48,64 +48,74 @@ const router = useRouter();
const route = useRoute(); const route = useRoute();
const userStore = UserStore(); const userStore = UserStore();
const toast = showLoadingToast({
message: "加载中...",
forbidClick: true,
duration: 0,
});
const code = route.query.code; const code = route.query.code;
const loading = ref(true)
if (!getToken()) { if (!getToken()) {
if (code) { if (code) {
// //
auth(code).then((data) => { auth(code).then((data) => {
setToken(data.token); setToken(data.token);
userStore.user = data.user; userStore.user = data.user;
loading.value = false toast.close();
window.location.href = "https://mailbox.biutag.com/" window.location.href = "https://jzxx.biutag.com/"
// wxStore.initSign() });
}); } else if (route.query.openid) {
} else if (route.query.openid) { //
// authOpenid(route.query.openid).then((data) => {
authOpenid(route.query.openid).then((data) => { setToken(data.token);
setToken(data.token); userStore.user = data.user;
userStore.user = data.user; toast.close();
loading.value = false });
window.location.href = "https://mailbox.biutag.com/" } else {
// wxStore.initSign() const appid = "wx795f76e4bc3b0062";
}); // // const location = window.location.href
} else { window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${encodeURIComponent(
const appid = "wx795f76e4bc3b0062"; location.origin
// const location = window.location.href )}&response_type=code&scope=snsapi_base&state=#wechat_redirect`;
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${encodeURIComponent( }
"https://mailbox.biutag.com/"
)}&response_type=code&scope=snsapi_base&state=#wechat_redirect`;
// window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${encodeURIComponent('https://mailbox.biutag.com/#/code?abc')}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect`
// https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx795f76e4bc3b0062&redirect_uri=https%3A%2F%2Fmailbox.biutag.com%2F&response_type=code&scope=snsapi_base&state=123#wechat_redirect'
}
} else { } else {
loading.value = false toast.close();
wxStore.initSign() wxStore.initSign()
}
function go(url) {
router.push(url)
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.wrapper { .wrapper {
background-color: #fff; background-color: #fff;
} }
header { header {
img { img {
width: 100%; width: 100%;
} }
} }
a { a {
width: 45.2%; width: 45.2%;
height: 84px; height: 84px;
text-decoration: none; text-decoration: none;
border: 1px solid var(--primary-color); border: 1px solid var(--primary-color);
color: var(--primary-color); color: var(--primary-color);
font-weight: bold; font-weight: bold;
font-size: 18px; font-size: 18px;
&:hover { &:hover {
cursor: pointer; cursor: pointer;
}
}
footer {
margin-top: 34vh;
a {
font-size: 12px;
font-weight: 500;
border: none;
} }
} }
</style> </style>

101
src/views/RealNameAuth.vue

@ -55,7 +55,7 @@ import { validatorIdCard } from "@/util/validator";
import { realUserInfo } from "@/api/auth"; import { realUserInfo } from "@/api/auth";
import UserStore from "@/store/user"; import UserStore from "@/store/user";
import WxStore from "@/store/wx"; import WxStore from "@/store/wx";
import { showToast } from "vant"; import { nextTick } from "vue";
const router = useRouter(); const router = useRouter();
const userStore = UserStore(); const userStore = UserStore();
@ -63,47 +63,44 @@ const wxStore = WxStore();
const showForm = ref(false); const showForm = ref(false);
const formRef = ref(null); const formRef = ref(null);
const form = ref({}); const form = ref({
realName: userStore.user.realName,
idCard: userStore.user.idCard,
});
const disabled = ref(true); const disabled = ref(true);
// //
if (!wxStore.signInitFlag) { // if (!wxStore.signInitFlag) {
//
// //
wxStore.initSign() wxStore.initSign();
} else {
if (form.value.realName && validatorIdCard(form.value.idCard) === true) {
nextTick(() => {
onFinish();
});
}
} }
watch(
() => wxStore.signInitFlag,
(val) => {
if (val) {
if (
form.value.realName &&
validatorIdCard(form.value.idCard) === true
) {
nextTick(() => {
onFinish();
});
}
}
}
);
function onInput() { function onInput() {
if (form.value.realName && validatorIdCard(form.value.idCard) === true) { if (form.value.realName && validatorIdCard(form.value.idCard) === true) {
disabled.value = false; onFinish();
const extraData = JSON.stringify(form.value);
const pathParam = `name=${form.value.realName}&idCard=${form.value.idCard}&userId=${userStore.user.id}`;
const script = document.createElement("script");
script.type = "text/wxtag-template";
script.text = `<div style="height: 44px; widht: 100vw"></div>`;
// env-version="trial"
const html = `<wx-open-launch-weapp style="width:100%;height:100%;display:block;" appid="wx6eb7bd5c49012475" username="gh_a3858f362acb" path="pages/index/index?${pathParam}" extra-data="${extraData}">${script.outerHTML}</wx-open-launch-weapp>`;
//const html = `<wx-open-launch-weapp style="width:100%;height:100%;display:block;" appid="wx453836cd13d31ea0" username="gh_eb26182512cb" path="pages/index/index?${pathParam}" extra-data="${extraData}">${script.outerHTML}</wx-open-launch-weapp>`;
document.querySelector("#launch-btn").innerHTML = html;
const launchEl = document.querySelector(
"#launch-btn wx-open-launch-weapp"
);
launchEl.addEventListener("launch", function (e) {
console.log("launch");
let timer = setInterval(() => {
realUserInfo(userStore.user.id).then((data) => {
if (data.idCard) {
userStore.user = data;
clearInterval(timer);
//
router.push("/mail");
}
});
}, 1000);
});
launchEl.addEventListener("error", function (e) {
});
} else { } else {
disabled.value = true; disabled.value = true;
if ( if (
@ -115,6 +112,36 @@ function onInput() {
} }
} }
} }
function onFinish() {
console.log("onFinish");
disabled.value = false;
const extraData = JSON.stringify(form.value);
const pathParam = `name=${form.value.realName}&idCard=${form.value.idCard}&userId=${userStore.user.id}`;
const script = document.createElement("script");
script.type = "text/wxtag-template";
script.text = `<div style="height: 44px; widht: 100vw"></div>`;
// env-version="trial"
//const html = `<wx-open-launch-weapp style="width:100%;height:100%;display:block;" appid="wx6eb7bd5c49012475" username="gh_a3858f362acb" path="pages/index/index?${pathParam}" extra-data="${extraData}">${script.outerHTML}</wx-open-launch-weapp>`;
const html = `<wx-open-launch-weapp style="width:100%;height:100%;display:block;" appid="wx453836cd13d31ea0" username="gh_eb26182512cb" path="pages/index/index?${pathParam}" extra-data="${extraData}">${script.outerHTML}</wx-open-launch-weapp>`;
document.querySelector("#launch-btn").innerHTML = html;
const launchEl = document.querySelector("#launch-btn wx-open-launch-weapp");
launchEl.addEventListener("launch", function (e) {
console.log("launch");
let timer = setInterval(() => {
realUserInfo(userStore.user.id).then((data) => {
if (data.faceAuth) {
userStore.user = data;
clearInterval(timer);
//
router.push("/mail");
}
});
}, 1000);
});
launchEl.addEventListener("error", function (e) {});
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.page { .page {
@ -151,9 +178,9 @@ function onInput() {
padding: 24px var(--van-cell-horizontal-padding) 28px; padding: 24px var(--van-cell-horizontal-padding) 28px;
.van-button { .van-button {
--van-button-normal-font-size: 16px; --van-button-normal-font-size: 16px;
&.van-button--disabled { &.van-button--disabled {
background-color: #6C707D; background-color: #6c707d;
--van-button-disabled-opacity: 1; --van-button-disabled-opacity: 1;
} }
} }

56
src/views/mail/MailDetail.vue

@ -31,41 +31,29 @@
</div> </div>
<div class="row"> <div class="row">
<label>附件</label> <label>附件</label>
<div class="attachments" v-if="mail.attachments"> <FileList :files="mail.attachments ? JSON.parse(mail.attachments) : []" />
<template
v-for="(file, index) in JSON.parse(mail.attachments)"
:key="index"
>
<img :src="`/api/file/stream/${file.filepath}`" @click="handleShowImgPreview(`/api/file/stream/${file.filepath}`)" />
</template>
</div>
<van-empty
v-if="
mail.attachments && !JSON.parse(mail.attachments).length
"
description="无附件"
style="padding-top: 0"
/>
</div> </div>
</div> </div>
</div> </div>
<Loading :loading="loading" />
<ImgPreview v-model:filepath="imgFilepath" v-model:show="showImgPreview" />
</template> </template>
<script setup> <script setup>
import FileList from "@/components/FileList.vue";
import { showLoadingToast } from "vant";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { getMail } from "@/api/mail"; import { getMail } from "@/api/mail";
const route = useRoute(); const route = useRoute();
const loading = ref(true);
const mail = ref({}); const mail = ref({});
const toast = showLoadingToast({
message: "加载中...",
forbidClick: true,
duration: 0,
});
if (route.params.id) { if (route.params.id) {
getMail(route.params.id).then((data) => { getMail(route.params.id).then((data) => {
mail.value = data; mail.value = data;
loading.value = false; toast.close()
}); });
} }
@ -97,29 +85,7 @@ function handleShowImgPreview(filepath) {
border-radius: 4px; border-radius: 4px;
min-height: 60px; min-height: 60px;
} }
.attachments {
margin-top: 10px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 10px;
img {
width: 100%;
height: 108px;
}
.file {
background-color: #f3faff;
height: 108px;
.name {
width: 100%;
max-width: 108px;
text-align: center;
max-height: 38px;
overflow: hidden;
word-break: break-word;
}
}
}
} }
} }
</style> </style>

5
src/views/mail/MailEvaluate.vue

@ -29,9 +29,12 @@ import { showSuccessToast } from "vant";
const route = useRoute(); const route = useRoute();
const router = useRouter(); const router = useRouter();
const satisfaction = ref(route.query.satisfaction || "SATISFIED"); const satisfaction = ref(route.query.satisfaction && route.query.satisfaction !== 'null' ? route.query.satisfaction : "satisfied");
function sumbit() { function sumbit() {
if (!satisfaction.value) {
return
}
updateEvaluate({ updateEvaluate({
mailId: route.params.id, mailId: route.params.id,
satisfaction: satisfaction.value satisfaction: satisfaction.value

60
src/views/mail/components/MyMail.vue

@ -7,14 +7,23 @@
> >
<template #default> <template #default>
<div class="card" v-for="mail in mails" :key="mail.id"> <div class="card" v-for="mail in mails" :key="mail.id">
<header @click="router.push('/mail/' + mail.id)"> <header class="flex between v-center">
{{ mail.title }} <span
class="title"
@click="router.push('/mail/' + mail.id)"
>{{ mail.title }}</span
>
<span class="state">{{
MAIL_STATES[mail.mailState] || "办理中"
}}</span>
</header> </header>
<div class="content">信件日期{{ mail.createTime }}</div> <div class="content">信件日期{{ mail.createTime }}</div>
<footer class="flex v-center between"> <footer class="flex v-center between">
<span>评价本次办理服务</span> <span>评价本次办理服务</span>
<div <div
style="padding: 16px" style="padding: 16px 0; width: 80px"
v-if="!mail.satisfaction"
class="flex end"
@click=" @click="
router.push( router.push(
`/mail/evaluate/${mail.id}?satisfaction=${mail.satisfaction}&title=${mail.title}&createTime=${mail.createTime}` `/mail/evaluate/${mail.id}?satisfaction=${mail.satisfaction}&title=${mail.title}&createTime=${mail.createTime}`
@ -23,13 +32,14 @@
> >
<van-icon <van-icon
name="arrow" name="arrow"
size="17" size="19"
v-if="!mail.satisfaction" v-if="!mail.satisfaction"
/> />
<span v-else>{{
satisfactions[mail.satisfaction]
}}</span>
</div> </div>
<div style="padding: 16px" v-else>
<span>{{ satisfactions[mail.satisfaction] }}</span>
</div>
</footer> </footer>
</div> </div>
</template> </template>
@ -45,9 +55,9 @@ const pageStore = PageStore();
const router = useRouter(); const router = useRouter();
const satisfactions = { const satisfactions = {
NOT_SATISFIED: "不满意", not_satisfied: "不满意",
BASICALLY_SATISFIED: "基本满意", basically_satisfied: "基本满意",
SATISFIED: "满意", satisfied: "满意",
}; };
const params = ref({ const params = ref({
size: 6, size: 6,
@ -62,8 +72,8 @@ function onLoad() {
listMail(params.value).then((data) => { listMail(params.value).then((data) => {
loading.value = false; loading.value = false;
if (!data.records.length) { if (!data.records.length) {
finished.value = true finished.value = true;
return return;
} }
mails.value = mails.value.concat(data.records); mails.value = mails.value.concat(data.records);
}); });
@ -74,26 +84,32 @@ onLoad();
watch(loading, (val) => { watch(loading, (val) => {
if (val) { if (val) {
params.value.current += 1; params.value.current += 1;
onLoad() onLoad();
} }
}); });
function refresh() { function refresh() {
mails.value = []; mails.value = [];
params.value.current = 1; params.value.current = 1;
finished.value = false finished.value = false;
onLoad() onLoad();
} }
watch(() => pageStore.myMailRefresh, (val) => { watch(
if (val) { () => pageStore.myMailRefresh,
refresh(); (val) => {
pageStore.myMailRefresh = false; if (val) {
refresh();
pageStore.myMailRefresh = false;
}
} }
}) );
const MAIL_STATES = {
processing: "办理中",
terminated: "已终止",
completion: "已办结",
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.card {
}
</style> </style>

1109
src/views/mail/components/Write.vue

File diff suppressed because it is too large Load Diff

95
vite.config.js

@ -1,55 +1,60 @@
import { defineConfig } from 'vite' import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue' import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite' import AutoImport from 'unplugin-auto-import/vite'
import svgLoader from 'vite-svg-loader' import svgLoader from 'vite-svg-loader'
import path from 'path' import path from 'path'
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default ({ mode }) => {
const env = loadEnv(mode, process.cwd());
plugins: [ return defineConfig({
vue(), define: {
svgLoader(), 'process.env': env
AutoImport({ },
imports: [ plugins: [
'vue' vue(),
] svgLoader(),
}), AutoImport({
], imports: [
resolve: { 'vue'
// https://cn.vitejs.dev/config/#resolve-alias ]
alias: { }),
// 设置路径 ],
'~': path.resolve(__dirname, './'), resolve: {
// 设置别名 // https://cn.vitejs.dev/config/#resolve-alias
'@': path.resolve(__dirname, './src/') alias: {
// 设置路径
'~': path.resolve(__dirname, './'),
// 设置别名
'@': path.resolve(__dirname, './src/')
},
// https://cn.vitejs.dev/config/#resolve-extensions
extensions: ['.js']
}, },
// https://cn.vitejs.dev/config/#resolve-extensions server: {
extensions: ['.js'] host: '0.0.0.0',
}, proxy: {
server: { '/api': {
host: '0.0.0.0', // https://mailbox.biutag.com/api
proxy: { // http://127.0.0.1:8080
'/api': { target: 'https://jzxx.biutag.com/api',
// https://mailbox.biutag.com/api changeOrigin: true,
// http://127.0.0.1:8080 rewrite: (p) => p.replace(/^\/api/, '')
target: 'https://mailbox.biutag.com/api', }
changeOrigin: true,
rewrite: (p) => p.replace(/^\/api/, '')
} }
} },
}, build: {
build: { rollupOptions: {
rollupOptions: { output: {
output: { entryFileNames: `assets/[name].${new Date().getTime()}.js`,
entryFileNames: `assets/[name].${new Date().getTime()}.js`, chunkFileNames: `assets/[name].${new Date().getTime()}.js`,
chunkFileNames: `assets/[name].${new Date().getTime()}.js`, assetFileNames: `assets/[name].${new Date().getTime()}.[ext]`,
assetFileNames: `assets/[name].${new Date().getTime()}.[ext]`, compact: true,
compact: true, manualChunks: {
manualChunks: { vue: ['vue']
vue: ['vue'] },
}, }
} }
} }
} })
}) }

Loading…
Cancel
Save