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
-
151src/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"; |
@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 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 { 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() { |
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; |
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