Compare commits

...

5 Commits

Author SHA1 Message Date
laishajiang d148161d58 登录页面 2 years ago
laishajiang 29e0c4e7f7 登录页面 2 years ago
laishajiang 51b73e4616 登录页面 2 years ago
laishajiang d1f61e3d10 pc互联网前端 2 years ago
laishajiang 1d3b2abe88 pc互联网前端 2 years ago
  1. BIN
      public/imgs/FaultUpload.jpg
  2. BIN
      public/imgs/web_btn_delete.png
  3. 5
      src/layout/Index.vue
  4. 19
      src/router/index.js
  5. 11
      src/util/request.js
  6. 131
      src/util/validator copy.js
  7. 92
      src/views/Home.vue
  8. 182
      src/views/MailDetail.vue
  9. 3
      src/views/MailEvaluate.vue
  10. 45
      src/views/RealNameAuth.vue
  11. 162
      src/views/Write.vue
  12. 3
      src/views/components/CorporateLogin.vue
  13. 176
      src/views/components/MailDraft.vue
  14. 212
      src/views/components/MyMail.vue
  15. 19
      src/views/components/PersonLogin.vue
  16. 576
      src/views/components/WriteInfo.vue

BIN
public/imgs/FaultUpload.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
public/imgs/web_btn_delete.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 872 B

After

Width:  |  Height:  |  Size: 872 B

5
src/layout/Index.vue

@ -1,11 +1,14 @@
<template>
<div class="wrapper">
<div class="wrapper" style="overflow:hidden; ">
<el-scrollbar >
<header>
<img src="/imgs/bg_web.png" alt="" />
</header>
<main>
<router-view />
</main>
</el-scrollbar>
</div>
</template>
<script setup>

19
src/router/index.js

@ -3,9 +3,10 @@ import { createRouter, createWebHistory } from 'vue-router'
import Layout from '@/layout/Index.vue'
import Home from '@/views/Home.vue'
import Write from '@/views/Write.vue'
import MailEvaluate from '@/views/MailEvaluate.vue'
import MailDetail from '@/views/MailDetail.vue'
import NotFound from '@/views/error/404.vue'
import RealNameAuth from '@/views/RealNameAuth.vue'
const routes = [
{
path: '/layout',
@ -18,7 +19,19 @@ const routes = [
{
path: '/mail/write',
component: Write,
}
},
{
path: '/mail/evaluate',
component: MailEvaluate
},
{
path: '/mail/:id',
component: MailDetail
},
{
path: '/realName/auth',
component: RealNameAuth
},
]
},
{

11
src/util/request.js

@ -47,7 +47,16 @@ export function del(url) {
export function upload(data) {
return post('/file/upload/base64', data)
}
export function uploadfile(url,data) {
return request(url, {
method: 'POST',
body: JSON.stringify(data),
headers: {
"Content-Type": 'multipart/form-data',
"Authorization": getToken()
}
})
}
function request(url, options) {
return new Promise((resolve, reject) => {
fetch(`${basePath}${url}`, {

131
src/util/validator copy.js

@ -0,0 +1,131 @@
/**
* 验证身份证号码
* @param { String } code 身份证号码
*/
export function validatorIdCard(rule,code,callback) {
// 身份证号前两位代表区域
const city = {
11: '北京',
12: '天津',
13: '河北',
14: '山西',
15: '内蒙古',
21: '辽宁',
22: '吉林',
23: '黑龙江 ',
31: '上海',
32: '江苏',
33: '浙江',
34: '安徽',
35: '福建',
36: '江西',
37: '山东',
41: '河南',
42: '湖北 ',
43: '湖南',
44: '广东',
45: '广西',
46: '海南',
50: '重庆',
51: '四川',
52: '贵州',
53: '云南',
54: '西藏 ',
61: '陕西',
62: '甘肃',
63: '青海',
64: '宁夏',
65: '新疆',
71: '台湾',
81: '香港',
82: '澳门',
91: '国外 ',
};
const idCardReg = /^[1-9]\d{5}(19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i; // 身份证格式正则表达式
// 如果身份证不满足格式正则表达式
if (!code) {
callback(new Error('请输入身份证号码'));
}
if (!code.match(idCardReg)) {
callback(new Error('请输入正确的身份证号码'));
}
if (!city[code.substr(0, 2)]) {
// 区域数组中不包含需验证的身份证前两位
callback(new Error('请输入正确的身份证号码'));
}
if (code.length === 18) {
// 18位身份证需要验证最后一位校验位
code = code.split('');
// ∑(ai×Wi)(mod 11)
// 加权因子
const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
// 校验位
const parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2];
let sum = 0;
let ai = 0;
let wi = 0;
for (let i = 0; i < 17; i++) {
ai = parseInt(code[i]);
wi = factor[i];
sum += ai * wi; // 开始计算并相加
}
const last = parity[sum % 11]; // 求余
if (last.toString() !== code[17]) {
callback(new Error('请输入正确的身份证号码'));
}
}
return true
}
/**
* 校验手机号
* @param {*} phonenumber
* @returns
*/
export function validatorPhone(rule,phonenumber,callback) {
if (!phonenumber) {
callback(new Error('请输入手机号码'));
}
if (!/^1[3456789]\d{9}/.test(phonenumber)) {
callback(new Error('请输入手机号码'));
}
return true
}
/**
* 校验手机号
* @param {*} phonenumber
* @returns
*/
export function Phone(phonenumber) {
if (!phonenumber) {
return '请输入手机号码';
}
if (!/^1[3456789]\d{9}/.test(phonenumber)) {
return '请输入手机号码';
}
return true
}
/**
* 校验内容长度
* @param {*} content
* @returns
*/
export function validatorContent(rule,content,callback) {
if (!content) {
callback(new Error('请输入信件内容'));
}
if (content.length < 10) {
callback(new Error('信件内容不能少于 10 个字'));
}
if (content.length > 300) {
callback(new Error('信件内容不能多于 300 个字'));
}
return true
}

92
src/views/Home.vue

@ -1,26 +1,29 @@
<template>
<div class="flex gap-10 center mt-20">
<div class="flex gap-10 center mt-20" style="align:center;">
<a
class="flex v-center center gap-16"
@click="router.push('/mail/write')"
style="right: 13px;"
>
<div style="width: 48px">
<div>
<img src="/imgs/write.png" alt="" />
</div>
<span>我要写信</span>
</a>
<a
class="flex v-center center gap-16"
@click="router.push('/mail?active=my')"
@click="router.push('/mail/write?active=my')"
style="left: 13px;"
>
<div style="width: 48px">
<div>
<img src="/imgs/search.png" alt="" />
</div>
<span>回复查询</span>
</a>
</div>
<Loading :loading="loading" />
</template>
<script setup>
import { useRoute, useRouter } from "vue-router";
@ -34,42 +37,87 @@ const userStore = UserStore();
const loading = ref(false);
if (!getToken()) {
if (route.query.openid) {
//
authOpenid(route.query.openid).then((data) => {
authOpenid('oWL3NwzZ9LbOxRse4uiPisbzYTI4').then((data) => {
setToken(data.token);
userStore.user = data.user;
loading.value = false;
wxStore.initSign();
console.log(userStore.user)
// wxStore.initSign();
});
}
} else {
loading.value = false;
// if (!getToken()) {
// if (route.query.openid) {
// //
// authOpenid(route.query.openid).then((data) => {
// setToken(data.token);
// userStore.user = data.user;
// loading.value = false;
wxStore.initSign();
}
// wxStore.initSign();
// });
// }
// } else {
// loading.value = false;
// wxStore.initSign();
// }
</script>
<style lang="scss" scoped>
.wrapper {
background-color: #fff;
}
header {
img {
width: 100%;
width: 1199px;
height: 321px;
}
}
.mt-20{
margin-top: 3%;
}
.flex div{
width: 580px;
height: 219px;
}
.flex div img{
position: absolute;
width: 156px;
height: 156px;
left:5.4%;
top:14.4%;
}
span{
position: absolute;
left: 52%;
top: 39.9%;
width: 128px;
height: 45px;
font-family: PingFang-SC-Heavy;
font-size: 32px;
color: #0E5A98;
text-align: center;
font-weight: 800;
}
a {
width: 45.2%;
height: 84px;
text-decoration: none;
border: 1px solid var(--primary-color);
color: var(--primary-color);
display: block;
position: relative;
width: 580px;
height: 219px;
background: #F3FAFF;
border: 1px solid rgba(32,119,192,1);
font-weight: bold;
font-size: 18px;
&:hover {
cursor: pointer;
}
}
</style>

182
src/views/MailDetail.vue

@ -0,0 +1,182 @@
<template>
<div class="wrapper">
<div class="card_first">
<h2>基本信息</h2>
<div class="row flex">
<label>信件标题</label>
<span>{{ mail.title }}</span>
</div>
<div class="row flex">
<label>联系人姓名</label>
<span>{{ mail.contactName }}</span>
</div>
<div class="row flex">
<label>联系人电话</label>
<span>{{ mail.contactPhone }}</span>
</div>
<div class="row flex">
<label>证件号码</label>
<span>{{ mail.contactIdCard }}</span>
</div>
</div>
<div class="card_second">
<h2>信件内容</h2>
<div class="row flex" v-if="mail.caseNumber">
<label>案件编号</label>
<span>{{ mail.caseNumber }}</span>
</div>
<div class="row">
<label>案件内容</label>
<div class="textarea text-wrap">{{ mail.content }}</div>
</div>
<div class="row">
<label>附件</label>
<div class="attachments" v-if="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>
</div>
</div>
</div>
<Loading :loading="loading" />
</template>
<script setup>
import { useRoute } from "vue-router";
import { getMail } from "@/api/mail";
const props = defineProps(["message"]);
if (props.message) {
console.log(props.message,9999);
console.log("msg"+props.message)
getMail(props.message).then((data) => {
mail.value = data;
loading.value = false;
});
}
const route = useRoute();
const loading = ref(true);
const mail = ref({});
function onMounted(){
}
const showImgPreview = ref(false);
const imgFilepath = ref("");
function handleShowImgPreview(filepath) {
imgFilepath.value = filepath;
showImgPreview.value = true;
}
</script>
<style lang="scss" scoped>
.card_first {
width: 1200px;
height: 172.5px;
background: #FFFFFF;
box-shadow: inset 0px -1px 0px 0px rgba(227,227,227,1);
padding-bottom: var(--van-padding-md);
h2{
width: 48px;
height: 17px;
font-family: PingFang-SC-Regular;
font-size: 12px;
color: #333333;
font-weight: 400;
margin-bottom:15px ;
}
label{
width: 90px;
height: 20px;
font-family: PingFang-SC-Regular;
font-size: 14px;
color: #666666;
letter-spacing: 0;
font-weight: 400;
}
span{
width: 229px;
height: 20px;
font-family: PingFang-SC-Regular;
font-size: 14px;
color: #333333;
letter-spacing: 0;
font-weight: 400;
}
.row.flex{
margin-bottom:15px ;
}
}
.card_second{
width: 1200px;
height: 365px;
background: #FFFFFF;
box-shadow: inset 0px -1px 0px 0px rgba(227,227,227,1);
label{
width: 90px;
height: 20px;
font-family: PingFang-SC-Regular;
font-size: 14px;
color: #666666;
letter-spacing: 0;
font-weight: 400;
}
span{
width: 229px;
height: 20px;
font-family: PingFang-SC-Regular;
font-size: 14px;
color: #333333;
letter-spacing: 0;
font-weight: 400;
}
h2{
width: 48px;
height: 17px;
font-family: PingFang-SC-Regular;
font-size: 12px;
color: #333333;
font-weight: 400;
margin-top: 40px;
}
.row{
margin-top: 16px;
}
.row.flex{
margin-top: 16px;
}
.textarea.text-wrap{
margin-left: 14px;
margin-top: 16px;
width: 1134px;
height: 60px;
font-family: PingFangSC-Regular;
font-size: 14px;
color: #333333;
font-weight: 400;
}
}
img{
width:120px;
height: 120px;
}
::v-deep .el-tabs__item {
width: 400px;
height: 33px;
font-family: PingFang SC;
font-size: 24px;
color: #333333 100%;
text-align: center;
font-weight: 400;
margin-bottom: 1.2%;
}
</style>

3
src/views/MailEvaluate.vue

@ -0,0 +1,3 @@
<template>
<div></div>
</template>

45
src/views/RealNameAuth.vue

@ -0,0 +1,45 @@
<template>
<div class="LoginPageBackground">
<div class="LoginPage">
<p>正在登录到 长沙市统一认证平台</p>
<el-tabs stretch v-model="activeName" style="width: 600px; height: 400px; position: relative;top: 30px;">
<el-tab-pane label="个人登录" name="first"><PersonLogin/></el-tab-pane>
<el-tab-pane label="法人登录" name="second"><CorporateLogin/></el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import PersonLogin from './components/PersonLogin.vue';
import CorporateLogin from './components/CorporateLogin.vue';
const activeName = ref('first')
</script>
<style lang="scss" scoped>
.LoginPageBackground{
width: 1200px;
height: 617px;
background-color: #2281cfc4;
position: relative;
top: -17px;
}
p{
font-size: 25px;
font-weight: 600;
position: relative;
top:40px;
left: 120px;
}
.LoginPage{
width: 600px;
height: 555px;
background-color:white;
position: relative;
top: 60px;
left: 300px;
}
::v-deep .el-tabs__content{
height: 300px;
}
</style>

162
src/views/Write.vue

@ -1,78 +1,92 @@
<template>
<el-form :model="form" label-width="120px">
<el-form-item label="Activity name">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="Activity zone">
<el-select v-model="form.region" placeholder="please select your zone">
<el-option label="Zone one" value="shanghai" />
<el-option label="Zone two" value="beijing" />
</el-select>
</el-form-item>
<el-form-item label="Activity time">
<el-col :span="11">
<el-date-picker
v-model="form.date1"
type="date"
placeholder="Pick a date"
style="width: 100%"
/>
</el-col>
<el-col :span="2" class="text-center">
<span class="text-gray-500">-</span>
</el-col>
<el-col :span="11">
<el-time-picker
v-model="form.date2"
placeholder="Pick a time"
style="width: 100%"
/>
</el-col>
</el-form-item>
<el-form-item label="Instant delivery">
<el-switch v-model="form.delivery" />
</el-form-item>
<el-form-item label="Activity type">
<el-checkbox-group v-model="form.type">
<el-checkbox label="Online activities" name="type" />
<el-checkbox label="Promotion activities" name="type" />
<el-checkbox label="Offline activities" name="type" />
<el-checkbox label="Simple brand exposure" name="type" />
</el-checkbox-group>
</el-form-item>
<el-form-item label="Resources">
<el-radio-group v-model="form.resource">
<el-radio label="Sponsor" />
<el-radio label="Venue" />
</el-radio-group>
</el-form-item>
<el-form-item label="Activity form">
<el-input v-model="form.desc" type="textarea" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">Create</el-button>
<el-button>Cancel</el-button>
</el-form-item>
</el-form>
<el-tabs v-model="pageStore.mailTabActive" class="demo-tabs"
:stretch="false" style="margin-top: 1%; width: 1200px;" @tab-change="handleClickOfWrite">
<el-tab-pane label="我要写信" name="write" ref="cab1" style="min-height: 1100px;" ><WriteInfo @childWriter-msg="getChildWriteMsg" /></el-tab-pane>
<el-tab-pane label="我的信件" name="my" @tab-click="handleClick">
<MyMail v-if="chooseTab=='isList'" @child-msg="getChildMsg" />
<MailDetail :message="message" v-else/>
</el-tab-pane>
<el-tab-pane label="草稿箱" name="draft">
<MailDraft :message_draft="message_draft" @child-msg="getMailDraftChildMsg"/>
</el-tab-pane>
</el-tabs>
</template>
<script lang="ts" setup>
import { reactive } from 'vue'
// do not use same name with ref
const form = reactive({
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: '',
})
const onSubmit = () => {
console.log('submit!')
}
</script>
<script lang="ts" setup>
import { reactive } from 'vue'
import { ref } from 'vue'
import WriteInfo from './components/WriteInfo.vue';
import MyMail from './components/MyMail.vue';
import MailDraft from './components/MailDraft.vue';
import MailDetail from '../views/MailDetail.vue';
import type { TabsPaneContext } from 'element-plus'
import { useRoute } from "vue-router";
import PageStore from '../store/page';
const chooseTab = ref('isList');
const route = useRoute();
const pageStore = PageStore()
if(route.query.active){
pageStore.mailTabActive = route.query.active
}else{
pageStore.mailTabActive = "write"
}
const message = ref("1");
const message_draft = ref("1");
const activeName = ref('first')
const handleClick = (tab: TabsPaneContext, event: Event) => {
}
const handleClickOfWrite = (name) => {
console.log(chooseTab.value)
chooseTab.value = 'isList'
}
function getChildMsg(msg) {
console.log("这就是子组件传过来的msg" + msg)
chooseTab.value = 'isDetail'
message.value = msg
console.log("aaa"+message.value)
}
function getChildWriteMsg(msg) {
// console.log("msg" + msg)
activeName.value = msg
// console.log("aaa"+activeName.value)
}
function getMailDraftChildMsg(msg) {
activeName.value = "first"
console.log("这就是子组件传过来的msg" + msg)
message_draft.value = msg
console.log("message_draft"+message_draft.value)
}
</script>
<style lang="scss" scoped>
::v-deep .el-tabs__item {
width: 400px;
height: 33px;
font-family: PingFang SC;
font-size: 24px;
color: #333333 100%;
text-align: center;
font-weight: 400;
margin-bottom: 1.2%;
}
::v-deep .el-tabs__item .is-active {
color: #0E5A98 100%;
}
::v-deep .el-tabs__active-bar {
background-color: #0E5A98 100%;
}
</style>

3
src/views/components/CorporateLogin.vue

@ -0,0 +1,3 @@
<template>
</template>

176
src/views/components/MailDraft.vue

@ -0,0 +1,176 @@
<template>
<el-dialog
v-model="dialogVisible"
title="提示"
width="30%"
>
<span>确认删除该草稿吗</span>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="dialogChoose()">
确定
</el-button>
</span>
</template>
</el-dialog>
<el-scrollbar>
<div v-if="mails.length<=0" v-loading="loading">
<h2 style="position: relative; left: 570px;">无草稿</h2>
</div>
<div v-else v-loading="loading">
<div class="card" v-for="mail in mails" :key="mail.id" >
<header class="title" @click="goWraiteMail(mail.id)">
{{ mail.title }}
</header>
<div class="content">信件日期{{ mail.createTime }}</div>
<div class="deleteImg">
<img src="/imgs/web_btn_delete.png" alt="" @click="handleDel(mail.id)"/>
</div>
</div>
<el-pagination
background
layout="prev, pager, next"
:current-page="params.current"
:page-size="params.size"
:total="total"
@current-change="handlePageChange"/>
</div>
</el-scrollbar>
</template>
<script setup>
import { useRouter } from "vue-router";
import { listDraft, delDraft } from "@/api/mailDraft";
import PageStore from "@/store/page";
import { onMounted } from 'vue';
import { updateEvaluate } from "@/api/mail";
import UserStore from "@/store/user";
const loading = ref(true);
const pageStore = PageStore();
const route = useRoute();
const router = useRouter();
const total = ref(0)
const params = ref({
size: 6,
current: 1,
});
const mails = ref([]);
const mailId = ref([]);
const dialogVisible = ref(false)
function handlePageChange(currentPage) {
params.value.current = currentPage
getListDraft()
//
}
function getListDraft(){
listDraft(params.value).then((data) => {
loading.value = false;
total.value = data.total;
params.value.size = data.size
mails.value = data.records;
});
}
onMounted(() => {
getListDraft()
})
function handleDel(id) {
dialogVisible.value = true;
mailId.val = id
}
function dialogChoose(){
loading.value = true;
delDraft(mailId.val).then(() => {
loading.value = false;
mails.value.splice(mails.value.findIndex((item) => item.id === mailId.val), 1)
ElMessage({
message: '删除成功',
type: 'success',
})
});
dialogVisible.value = false
}
function goWraiteMail(id) {
pageStore.mailDraftId = id;
pageStore.mailTabActive = "write";
console.log("mailid"+pageStore.mailDraftId)
}
function refresh() {
mails.value = [];
params.value.current = 1;
finished.value = false
// onLoad()
}
watch(() => pageStore.myMailDraftRefresh, (val) => {
if (val) {
getListDraft()
pageStore.myMailDraftRefresh = false;
console.log("pageStore.myMailDraftRefreshLater"+pageStore.myMailDraftRefresh)
}
})
</script>
<style lang="scss" scoped>
.title{
width: 500px;
height: 30px;
font-family: PingFang-SC-Bold;
font-size: 17px;
color: #333333;
letter-spacing: 0;
font-weight: 700;
cursor: pointer;
}
.content{
position: relative;
top: -5px;
width: 300px;
height: 17px;
font-family: PingFang-SC-Regular;
font-size: 12px;
color: #666666;
letter-spacing: 0;
font-weight: 400;
}
::v-deep footer{
position: relative; top: 8px;
span{
width: 150px;
height: 30px;
font-family: PingFang-SC-Regular;
font-size: 14px;
color: #333333;
letter-spacing: 0;
font-weight: 400;
}
}
.card{
margin-left: 10px;
padding-bottom: 0px;
.deleteImg{
width: 33px;
height: 33px;
position: relative;
top:-80px;
left: 1100px;
cursor: pointer;
}
img{
width: 33px;
height: 33px;
opacity: 1;
}
}
.el-pagination{
position: relative;
left: 580px;
}
</style>

212
src/views/components/MyMail.vue

@ -0,0 +1,212 @@
<template >
<div v-if="mails.length<=0" v-loading="loading">
<h2 style="position: relative; left: 570px;">暂无信件</h2>
</div>
<div v-else v-loading="loading">
<el-scrollbar>
<div class="card" v-for=" (mail,index) in mails" :key="mail.id" >
<header class="title" @click="gotoMailDetail(mail.id)">
{{ mail.title }}
</header>
<div class="content">信件日期{{ mail.createTime }}</div>
<footer class="flex v-center between" >
<span style="position: relative;left: 2px;" >评价本次办理服务</span>
<div class="satisfaction_style" ref="myref" v-if="!mail.satisfaction" style="position: relative; left: -550px; padding-left: 10%;">
<el-radio-group v-model="mailDataList[index]" @change="satischange()">
<el-radio-button label="NOT_SATISFIED" ref="satis">不满意</el-radio-button>
<el-radio-button label="BASICALLY_SATISFIED">基本满意</el-radio-button>
<el-radio-button label="SATISFIED" >满意</el-radio-button>
</el-radio-group>
<el-button style="position: relative; top: 4px; left: 50px; " @click="sumbit(mailDataList[index],mail.id,index)">提交</el-button>
</div>
<div v-else class="satisfaction_style" style="position: relative; left: -950px;top: -6px;">
{{satisfactions[mail.satisfaction]}}
</div>
</footer>
</div>
</el-scrollbar>
<el-pagination
background
layout="prev, pager, next"
:current-page="params.current"
:page-size="params.size"
:total="total"
@current-change="handlePageChange"/>
</div>
</template>
<script setup>
const loading = ref(true);
import { useRouter } from "vue-router";
import { listMail } from "@/api/mail";
import PageStore from "@/store/page";
import { onMounted } from 'vue';
import { updateEvaluate } from "@/api/mail";
import UserStore from "@/store/user";
const pageStore = PageStore();
const route = useRoute();
const router = useRouter();
const mailDataList = ref([])
const myref = ref([])
const satisfactions = {
NOT_SATISFIED: "不满意",
BASICALLY_SATISFIED: "基本满意",
SATISFIED: "满意",
};
const satis = ref();
function satischange(){
console.log("myref.value"+myref)
console.log(satis)
}
const total = ref(0)
const params = ref({
size: 10,
current: 1,
});
function handlePageChange(currentPage) {
params.value.current = currentPage
getListMail()
//
}
const mails = ref([]);
const const_satisfaction = '';
const mailData = [];
function getListMail(){
listMail(params.value).then((data) => {
loading.value = false;
total.value = data.total;
params.value.size = data.size
// params.value.current = data.current
mails.value = data.records;
// const_satisfaction = mails.value.satisfaction;
// mailDataList.value = mails.value.satisfaction
// console.log(mailDataList)
});
}
onMounted(() => {
getListMail()
})
// const mailId = ref();
const centerDialogVisible=ref(false)
const emit = defineEmits(['child-msg'])
const satisfaction = ref(route.query.satisfaction || "SATISFIED");
function sumbit(satisfaction,id,index) {
if(satisfaction == null){
ElMessage({
message: '请选择评价',
type: 'warning',
})
return;
}
ElMessageBox.confirm(
'确定提交评价吗?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
updateEvaluate({
mailId: id,
satisfaction: satisfaction
}).then(data => {
mails.value[index].satisfaction = satisfaction
loading.value = false;
ElMessage({
message: '提交成功',
type: 'success',
})
})
})
.catch(() => {
loading.value = false,
ElMessage({
type: 'info',
message: '取消提交',
})
})
}
function gotoMailDetail(id){
emit('child-msg', id)
}
watch(() => pageStore.myMailRefresh, (val) => {
if (val) {
getListMail()
pageStore.myMailRefresh = false;
}
})
</script>
<style lang="scss" scoped>
.title{
width: 500px;
height: 30px;
font-family: PingFang-SC-Bold;
font-size: 17px;
color: #333333;
letter-spacing: 0;
font-weight: 700;
cursor: pointer;
}
.content{
position: relative;
top: -5px;
width: 300px;
height: 17px;
font-family: PingFang-SC-Regular;
font-size: 12px;
color: #666666;
letter-spacing: 0;
font-weight: 400;
}
::v-deep footer{
position: relative; top: 8px;
span{
width: 150px;
height: 30px;
font-family: PingFang-SC-Regular;
font-size: 14px;
color: #333333;
letter-spacing: 0;
font-weight: 400;
}
.el-button{
width: 45px;
height: 24px;
background: #0E5A98;
border-radius: 2px;
span{
width: 24px;
height: 17px;
font-family: PingFang-SC-Regular;
font-size: 12px;
color: #FFFFFF;
letter-spacing: 0;
text-align: right;
font-weight: 400;
}
}
}
.satisfaction_style{
position: relative;
left: -550px;
padding-left: 10%;
top: -8px;
}
.card{
margin-left: 10px;
padding-bottom: 30px;
}
.el-pagination{
position: relative;
left: 580px;
}
</style>

19
src/views/components/PersonLogin.vue

@ -0,0 +1,19 @@
<template>
<div>
<img style="height: 200px;width: 200px;position: relative;left: 200px;top: 20px;" src="/public/logo.png">
</div>
<p>请使用本人<span style="font-weight: bold;"> 微信 </span>扫描上方小程序登录注册</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;如没有账号系统将自动注册新账号</p>
</template>
<style lang="scss" scoped>
p{
// font-size: 25px;
// font-weight: 600;
position: relative;
top:30px;
left: 170px;
}
</style>

576
src/views/components/WriteInfo.vue

@ -0,0 +1,576 @@
<template>
<!-- <el-scrollbar > -->
<span>联系人信息</span>
<el-form
:model="mail"
:rules="rules"
label-width="120px"
style="margin-top: 0.9%;"
label-position="left"
ref="formRef"
v-loading="loading">
<el-form-item label="联系人姓名" :required="true" prop="contactName" >
<el-input v-model="mail.contactName" placeholder="请输入姓名" readonly/>
</el-form-item>
<el-form-item label="称呼" prop="contactSex" style="top:-25px" >
<el-radio-group v-model="mail.contactSex" >
<el-radio label="M">先生</el-radio>
<el-radio label="F">女士</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="证件号码" prop="contactIdCard" type="text" style="top:-25px" >
<el-input v-model="mail.contactIdCard" placeholder="请输入证件号码" readonly="true"/>
</el-form-item>
<el-form-item label="联系电话" prop="contactPhone" style="top:-25px">
<el-input v-model="mail.contactPhone" placeholder="请输入联系电话" readonly="true"/>
<div
class="releative"
style="width: 77px; height: 24px">
<el-button
size="small"
type="primary"
@click="smsSendCode"
:disabled="sendBtnDisabled"
class="send-btn"
>{{
sendBtnDisabled
? `${time}秒后重发`
: "发送验证码"
}}</el-button>
</div>
</el-form-item>
<el-form-item label="验证码" prop="code" style="top:-25px" >
<el-input v-model="mail.code" placeholder="请输入验证码" oninput="value=value.replace(/[^\d.]/g,'')"/>
</el-form-item>
<span style="width: 48px;
height: 17px;
font-family: PingFang-SC-Regular;
font-size: 12px;
color: #666666;
font-weight: 400;
position: relative;
top: -8px;
right: 9px;">信件内容</span>
<el-form-item label="案件编号" prop="caseNumber" >
<el-input v-model="mail.caseNumber" placeholder="如有具体案件编号请输入案件编号"/>
</el-form-item>
<el-form-item label="被投诉/涉及单位" >
<el-select
v-model="mail.involvedDeptName"
placeholder="请选择单位"
@change="selectMediaId"
ref="mySelected"
>
<el-option v-for="item in depts"
:key="item.value"
:label="item.text"
:value="item.text"
ref="select" />
</el-select>
</el-form-item>
<el-form-item label="信件内容" prop="content" class="content_item">
<el-input v-model="mail.content" @input="timeEffectInput" resize="none" :rows="3" type="textarea" class="content" placeholder="请您尽量完整的描述您的信件内容,如发生事件、涉及单位、涉及对象姓名、警号以及具体事项" />
<span ref="contentSpan" style="position: absolute; right: 85px; top: 120px;">{{ mail.content ? mail.content.length : 0 }}/300</span>
</el-form-item>
<div style="position: relative; top: 100px;">
<span>附件</span>
<el-upload
v-model:file-list="mail.attachments"
action="/api/file/upload"
:http-request="uploadAction"
:headers="headers"
list-type="picture-card"
:limit="5"
:show-file-list="true"
:auto-upload="true"
multiple
:on-success="handleSuccess"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
>
<el-image
style="width: 89px; height: 89px "
:src="imgurl">
</el-image>
<el-icon><Plus /></el-icon>
</el-upload>
<span class="uploadSign">最多只能上传9张图片支持格式为pngjpggifsvg</span>
<el-dialog v-model="previewVisible" title="图片预览">
<img w-full :src="dialogImageUrl" alt="Preview Image" />
</el-dialog>
<el-form-item class="commit">
<el-button class="button1" @click="handleSaveDraft">存稿</el-button>
<el-button class="button2" @click="handleSave">提交</el-button>
</el-form-item>
</div>
</el-form>
</template>
<script setup>
import { reactive } from 'vue'
import { ref } from 'vue'
import { validatorIdCard, validatorPhone ,validatorContent,Phone} from "@/util/validator copy";
import { getToken } from "@/util/cookie";
import UserStore from "@/store/user";
import PageStore from "@/store/page";
import { addMail } from "@/api/mail";
import { depts } from "@/store/dept";
import { send } from "@/api/sms";
import { saveDraft, getDraft } from "@/api/mailDraft";
const userStore = UserStore();
const pageStore = PageStore();
const mySelected = ref();
const imgurl = ref();
const loading = ref(false);
imgurl.value = "/imgs/FaultUpload.jpg"
const rules= {
contactName: [ { type: 'string',required: true,message: "", trigger: 'blur'}, {max: 30,message: "名称长度不能超过30位" }],
contactPhone: [{ required: true, validator: validatorPhone, trigger: "blur" },
],
contactIdCard: [{ required: true, validator: validatorIdCard, trigger: "blur" },
],
code:[{ required: true, message: "请输入验证码", trigger: "blur" },
],
content:[{ required: true, validator: validatorContent, trigger: "blur" },
],
}
const headers = reactive({"Authorization": getToken()});
const previewVisible = ref(false);
const dialogImageUrl = ref('');
const select = ref('');
const mail = ref({
contactName: '',
contactIdCard: '',
contactPhone: '',
contactSex: '',
smsRequestId: '',
content: '',
code:'',
involvedDeptName:'',
attachments:''
})
const mailData = ref({
contactName: '',
contactIdCard: '',
contactPhone: '',
contactSex: '',
smsRequestId: '',
content: '',
code:'',
involvedDeptId:'',
involvedDeptName:'',
attachments:[]
})
//
const handlePictureCardPreview = (filepath) => {
console.log(filepath)
dialogImageUrl.value = filepath.url;
previewVisible.value = true;
};
initMail();
function initMail() {
mail.value = {
contactName: '蒋礼',
contactIdCard: '421083200202250451',
contactPhone: '17365710386',
contactSex: 'M',
content: "",
attachments: [],
};
}
const list = ref([])
watch(
() => pageStore.mailTabActive,
() => {
if (pageStore.mailDraftId) {
getDraft(pageStore.mailDraftId).then((data) => {
mail.value = data;
mailData.value.attachments = JSON.parse(data.attachments);
console.log( mailData.value.attachments.filepath)
list.value = []
for(const i of mailData.value.attachments){
let obj = new Object();
console.log(i.filepath)
obj.url = "/api/file/stream/"+i.filepath;
list.value.push(obj);
}
// mailData.value.attachments = list.value;
mail.value.attachments = list.value;
});
pageStore.mailDraftId = "";
}
}
);
const filepath = ref();
const handleSuccess = (obj,response,file) =>{
console.log(response.response.data.filepath);
//
filepath.value = response.response.data.filepath;
//push
mailData.value.attachments.push({filepath: filepath.value})
console.log("response.response"+response.response)
console.log("mailData.value.attachments"+mailData.value.attachments)
}
//
const handleRemove = (file, fileList) => {
// console.log('handleRemove', handleRemove);
console.log('file', file);
var index = mailData.value.attachments.findIndex(
temp => {
if(file.name == temp.file){
return true
}
}
);
mailData.value.attachments.splice(index,1)
console.log('fileList', fileList);
};
const emit = defineEmits(['childWriter-msg'])
const handleSaveDraft = () => {
formRef.value.validate().then(() => {
mailData.value.code = mail.value.code;
mailData.value.contactIdCard = mail.value.contactIdCard;
mailData.value.contactName = mail.value.contactName;
mailData.value.content = mail.value.content;
mailData.value.contactPhone = mail.value.contactPhone;
mailData.value.smsRequestId = mail.value.smsRequestId;
mailData.value.contactSex = mail.value.contactSex;
// mailData.value.attachments = mail.value.attachments;
loading.value = true;
ElMessageBox.confirm(
'确定提交草稿内容吗?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
saveDraft(mailData.value).then((data) => {
loading.value = false;
mail.value.id = data.id;
initMail();
// 稿
pageStore.mailTabActive = "draft"
pageStore.myMailDraftRefresh = true
});
ElMessage({
type: 'success',
message: '提交成功',
})
})
.catch(() => {
loading.value = false,
ElMessage({
type: 'info',
message: '取消提交',
})
})
});
};
const handleSave = () => {
formRef.value.validate().then(() => {
mailData.value.code = mail.value.code;
mailData.value.contactIdCard = mail.value.contactIdCard;
mailData.value.contactName = mail.value.contactName;
mailData.value.content = mail.value.content;
mailData.value.contactPhone = mail.value.contactPhone;
mailData.value.smsRequestId = mail.value.smsRequestId;
mailData.value.contactSex = mail.value.contactSex;
loading.value = true;
ElMessageBox.confirm(
'确定提交信件吗?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
addMail(mailData.value)
.then(() => {
loading.value = false;
// showSuccessToast("");
//
pageStore.mailTabActive = "my";
//
pageStore.myMailRefresh = true
//
userStore.user.phone = mail.value.phone;
initMail();
setTimeout(() => {
emit('childWriter-msg', "my")
}, 300)
})
.catch(() => {
loading.value = false;
});
ElMessage({
type: 'success',
message: '提交成功',
})
})
.catch(() => {
loading.value = false;
ElMessage({
type: 'info',
message: '取消提交',
})
})
});
};
function selectMediaId(depart){
console.log(mySelected.value, 'select值')
for (const i of depts) {
if(i.text == depart){
mailData.value.involvedDeptId=i.value;
mailData.value.involvedDeptName=i.text;
}
}
// console.log(mailData.value.involved_dept_id, 'select')
// console.log(depart, 'ID')
}
const formRef = ref();
const sendBtnDisabled = ref(false);
let time = ref(30);
function smsSendCode() {
formRef.value.validate(Phone).then(() => {
sendBtnDisabled.value = true;
//
send(mail.value.contactPhone).then((data) => {
mail.value.smsRequestId = data.requestId;
});
let timer = setInterval(() => {
time.value -= 1;
if (time.value <= 0) {
sendBtnDisabled.value = false;
clearInterval(timer);
time.value = 30;
}
}, 1000);
});
}
const contentSpan = ref();
function timeEffectInput() {
console.log(mail.value)
// contentData = mail.value
const length = mail.value.content.length //
if (length > 300) { // 200
//
contentSpan.style = 'color:red'
// 0-200
mail.value.content = mail.value.content.substr(0, 300)
} else {
contentSpan.style = 'color:#909399'
}
}
</script>
<style lang="scss" scoped>
.wrapper {
background-color: #fff;
}
.commit{
position:absolute;
top: 300px;
}
span{
width: 60px;
height: 17px;
font-family: PingFang-SC-Regular;
font-size: 12px;
color: #666666;
font-weight: 400;
margin-left: 0.8%;
}
.content{
width: 1112px;
resize:none;
height: 64px;
font-family: PingFangSC-Regular;
font-size: 14px;
color: #CCCCCC;
font-weight: 400;
position: relative;
left: -100px;
top:50px;
}
.releative{
position: absolute;
left: 90%;
top: 3.9%;
.el-button{
width: 77px;
height: 24px;
background: #0E5A98;
border-radius: 2px;
span{
width: 60px;
height: 17px;
font-family: PingFang-SC-Regular;
font-size: 12px;
color: #FFFFFF;
letter-spacing: 0;
text-align: right;
font-weight: 400;
}
}
}
// ::v-deep .el-image__inner{
// background-size:100% 100%;
// }
::v-deep .content_item {
.el-form-item__error{
top: 30px;
}
}
::v-deep .el-form-item__label {
margin-top: 1.1%;
margin-bottom: 1.1%;
width: 70px;
height: 20px;
font-family: PingFang-SC-Regular;
font-size: 14px;
color: #333333;
letter-spacing: 0;
line-height: 20px;
font-weight: 400;
}
.el-form-item{
position: relative;
top: -10px;
}
.el-input{
margin-top: 1.1%;
margin-bottom: 1.1%;
width: 229px;
height: 20px;
font-family: PingFang-SC-Regular;
font-size: 14px;
color: #999999;
letter-spacing: 0;
font-weight: 400;
}
.el-radio__label{
width: 28px;
height: 20px;
font-family: PingFang-SC-Regular;
font-size: 14px;
color: #999999;
letter-spacing: 0;
font-weight: 400;
}
::v-deep .el-upload--picture-card{
width: 150px;
height: 150px;
border:2px dashed white
}
// ::v-deep .el-icon::before {
// content: '';
// position: absolute;
// width: 31.25px;
// border-top: 4.16px solid;
// color: cornflowerblue;
// }
// ::v-deep .el-icon::after {
// content: '';
// position: absolute;
// height: 31.25px;
// border-left: 4.16px solid;
// color: cornflowerblue;
// }
::v-deep .el-select__suffix{
visibility:hidden;
}
.uploadSign{
position: relative;
top: 5px;
width: 295px;
height: 17px;
font-family: PingFang-SC-Regular;
font-size: 12px;
color: #333333;
letter-spacing: 0;
line-height: 17px;
font-weight: 400;
}
.commit{
top: 180%;
position: absolute;
left: 20%;
}
::v-deep .button1{
position: relative;
left: -50px;
width: 266px;
height: 44px;
background: #F3FAFF;
border: 0.5px solid rgba(32,119,192,1);
border-radius: 2px;
span{
width: 34px;
height: 24px;
font-family: PingFang-SC-Regular;
font-size: 17px;
color: #0E5A98;
text-align: left;
font-weight: 400;
}
}
::v-deep .button2{
width: 266px;
height: 44px;
background: #0E5A98;
border-radius: 2px;
span{
width: 34px;
height: 24px;
font-family: PingFang-SC-Regular;
font-size: 17px;
color: #FFFFFF;
text-align: left;
font-weight: 400;
}
}
</style>
Loading…
Cancel
Save