10 changed files with 822 additions and 64 deletions
-
31src/pages/OperationCenter/OperationSales/AdsMgm/index.scss
-
12src/pages/OperationCenter/OperationSales/AdsMgm/loadable.jsx
-
4src/pages/OperationCenter/OperationSales/AppPushMgm/index.scss
-
5src/pages/OperationCenter/OperationSales/AppPushMgm/loadable.jsx
-
41src/pages/OperationCenter/OperationSales/InformationMgm/index.scss
-
137src/pages/OperationCenter/OperationSales/InformationMgm/loadable.jsx
-
263src/pages/OperationCenter/OperationSales/ShortMessageMgm/index.scss
-
363src/pages/OperationCenter/OperationSales/ShortMessageMgm/loadable.jsx
-
2src/services/OperationCenter/OperationMarket/index.js
-
12src/services/OperationCenter/OperationMarket/shortMessage.js
@ -1,5 +1,260 @@ |
|||
@import "@/assets/css/mixin.scss"; |
|||
$color-container-bg : var(--color-container-bg); |
|||
$color-user-list-bg : var(--color-user-list-bg); |
|||
$color-text : var(--color-text); |
|||
$color-primary : var(--color-primary); |
|||
|
|||
.short-message-mgm { |
|||
width: 100%; |
|||
height: 100%; |
|||
overflow-y: auto; |
|||
@include scrollBar(#8bb3e3, #3471c4); |
|||
|
|||
.hidden { |
|||
display: none !important; |
|||
} |
|||
|
|||
.mgm-wraper { |
|||
display: flex; |
|||
width: 100%; |
|||
height: 100%; |
|||
padding-top: 10px; |
|||
} |
|||
|
|||
.full-group { |
|||
width: 100%; |
|||
padding: 15px 15px 0; |
|||
border-radius: 6px; |
|||
background: var(--color-user-list-bg); |
|||
box-shadow: 0px 3px 8px 0px rgb(0 0 0 / 8%); |
|||
} |
|||
|
|||
.search-group { |
|||
display: block; |
|||
width: 375px; |
|||
padding: 10px 10px 20px 20px; |
|||
|
|||
.title { |
|||
width: 100%; |
|||
font-size: 16px; |
|||
font-family: Microsoft YaHei, Microsoft YaHei-Bold; |
|||
font-weight: 700; |
|||
text-align: left; |
|||
color: var(--color-text); |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.ant-select-selector, |
|||
.ant-picker, |
|||
.ant-input { |
|||
background-color: var(--color-search-list-item-bg) !important; |
|||
box-shadow: none !important; |
|||
color: var(--color-search-list-item-value); |
|||
border-color: var(--color-search-list-item-bd) !important; |
|||
} |
|||
|
|||
.form-box { |
|||
width: 100%; |
|||
display: flex; |
|||
align-items: center; |
|||
margin-bottom: 20px; |
|||
|
|||
.form-txt { |
|||
color: var(--color-search-list-item-text); |
|||
flex: 0 0 25%; |
|||
max-width: 25%; |
|||
text-align: right; |
|||
padding-right: 6px; |
|||
} |
|||
|
|||
|
|||
.form-con { |
|||
flex: 1; |
|||
width: 220px; |
|||
} |
|||
|
|||
.form-long { |
|||
flex: 1; |
|||
min-width: 220px; |
|||
} |
|||
} |
|||
|
|||
.form-btn { |
|||
display: flex; |
|||
flex-flow: row nowrap; |
|||
justify-content: space-between; |
|||
margin: 40px 10px 10px; |
|||
padding: 0 3px; |
|||
|
|||
.ant-btn+.ant-btn { |
|||
margin-left: 10px; |
|||
} |
|||
|
|||
.ant-btn span { |
|||
font-size: 16px; |
|||
font-family: Microsoft YaHei, Microsoft YaHei-Regular; |
|||
font-weight: 400; |
|||
text-align: center; |
|||
color: #ffffff; |
|||
} |
|||
|
|||
.reset { |
|||
width: 90px; |
|||
height: 36px; |
|||
border-radius: 4px; |
|||
background: var(--button-default-bg); |
|||
} |
|||
|
|||
.submit { |
|||
width: calc(100% - 100px); |
|||
height: 36px; |
|||
border-radius: 4px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.row-operate { |
|||
display: flex; |
|||
justify-content: flex-end; |
|||
} |
|||
|
|||
.ant-btn+.ant-btn { |
|||
margin-left: 10px; |
|||
} |
|||
|
|||
.green { |
|||
background-color: #67c23a; |
|||
border-color: #67c23a; |
|||
} |
|||
|
|||
.result-group { |
|||
width: calc(100% - 375px); |
|||
padding-bottom: 15px; |
|||
padding: 20px; |
|||
background: var(--color-user-list-bg); |
|||
border-top-left-radius: 20px; |
|||
box-shadow: 0px 3px 8px 0px rgba(0, 0, 0, 0.08); |
|||
|
|||
|
|||
.row-head { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
margin-bottom: 12px; |
|||
|
|||
.number-wrapper { |
|||
display: inline-flex; |
|||
align-items: center; |
|||
font-size: 14px; |
|||
|
|||
.letter { |
|||
color: var(--color-text); |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.total-number { |
|||
color: var(--color-primary); |
|||
font-weight: bold; |
|||
margin: 0 4px; |
|||
font-size: 14px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.cc-result-flow { |
|||
width: 100%; |
|||
height: calc(100% - 34px - 13px); |
|||
|
|||
.yisa-table { |
|||
width: 100%; |
|||
height: calc(100% - 32px - 15px); |
|||
overflow-y: auto !important; |
|||
@include scrollBar(#8bb3e3, #3471c4); |
|||
|
|||
.ant-table-thead { |
|||
th { |
|||
background: var(--color-table-header-bg) !important; |
|||
} |
|||
} |
|||
|
|||
.ant-table-tbody { |
|||
td { |
|||
background: var(--color-table-body-bg) !important; |
|||
border-bottom-color: var(--color-table-border-bottom-color); |
|||
} |
|||
|
|||
tr:nth-child(even) { |
|||
td { |
|||
background: var(--color-table-body-bg-nth-child-even) !important; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.row-pic { |
|||
width: 100%; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: flex-start; |
|||
|
|||
.ant-image { |
|||
margin-right: 3px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
.modal-short { |
|||
|
|||
.ant-select-selector, |
|||
.ant-picker, |
|||
.ant-input { |
|||
background-color: var(--color-search-list-item-bg) !important; |
|||
box-shadow: none !important; |
|||
color: var(--color-search-list-item-value); |
|||
border-color: var(--color-search-list-item-bd) !important; |
|||
} |
|||
|
|||
.row-box { |
|||
width: 100%; |
|||
display: flex; |
|||
margin-bottom: 16px; |
|||
|
|||
.r-txt { |
|||
padding-right: 8px; |
|||
min-width: 80px; |
|||
text-align: right; |
|||
|
|||
&.required::before { |
|||
margin-right: 4px; |
|||
color: #f56c6c; |
|||
font-family: SimSun, sans-serif; |
|||
content: "*"; |
|||
} |
|||
} |
|||
|
|||
.r-con { |
|||
flex: 1; |
|||
|
|||
.text { |
|||
margin-bottom: 8px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.btn-box { |
|||
margin-top: 20px; |
|||
text-align: center; |
|||
|
|||
.ant-btn+.ant-btn { |
|||
margin-left: 20px; |
|||
} |
|||
|
|||
.cancel { |
|||
border: 1px solid var(--button-default-bg); |
|||
background: var(--button-default-bg); |
|||
|
|||
span { |
|||
color: #ffffff; |
|||
} |
|||
} |
|||
} |
|||
} |
@ -1,15 +1,360 @@ |
|||
import React, { useState, useRef, useEffect } from "react"; |
|||
// import { message, Pagination, Table, Space, Modal, } from "antd"; |
|||
// import { dictionary, utils } from "@/config/common"; |
|||
// import moment from 'moment' |
|||
import { |
|||
message, |
|||
Input, |
|||
Select, |
|||
Button, |
|||
DatePicker, |
|||
Pagination, |
|||
Table, |
|||
Modal, |
|||
} from "antd"; |
|||
import { ResultFlowResult } from "@/components"; |
|||
// import { useSessionStorageState, useUpdateEffect, useSize, useUpdate } from 'ahooks'; |
|||
// import ajax from "@/services" |
|||
// import { FormInput, FormSelect, OptionPanel, ResultPanel, FormSliderPicker, AreaCascader, ImgResize, ImgZoom, } from "@/components" |
|||
// import "./index.scss"; |
|||
// import errorImg from "@/assets/images/layout/error.png" |
|||
// import { useLocation } from "react-router-dom"; |
|||
import ajax from "@/services/OperationCenter/OperationMarket"; |
|||
import { dictionary } from "@/config/common"; |
|||
import moment from "moment"; |
|||
import "./index.scss"; |
|||
|
|||
// 短信管理 |
|||
function ShortMessageMgm() { |
|||
return <div>ShortMessageMgm</div> |
|||
// 默认数据 |
|||
const defaultData = { |
|||
phoneNumber: "", // 手机号 |
|||
msgType: "", // 类型 |
|||
times: "", // 时间 |
|||
}; |
|||
// 分页数据 |
|||
const [pageInfo, setPageInfo] = useState({ |
|||
pageNum: 1, |
|||
pageSize: 15, |
|||
}); |
|||
// 表单数据 |
|||
const [formData, setFormData] = useState(defaultData); |
|||
// 搜索提交数据-存储 |
|||
const [holdData, setHoldData] = useState(formData); |
|||
// 访问接口,isAjax改变时执行 |
|||
const [isAjax, setIsAjax] = useState(false); |
|||
// 检索按钮加载状态 |
|||
const [loading, setLoading] = useState(false); |
|||
// 表格加载状态 |
|||
const [tabLoading, setTabLoading] = useState(false); |
|||
// 表格返回数据 |
|||
const [resultData, setResultData] = useState({ |
|||
total: 0, |
|||
list: [], |
|||
}); |
|||
|
|||
// 所有下拉菜单 |
|||
const [typeList, setTypeList] = useState([]); |
|||
|
|||
// 弹窗 |
|||
const [visible, setVisible] = useState(false); |
|||
const [modalObj, setModalObj] = useState({ |
|||
phoneNumber: "", //手机号 |
|||
content: "", //内容 |
|||
}); |
|||
|
|||
// 访问接口,获取下拉 |
|||
useEffect(() => { |
|||
getSelectList(); |
|||
}, []); |
|||
|
|||
// 访问接口,获取表格 |
|||
useEffect(() => { |
|||
getData(); |
|||
}, [isAjax]); |
|||
|
|||
// 表头 |
|||
const columns = [ |
|||
{ |
|||
title: "手机号", |
|||
dataIndex: "phoneNumber", |
|||
align: "center", |
|||
}, |
|||
{ |
|||
title: "消息类型", |
|||
dataIndex: "msgType", |
|||
align: "center", |
|||
render: (val, row, index) => { |
|||
return getTypeText(val); |
|||
}, |
|||
}, |
|||
{ |
|||
title: "内容", |
|||
dataIndex: "content", |
|||
align: "center", |
|||
}, |
|||
{ |
|||
title: "操作人", |
|||
dataIndex: "operatorId", |
|||
align: "center", |
|||
}, |
|||
{ |
|||
title: "时间", |
|||
dataIndex: "updatedTime", |
|||
align: "center", |
|||
sorter: (a, b) => |
|||
moment(a.updatedTime).diff(moment(b.updatedTime), "seconds"), |
|||
}, |
|||
]; |
|||
|
|||
// 获取状态文本 |
|||
const getTypeText = (val) => { |
|||
const obj = typeList.filter((v, i) => v.sms_id == val); |
|||
return obj?.length ? obj[0].sms_name : "-"; |
|||
}; |
|||
|
|||
// 分页 |
|||
const paginationProps = { |
|||
className: "pagination-common", |
|||
// position: ["bottomCenter"], |
|||
showQuickJumper: true, |
|||
showSizeChanger: true, |
|||
current: pageInfo.pageNum, |
|||
total: resultData?.total, |
|||
showTotal: () => `共 ${resultData.total || 0} 条`, |
|||
pageSize: pageInfo.pageSize, |
|||
pageSizeOptions: Array.from( |
|||
new Set([...[15], ...(dictionary?.pageSizeOptions || [])]) |
|||
), |
|||
onChange: (current, size) => { |
|||
setPageInfo({ |
|||
...pageInfo, |
|||
...{ pageNum: pageInfo.pageSize == size ? current : 1, pageSize: size }, |
|||
}); |
|||
setIsAjax(!isAjax); |
|||
}, |
|||
}; |
|||
|
|||
// 获取列表数据 |
|||
const getData = () => { |
|||
let postData = { ...formData }; |
|||
if (!loading) { |
|||
postData = { ...holdData }; |
|||
} |
|||
// 字段过滤 |
|||
const newObj = { |
|||
phoneNumber: postData?.phoneNumber, |
|||
msgType: postData?.msgType, |
|||
beginTime: postData?.times?.length |
|||
? postData?.times[0].format("YYYY-MM-DD HH:mm:ss") |
|||
: "", |
|||
endTime: postData?.times?.length |
|||
? postData?.times[1].format("YYYY-MM-DD HH:mm:ss") |
|||
: "", |
|||
}; |
|||
// console.log(postData, newObj); |
|||
setTabLoading(true); |
|||
ajax.getSmsList({ ...newObj, ...pageInfo }).then( |
|||
(res) => { |
|||
if (parseInt(res?.status) === 20000) { |
|||
setResultData(res?.data || {}); |
|||
} else { |
|||
message.error(res?.message); |
|||
} |
|||
setLoading(false); |
|||
setTabLoading(false); |
|||
}, |
|||
(err) => { |
|||
console.log(err); |
|||
setLoading(false); |
|||
setTabLoading(false); |
|||
} |
|||
); |
|||
}; |
|||
|
|||
// 检索数据 |
|||
const handleSearch = () => { |
|||
setLoading(true); |
|||
setPageInfo({ ...pageInfo, ...{ pageNum: 1 } }); |
|||
setHoldData(formData); |
|||
setIsAjax(!isAjax); |
|||
}; |
|||
|
|||
// 下拉菜单 |
|||
const getSelectList = () => { |
|||
ajax.getSmsMsgType().then( |
|||
(res) => { |
|||
if (parseInt(res?.status) === 20000) { |
|||
setTypeList(res?.data?.list || []); |
|||
} else { |
|||
message.error(res?.message); |
|||
} |
|||
}, |
|||
(err) => { |
|||
console.log(err); |
|||
} |
|||
); |
|||
}; |
|||
|
|||
// 发送-确定 |
|||
const handleComfirm = () => { |
|||
if (!modalObj?.phoneNumber) { |
|||
message.error("请输入手机号"); |
|||
return; |
|||
} |
|||
if (!modalObj?.content) { |
|||
message.error("请输入内容"); |
|||
return; |
|||
} |
|||
ajax.doSmsSend(modalObj).then( |
|||
(res) => { |
|||
if (parseInt(res?.status) === 20000) { |
|||
message.success(res?.message); |
|||
setVisible(false); |
|||
setPageInfo({ ...pageInfo, ...{ pageNum: 1 } }); |
|||
setIsAjax(!isAjax); |
|||
} else { |
|||
message.error(res?.message); |
|||
} |
|||
}, |
|||
(err) => { |
|||
console.log(err); |
|||
} |
|||
); |
|||
}; |
|||
|
|||
return ( |
|||
<div className="short-message-mgm"> |
|||
{/* 主页 */} |
|||
<div className="mgm-wraper"> |
|||
<div className="search-group"> |
|||
<div class="title">查询条件</div> |
|||
<div className="form-box"> |
|||
<div className="form-txt">手机号</div> |
|||
<Input |
|||
className="form-con" |
|||
placeholder="请输入手机号" |
|||
value={formData?.phoneNumber} |
|||
onChange={(e) => |
|||
setFormData({ ...formData, phoneNumber: e.target.value }) |
|||
} |
|||
/> |
|||
</div> |
|||
<div className="form-box"> |
|||
<div className="form-txt">类型</div> |
|||
<Select |
|||
className="form-con" |
|||
allowClear |
|||
fieldNames={{ |
|||
value: "sms_id", |
|||
label: "sms_name", |
|||
}} |
|||
options={typeList || []} |
|||
placeholder="全部" |
|||
value={formData?.msgType || undefined} |
|||
onChange={(e) => setFormData({ ...formData, msgType: e })} |
|||
/> |
|||
</div> |
|||
<div className="form-box"> |
|||
<div className="form-txt">时间</div> |
|||
<DatePicker.RangePicker |
|||
className="form-long" |
|||
showTime |
|||
value={formData?.times || null} |
|||
onChange={(e, str) => setFormData({ ...formData, times: e })} |
|||
/> |
|||
</div> |
|||
<div className="form-btn"> |
|||
<Button className="reset" onClick={() => setFormData(defaultData)}> |
|||
重置 |
|||
</Button> |
|||
<Button |
|||
className="submit" |
|||
type="primary" |
|||
onClick={handleSearch} |
|||
loading={loading} |
|||
> |
|||
查询 |
|||
</Button> |
|||
</div> |
|||
</div> |
|||
<div className="result-group"> |
|||
<div className="row-head"> |
|||
<span className="number-wrapper"> |
|||
<span className="letter">共查询到</span> |
|||
<span className="total-number"> {resultData.total || 0} </span> |
|||
<span className="letter">条结果</span> |
|||
</span> |
|||
<div> |
|||
<Button |
|||
type="primary" |
|||
onClick={() => { |
|||
setModalObj({ phoneNumber: "", content: "" }); |
|||
setVisible(true); |
|||
}} |
|||
> |
|||
发送消息 |
|||
</Button> |
|||
</div> |
|||
</div> |
|||
<ResultFlowResult |
|||
ajaxLoad={tabLoading} |
|||
resultData={resultData?.list || []} |
|||
> |
|||
<Table |
|||
// bordered |
|||
className="yisa-table" |
|||
rowKey={(row) => row.id} |
|||
dataSource={resultData?.list || []} |
|||
columns={columns} |
|||
pagination={false} |
|||
loading={tabLoading} |
|||
/> |
|||
<Pagination {...paginationProps} className="pagination-common" /> |
|||
</ResultFlowResult> |
|||
</div> |
|||
</div> |
|||
<Modal |
|||
title="发送短信消息" |
|||
open={visible} |
|||
// centered |
|||
footer={null} |
|||
width={772} |
|||
onCancel={() => setVisible(false)} |
|||
className="modal-short" |
|||
> |
|||
<div> |
|||
<div className="row-box"> |
|||
<div className="r-txt">发送对象</div> |
|||
<div className="r-con"> |
|||
<div className="text">指定用户</div> |
|||
<Input.TextArea |
|||
placeholder="请输入手机号,多个手机号用,分隔。例:13400000001,13400000002" |
|||
autoSize={{ minRows: 2, maxRows: 2 }} |
|||
value={modalObj.phoneNumber} |
|||
onChange={(e) => |
|||
setModalObj({ ...modalObj, phoneNumber: e.target.value }) |
|||
} |
|||
/> |
|||
</div> |
|||
</div> |
|||
<div className="row-box"> |
|||
<div className="r-txt required">内容</div> |
|||
<div className="r-con"> |
|||
<Input.TextArea |
|||
placeholder="请输入内容" |
|||
autoSize={{ minRows: 2, maxRows: 2 }} |
|||
value={modalObj.content} |
|||
onChange={(e) => |
|||
setModalObj({ ...modalObj, content: e.target.value }) |
|||
} |
|||
/> |
|||
</div> |
|||
</div> |
|||
<div className="btn-box"> |
|||
<Button className="cancel" onClick={() => setVisible(false)}> |
|||
取消 |
|||
</Button> |
|||
<Button type="primary" onClick={handleComfirm}> |
|||
发送 |
|||
</Button> |
|||
</div> |
|||
</div> |
|||
</Modal> |
|||
</div> |
|||
); |
|||
} |
|||
|
|||
export default ShortMessageMgm; |
@ -0,0 +1,12 @@ |
|||
import ajax from "@/config/ajax"; |
|||
// --短信管理--
|
|||
export default { |
|||
// 消息类型
|
|||
getSmsMsgType: (data) => |
|||
ajax({ url: "/api/ope/sms/message_type", type: "get", data }), |
|||
// 列表
|
|||
getSmsList: (data) => ajax({ url: "/api/ope/sms/list", type: "get", data }), |
|||
// 发送
|
|||
doSmsSend: (data) => |
|||
ajax({ url: "/api/ope/sms/send_message", type: "post", data }), |
|||
}; |
Write
Preview
Loading…
Cancel
Save
Reference in new issue