pref#hmc_生日祝福、短信优化

This commit is contained in:
Paidax
2025-12-31 10:12:55 +08:00
parent e2cf8b224b
commit 857819741f
36 changed files with 2924 additions and 172 deletions
File diff suppressed because it is too large Load Diff
@@ -109,14 +109,14 @@ layout("/mobile/platform.html"){
.right_content {
width: calc(100% - 150px);
padding-left: 20px;
padding-left: 10px;
padding-right: 10px;
position: relative;
height: 100px
}
.optionDesc {
/*margin-top: -16px;*/
/*margin-top: -10px;*/
display: -webkit-box;
/*-webkit-box-orient: vertical;*/
/*-webkit-line-clamp: 3;*/
@@ -125,7 +125,8 @@ layout("/mobile/platform.html"){
text-overflow: ellipsis;
font-size: 13px;
color: #868282;
height: 86%;
height: 80%;
margin-bottom: 10px;
overflow-y: auto;
}
@@ -139,7 +140,6 @@ layout("/mobile/platform.html"){
width: inherit;
margin-top: -5px;
position: absolute;
font-family: "";
top: 0;
right: 0;
transform: rotate(23deg);
@@ -224,7 +224,7 @@ layout("/mobile/platform.html"){
</div>
</van-cell>
<div class="selection" style="background: #FFF; margin-bottom: 80px"
<div class="selection" style="background: #FFF; margin-bottom: 100px"
v-for="(subject,sidx) in projectInfo.welfareProjectSubjects">
<div style="display: flex;width: 100%;padding: 10px 0;flex-wrap: wrap;height: 130px"
v-for="(option, oidx) in subject.options">
@@ -240,14 +240,15 @@ layout("/mobile/platform.html"){
</div>
<div class="right_content">
<div style="display: flex;justify-content: space-between;align-items: center;font-size: 14px">
<div style="width: 100%;display: flex;justify-content: space-between">
<div>
{{option.optionName}}
</div>
<div>
<span style="color: rgb(10 132 255 / 70%)">套餐详情</span>
</div>
<div style="display: flex; justify-content: space-between; align-items: center; font-size: 14px; width: 100%;">
<!-- 左侧:名称(允许收缩,不换行,溢出省略) -->
<div style="flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
{{ option.optionName }}
</div>
<!-- 右侧:“详情” 固定宽度,不参与伸缩 -->
<div style="flex-shrink: 0; margin-left: 8px;">
<span style="color: rgb(10 132 255 / 70%)" @click="openViewDesc(option.description)">详情</span>
</div>
</div>
<div class="optionDesc" @click="openViewDesc(option.description)">
@@ -259,9 +260,7 @@ layout("/mobile/platform.html"){
备注:{{option.simpleDesc}}
</div>
<div style="position: absolute;right: 10px;bottom: -30px;left: 0;display: flex;justify-content: space-between">
<div style="width: 70px;font-size: 13px;color: #918a8a;text-align: right;"
@click="openViewDesc(option.description)">
<div style="font-size: 13px;color: #918a8a;text-align: right;">
</div>
<van-stepper :default-value="0"
:min="0"
@@ -182,7 +182,7 @@ layout("/layouts/platform.html"){
</el-col>
</el-row>
<template v-if="formData.isManyUnit">
<template v-if="formData.isManyUnit && formData.specialStaffType != 'HMC_RELATION'">
<el-row :gutter="10">
<el-col :span=12>
<el-form-item label="所属单位(工会关系)" prop="unionRelationUnitId">
@@ -0,0 +1,152 @@
const COMMON_QUERY = {
template: /*language=HTML*/ `
<div class="search">
<div class="search-item">
<div class="search-item-label">姓名/工号</div>
<div class="search-item-option">
<el-input placeholder="请输入姓名或工号查询" clearable v-model="pageForm.searchKeyword"></el-input>
</div>
</div>
<div class="search-item">
<div class="search-item-label">所属工会</div>
<div class="search-item-option">
<el-select @change="flushUnits" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.unionname" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">所属单位</div>
<div class="search-item-option">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">在职状态</div>
<div class="search-item-option">
<dict-select v-model="pageForm.userStates" style="width: 100%" placeholder="在职状态" @change="doSearch"
code="USER_STATE" multiple></dict-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">人员类型</div>
<div class="search-item-option">
<dict-select v-model="pageForm.personTypes" style="width: 100%" placeholder="人员类型" @change="doSearch"
code="PERSON_TYPE" multiple></dict-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">人员性质</div>
<div class="search-item-option">
<dict-select v-model="pageForm.preparedBys" style="width: 100%" placeholder="人员性质" @change="doSearch"
code="PREPARED_BY" multiple></dict-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">生日日期</div>
<div class="search-item-option">
<el-date-picker :picker-options="pickerOptions" @change="changeDateRangeChange"
align="right" end-placeholder="结束日期" format="yyyy-MM-dd"
range-separator="-" start-placeholder="开始日期" style="width: 100%"
type="datetimerange" v-model="pageForm.changeDateRange"
value-format="yyyy-MM-dd"></el-date-picker>
</div>
</div>
<div class="search-query">
<el-button type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
</div>
</div>
`,
data() {
return {
pickerOptions: {
shortcuts: [
{
text: "未来一周",
onClick(picker) {
const end = new Date()
const start = new Date()
end.setTime(start.getTime() + 3600 * 1000 * 24 * 7)
picker.$emit("pick", [start, end])
}
},
{
text: "未来一个月",
onClick(picker) {
const end = new Date()
const start = new Date()
end.setTime(start.getTime() + 3600 * 1000 * 24 * 30)
picker.$emit("pick", [start, end])
}
},
{
text: "未来三个月",
onClick(picker) {
const end = new Date()
const start = new Date()
end.setTime(start.getTime() + 3600 * 1000 * 24 * 90)
picker.$emit("pick", [start, end])
}
}
]
},
unions: [],
units: [],
pageForm: {
searchKeyword: '',
unionId: '',
unitId: '',
userStates: [],
personTypes: [],
preparedBys: [],
changeDateRange: [],
}
}
},
methods: {
doSearch(){
const pageForm = clone(this.pageForm)
pageForm.userStates = JSON.stringify(this.pageForm.userStates)
pageForm.personTypes = JSON.stringify(this.pageForm.personTypes)
pageForm.preparedBys = JSON.stringify(this.pageForm.preparedBys)
this.$emit('search', pageForm)
},
changeDateRangeChange(val){
if (val && val.length > 0) {
this.pageForm.startDate = val[0]
this.pageForm.endDate = val[1]
} else {
this.pageForm.startDate = null
this.pageForm.endDate = null
}
this.doSearch()
},
async initData(){
if (this.$auth.hasRoleOr('sysadmin, SchoolUnionMemberAdmin, SchoolUnionAdmin')) {
this.unions = await getUnions(this.pageForm.unionId)
this.units = await getUnits()
} else {
const user = JSON.parse(window.sessionStorage.getItem('user'))
this.unions = await getUnions(user.union.id)
this.units = await getUnits(user.union.id)
}
},
async flushUnits(){
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.units = await getUnits(this.pageForm.unionId)
}
}
},
async created() {
this.initData()
}
}
@@ -0,0 +1,298 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<el-card shadow="never">
<common-query ref="commonQueryRef" @search="search"></common-query>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool :app="this" label="数据列表(默认展示近15天的数据,搜索会忽略年份)">
<template #func>
<el-button type="primary" size="small" @click="doExport">导出Excel</el-button>
<el-button type="primary" size="small" @click="openSendMsgByQuery">发送通知</el-button>
<el-button type="primary" size="small" @click="openPicSet">配置图片</el-button>
</template>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" ref="table"
row-key="id" style="width: 100%">
<el-table-column :index="indexMethod"
header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column :label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns">
</el-table-column>
<el-table-column fixed="right" label="操作" width="250px">
<template slot-scope="{row}">
<el-button @click="openView(row)" size="mini" type="primary">人员信息</el-button>
<el-button @click="openSendMsgByUser(row)" size="mini" type="primary">发送通知</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
<template #view>
<member-info ref="memberInfoRef"></member-info>
</template>
</guava>
<el-dialog
:close-on-click-modal="false"
:visible.sync="sendMsgByQueryDialogVisible"
title="请在下方填写需要发送的内容"
width="50%"
>
<el-form :model="sendMsgByQueryFormData" label-width="80px" ref="sendMsgByQueryForm">
<el-form-item
:rules="[{required: true, message: '请输入发送标题', trigger: ['blur', 'change']}]"
label="发送标题"
prop="title">
<el-input
:rows="6"
placeholder="请输入发送标题"
v-model="sendMsgByQueryFormData.title">
</el-input>
</el-form-item>
<el-form-item
:rules="[{required: true, message: '请选择发送内容', trigger: ['blur', 'change']}]"
label="发送内容"
prop="content">
<el-input
:rows="6"
placeholder="请输入内容"
type="textarea"
v-model="sendMsgByQueryFormData.content">
</el-input>
</el-form-item>
</el-form>
<span class="dialog-footer" slot="footer">
<el-button @click="sendMsgByQueryDialogVisible = false">取 消</el-button>
<el-button @click="sendMsgByQueryUsers" type="primary">确 定</el-button>
</span>
</el-dialog>
<!-- 根据行内数据发送消息 -->
<el-dialog
:close-on-click-modal="false"
:visible.sync="sendMsgByUserDialogVisible"
title="请在下方填写需要发送的内容"
width="50%"
>
<el-form :model="sendMsgByUserFormData" label-width="80px" ref="sendForm">
<el-form-item label="发送对象" prop="userInfo">
<el-input placeholder="请输入发送对象" readonly v-model="sendMsgByUserFormData.userInfo"></el-input>
</el-form-item>
<el-form-item
:rules="[{required: true, message: '请输入发送标题', trigger: ['blur', 'change']}]"
label="发送标题"
prop="title">
<el-input
placeholder="请输入发送标题"
v-model="sendMsgByUserFormData.title">
</el-input>
</el-form-item>
<el-form-item
:rules="[{required: true, message: '请选择发送内容', trigger: ['blur', 'change']}]"
label="发送内容"
prop="content">
<el-input
:rows="6"
placeholder="请输入内容"
type="textarea"
v-model="sendMsgByUserFormData.content">
</el-input>
</el-form-item>
</el-form>
<span class="dialog-footer" slot="footer">
<el-button @click="sendMsgByUserDialogVisible = false">取 消</el-button>
<el-button @click="sendMsgByUser" type="primary">确 定</el-button>
</span>
</el-dialog>
<el-dialog
:close-on-click-modal="false"
:visible.sync="dialogVisible"
title="生日贺卡图片设置"
width="50%"
>
<el-form :model="formData" label-width="80px" ref="formRef">
<el-form-item label="背景图片" prop="picUrl">
<image-Upload :file-size="5"
:file-type="['png','jpg']"
:height="100"
:limit="1"
:width="100"
ref="imageUpload"
v-model="formData.picUrl"></image-Upload>
</el-form-item>
<el-form-item label="贺卡图片" prop="birthdayUrl">
<image-Upload :file-size="5"
:file-type="['png','jpg']"
:height="100"
:limit="1"
:width="100"
ref="imageUpload"
v-model="formData.birthdayUrl"></image-Upload>
</el-form-item>
</el-form>
<span class="dialog-footer" slot="footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button @click="doSubmit" type="primary">确 定</el-button>
</span>
</el-dialog>
</div>
<script>
<!--#include("commonQuery.js"){}#-->
<!--#include("../../../member/common/memberInfo.js"){}#-->
new Vue({
el: '#app',
mixins: [initTableMixins],
data() {
return {
pageForm: {},
tableColumns: [
{ prop: "loginname", label: "工号", sortable: true },
{ prop: "username", label: "姓名", sortable: true },
{ prop: "sex", label: "性别", sortable: true },
{ prop: "mobile", label: "联系方式", sortable: true },
{ prop: "birthday", label: "出生年月", sortable: true },
{ prop: "daysUntilBirthday", label: "生日倒计时(天)", sortable: true },
{ prop: "userState", label: "在职状态", sortable: true, width: "100px" },
{ prop: "personType", label: "人员类型", sortable: true, width: "120px" },
{ prop: "preparedBy", label: "人员性质", sortable: true, width: "120px" },
{ prop: "unionname", label: "所属工会", sortable: true, width: "160px" },
{ prop: "unitname", label: "所属单位", sortable: true, width: "160px" }
],
// 根据查询条件推送消息相关
sendMsgByQueryDialogVisible: false,
sendMsgByQueryFormData: {},
// 根据行内发送消息相关
sendMsgByUserDialogVisible: false,
sendMsgByUserFormData: {},
// 图片配置
dialogVisible: false,
formData: {
picUrl: '',
birthdayUrl: ''
}
}
},
components: {
'common-query': COMMON_QUERY,
'member-info': MEMBER_INFO,
},
methods: {
async openPicSet() {
const resp = await $.post('/platform/staffManage/birthday/manage/getConfig')
if (resp.code === 0) {
this.formData = resp.data
}
this.dialogVisible = true
},
doSubmit() {
this.$confirm('确定要提交吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
const resp = await $.post('/platform/staffManage/birthday/manage/saveOrModifyConfig', this.formData)
if (resp.code === 0) {
this.$message.success('保存成功')
this.dialogVisible = false
} else {
this.$message.error(resp.msg)
}
})
},
openSendMsgByUser(row) {
this.sendMsgByUserFormData.userId = row.id
this.sendMsgByUserFormData.userInfo = row.username
this.sendMsgByUserDialogVisible = true
},
async sendMsgByUser() {
const valid = await this.$refs['sendForm'].validate()
if (!valid) return
const confirm = await this.$confirm('您确定要向' + this.sendMsgByUserFormData.userInfo + '数据发送信息吗?', '提示', {
confirmButtonText: '确定',
cancelButtonTest: '取消',
type: 'warning'
})
if (confirm === "confirm") {
const resp = await $.post('/platform/staffManage/birthday/manage/sendMsgByUser',
this.sendMsgByUserFormData
)
if (resp.code === 0) {
this.sendMsgByUserDialogVisible = false
this.$message.success(resp.msg)
} else {
this.$message.warning(resp.msg)
}
}
},
openSendMsgByQuery() {
this.sendMsgByQueryFormData = JSON.parse(JSON.stringify(this.pageForm))
this.sendMsgByQueryDialogVisible = true
},
async sendMsgByQueryUsers() {
const valid = await this.$refs['sendMsgByQueryForm'].validate()
if (!valid) return
const confirm = await this.$confirm('您确定根据查询条件发送信息吗?', '提示', {
confirmButtonText: '确定',
cancelButtonTest: '取消',
type: 'warning'
})
if (confirm === "confirm") {
const resp = await $.post('/platform/staffManage/birthday/manage/sendMsgByQueryUsers', this.sendMsgByQueryFormData)
if (resp.code === 0) {
this.sendMsgByQueryDialogVisible = false
this.$message.success(resp.msg)
} else {
this.$message.warning(resp.msg)
}
}
},
doExport() {
this.$downLoad("/platform/staffManage/birthday/manage/doExport", this.pageForm)
},
openView(row) {
this.$refs.guava.view()
this.$nextTick(() => {
this.$refs.memberInfoRef.onOpen(row.id)
})
},
search(pageForm){
this.pageForm = { ...this.pageForm, ...pageForm }
this.pageData()
},
},
async created() {
this.pageData()
},
})
</script>
<!--#
}
#-->
@@ -0,0 +1,72 @@
const COMMON_QUERY = {
template: /*language=HTML*/ `
<div class="search">
<div class="search-item">
<div class="search-item-label">姓名/工号</div>
<div class="search-item-option">
<el-input placeholder="请输入姓名或工号查询" clearable v-model="pageForm.searchKeyword"></el-input>
</div>
</div>
<div class="search-item">
<div class="search-item-label">所属工会</div>
<div class="search-item-option">
<el-select @change="flushUnits" @clear="flushUnits" clearable filterable
placeholder="请选择所属工会" style="width: 100%;" v-model="pageForm.unionId">
<el-option :key="item.id" :label="item.unionname" :value="item.id"
v-for="item in unions"></el-option>
</el-select>
</div>
</div>
<div class="search-item">
<div class="search-item-label">所属单位</div>
<div class="search-item-option">
<el-select clearable filterable placeholder="请选择所属单位" style="width: 100%"
v-model="pageForm.unitId">
<el-option :key="item.id" :label="item.name" :value="item.id"
v-for="item in units"></el-option>
</el-select>
</div>
</div>
<div class="search-query">
<el-button type="primary" icon="el-icon-search" @click="doSearch">搜索</el-button>
</div>
</div>
`,
data() {
return {
unions: [],
units: [],
pageForm: {
searchKeyword: '',
unionId: '',
unitId: '',
}
}
},
methods: {
doSearch(){
this.$emit('search', this.pageForm)
},
async initData(){
if (this.$auth.hasRoleOr('sysadmin, SchoolUnionMemberAdmin, SchoolUnionAdmin')) {
this.unions = await getUnions(this.pageForm.unionId)
this.units = await getUnits()
} else {
const user = JSON.parse(window.sessionStorage.getItem('user'))
this.unions = await getUnions(user.union.id)
this.units = await getUnits(user.union.id)
}
},
async flushUnits(){
this.$set(this.pageForm, "unitId", null)
this.units = []
if (this.pageForm.unionId) {
this.units = await getUnits(this.pageForm.unionId)
}
}
},
async created() {
this.initData()
}
}
@@ -0,0 +1,78 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app">
<guava ref="guava">
<el-card shadow="never">
<common-query ref="commonQuery" @search="search"></common-query>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool :app="this" label="数据列表">
<template #func>
<!-- <el-button type="primary" size="small" @click="doExport">导出Excel</el-button>-->
</template>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder" ref="table"
row-key="id" style="width: 100%">
<el-table-column :index="indexMethod"
header-align="center"
label="序号" type="index" width="80px"></el-table-column>
<el-table-column :label="column.label"
:prop="column.prop"
:sortable="column.sortable"
:width="column.width"
header-align="center"
min-width="100px"
show-overflow-tooltip
v-for="column in tableColumns">
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</guava>
</div>
<script>
<!--#include("commonQuery.js"){}#-->
new Vue({
el: '#app',
mixins: [initTableMixins],
data(){
return{
pageForm: {},
tableColumns: [
{ prop: "loginname", label: "工号", sortable: true },
{ prop: "username", label: "姓名", sortable: true },
{ prop: "unionName", label: "所属工会", sortable: true, width: "160px" },
{ prop: "unitName", label: "所属单位", sortable: true, width: "160px" },
{ prop: "msgTitle", label: "消息标题", sortable: true },
{ prop: "msgContent", label: "消息内容", sortable: true },
{ prop: "pushByName", label: "推送人", sortable: true },
{ prop: "pushTime", label: "推送时间", sortable: true },
{ prop: "pushType", label: "推送类型", sortable: true },
],
}
},
components: {
'common-query': COMMON_QUERY,
},
methods: {
doExport(){
},
search(pageForm){
this.pageForm = { ...this.pageForm, ...pageForm }
this.pageData()
},
},
created() {
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -316,6 +316,10 @@ layout("/layouts/platform.html"){
<el-button :disabled="!pageForm.projectId" type="primary" size="small"
@click="doExportWelfareBySearch">导出名单
</el-button>
<el-button :disabled="!pageForm.projectId" type="primary" size="small"
@click="sendMsgNoChoice">通知未选择人员
</el-button>
</template>
</table-tool>
@@ -717,6 +721,46 @@ layout("/layouts/platform.html"){
</span>
</el-dialog>
<el-dialog
:close-on-click-modal="false"
:visible.sync="sendMsgNoChoiceDialogVisible"
title="请在下方填写需要发送的内容"
width="50%"
>
<el-form :model="noChoiceFormData" label-width="80px" ref="noChoiceSendForm">
<el-form-item
:rules="[{required: true, message: '请输入发送标题', trigger: ['blur', 'change']}]"
label="发送标题"
prop="title">
<el-input
:rows="6"
placeholder="请输入发送标题"
v-model="noChoiceFormData.title">
</el-input>
</el-form-item>
<el-form-item
:rules="[{required: true, message: '请选择发送内容', trigger: ['blur', 'change']}]"
label="发送内容"
prop="content">
<el-input
:rows="6"
placeholder="请输入内容"
type="textarea"
v-model="noChoiceFormData.content">
</el-input>
</el-form-item>
</el-form>
<span class="dialog-footer" slot="footer">
<el-button @click="sendMsgNoChoiceDialogVisible = false">取 消</el-button>
<el-button @click="sendMsgToNotWelfareUsers" type="primary">确 定</el-button>
</span>
</el-dialog>
</div>
<script>
<!--#include("/platform/welfare/include/common.js"){}#-->
@@ -823,13 +867,48 @@ layout("/layouts/platform.html"){
loginname: '',
title: '',
content: ''
}
},
// 通知未选择相关
sendMsgNoChoiceDialogVisible: false,
noChoiceFormData: {},
}
},
components: {
'courier-number-info': httpVueLoader('/components/welfare/CourierNumberInfo.vue?v=' + new Date().getTime())
},
methods: {
sendMsgNoChoice(){
this.$set(this.formData, "sendTypes", [])
this.$set(this.formData, "url", `<a href="` + (APP_DOMAIN + '/mobile/welfare/list/receive?projectId=' + row.id) + `">点击参与</a>`)
this.$set(this.formData, "content", "温馨提示:请尽快完成福利套餐的选择,逾期未选择视为默认发放XXXX。")
this.$set(this.formData, "id", this.pageForm.projectId)
this.sendMsgNoChoiceDialogVisible = true
},
async sendMsgToNotWelfareUsers() {
const valid = await this.$refs['noChoiceSendForm'].validate()
if (!valid) return
const confirm = await this.$confirm('您确定要向未选福利的人员发送信息吗?', '提示', {
confirmButtonText: '确定',
cancelButtonTest: '取消',
type: 'warning'
})
if (confirm === "confirm") {
const resp = await $.post('/platform/welfare/project/mange/sendMsgToNotWelfareUsers', {
title: this.noChoiceFormData.title,
projectId: this.noChoiceFormData.id,
sendMsgValue: this.noChoiceFormData.content,
url: this.noChoiceFormData.url
})
if (resp.code === 0) {
this.sendMsgNoChoiceDialogVisible = false
this.$message.success(resp.msg)
} else {
this.$message.warning(resp.msg)
}
}
},
doExportWelfareBySearch(){
window.open(loc() + '/doExportWelfareBySearch?searchName=' + this.pageForm.searchName +
'&searchKeyWord=' + this.pageForm.searchKeyword +