parent
20f7e338d0
commit
1b148f9e51
@ -1,100 +1,293 @@
|
|||||||
import TabsComp from '@/components/TabsComp';
|
import TabsComp from '@/components/TabsComp';
|
||||||
import styles from '../../../GLQ/index.less';
|
import styles from '../../../GLQ/index.less';
|
||||||
import { useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { ConfigProvider, DatePicker, Form, Input, Select, Table } from 'antd';
|
import { ConfigProvider, DatePicker, Form, Input, Pagination, Select, Table, message } from 'antd';
|
||||||
|
|
||||||
import { rowClassName } from '@/utils';
|
import { rowClassName } from '@/utils';
|
||||||
import ButtonComp from '@/components/ButtonComp';
|
import ButtonComp from '@/components/ButtonComp';
|
||||||
|
import { mailIssueList, secretFormatList, secretList, secretUpdateStatus } from '@/services/my';
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const [activeTab, setActiveTab] = useState(1)
|
const [activeTab, setActiveTab] = useState(1)
|
||||||
const [tableData, setTableData] = useState([]);
|
const [tableData, setTableData] = useState([]);
|
||||||
|
const [pageNumber, setPageNumber] = useState(1);
|
||||||
|
const [pageSize, setpageSize] = useState(10);
|
||||||
|
const [total, setTotal] = useState(0);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
const [selectData, setSelectData] = useState<any>({
|
||||||
|
productName: [],
|
||||||
|
publisherType: []
|
||||||
|
});
|
||||||
|
const [tableData1, setTableData1] = useState([]);
|
||||||
|
const [pageNumber1, setPageNumber1] = useState(1);
|
||||||
|
const [pageSize1, setpageSize1] = useState(10);
|
||||||
|
const [total1, setTotal1] = useState(0);
|
||||||
|
|
||||||
|
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
|
||||||
|
const formItemSty = { width: '31%', marginBottom: 20, marginRight: 30 };
|
||||||
|
|
||||||
const columns: any = [
|
const columns: any = [
|
||||||
{
|
{
|
||||||
title: '序号', key: 'index', align: 'center', width: 100,
|
title: '序号', key: 'index', align: 'center', width: 100,
|
||||||
render: (a: any, b: any, c: any) => {
|
render: (a: any, b: any, c: any) => {
|
||||||
return <span>{c + 1}</span>;
|
return <span>{(pageNumber - 1) * pageSize + c + 1}</span>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ title: '产品名称', dataIndex: 'productName', key: 'productName', align: 'center' },
|
||||||
|
{ title: '产品编号', dataIndex: 'productNum', key: 'productNum', align: 'center' },
|
||||||
|
{ title: '载体类型', dataIndex: 'carrierType', key: 'carrierType', align: 'center' },
|
||||||
|
{ title: '载体型号', dataIndex: 'applyModel', key: 'applyModel', align: 'center' },
|
||||||
|
{ title: '数量', dataIndex: 'number', key: 'number', align: 'center' },
|
||||||
|
{ title: '当前状态', dataIndex: 'currentStatus', key: 'currentStatus', align: 'center' },
|
||||||
|
{ title: '导入时间', dataIndex: 'importTime', key: 'importTime', align: 'center' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const columns1: any = [
|
||||||
|
{
|
||||||
|
title: '序号', key: 'index', align: 'center', width: 100,
|
||||||
|
render: (a: any, b: any, c: any) => {
|
||||||
|
return <span>{(pageNumber1 - 1) * pageSize1 + c + 1}</span>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ title: '编号', dataIndex: 'name', key: 'name', align: 'center' },
|
// { title: '编号', dataIndex: 'name', key: 'name', align: 'center' },
|
||||||
{ title: '密钥分发平台名称', dataIndex: 'name', key: 'name', align: 'center' },
|
{ title: '密钥分发平台名称', dataIndex: 'keyDistPlatformName', key: 'keyDistPlatformName', align: 'center' },
|
||||||
{ title: '密钥分发平台实体标识', dataIndex: 'name', key: 'name', align: 'center' },
|
{ title: '密钥分发平台实体标识', dataIndex: 'keyDistPlatformEntity', key: 'keyDistPlatformEntity', align: 'center' },
|
||||||
{ title: '产品名称', dataIndex: 'name', key: 'name', align: 'center' },
|
{ title: '产品名称', dataIndex: 'productName', key: 'productName', align: 'center' },
|
||||||
{ title: '产品编号', dataIndex: 'name', key: 'name', align: 'center' },
|
{ title: '产品编号', dataIndex: 'productCode', key: 'productCode', align: 'center' },
|
||||||
{ title: '载体类型', dataIndex: 'name', key: 'name', align: 'center' },
|
{ title: '载体类型', dataIndex: 'carrierType', key: 'carrierType', align: 'center' },
|
||||||
{ title: '载体型号', dataIndex: 'name', key: 'name', align: 'center' },
|
{ title: '载体型号', dataIndex: 'applyModel', key: 'applyModel', align: 'center' },
|
||||||
{ title: '总数量', dataIndex: 'name', key: 'name', align: 'center' },
|
{ title: '总数量', dataIndex: 'total', key: 'total', align: 'center' },
|
||||||
{ title: '已下载数量', dataIndex: 'name', key: 'name', align: 'center' },
|
{ title: '已下载数量', dataIndex: 'downloadNum', key: 'downloadNum', align: 'center' },
|
||||||
{ title: '授权', dataIndex: 'name', key: 'name', align: 'center' },
|
{ title: '授权', dataIndex: 'empower', key: 'empower', align: 'center' },
|
||||||
{ title: '优先级', dataIndex: 'name', key: 'name', align: 'center' },
|
{ title: '优先级', dataIndex: 'priority', key: 'priority', align: 'center' },
|
||||||
{ title: '结束时间', dataIndex: 'name', key: 'name', align: 'center' },
|
{ title: '结束时间', dataIndex: 'overTime', key: 'overTime', align: 'center' },
|
||||||
{ title: '通知标志', dataIndex: 'name', key: 'name', align: 'center' },
|
{ title: '通知标志', dataIndex: 'notificationFlag', key: 'notificationFlag', align: 'center' },
|
||||||
{ title: '删除标志', dataIndex: 'name', key: 'name', align: 'center' }
|
{ title: '删除标志', dataIndex: 'deleteFlag', key: 'deleteFlag', align: 'center' }
|
||||||
]
|
]
|
||||||
|
|
||||||
const formItemSty = { width: '32%', marginBottom: 20 };
|
useEffect(() => {
|
||||||
|
form.setFieldsValue({
|
||||||
|
productName: '',
|
||||||
|
carrierType: '',
|
||||||
|
carrierNumber: '',
|
||||||
|
orderDirection: '',
|
||||||
|
})
|
||||||
|
getSelect()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
// 获取下拉框数据
|
||||||
|
const getSelect = () => {
|
||||||
|
secretFormatList({}).then((res) => {
|
||||||
|
if (res?.result == "success") {
|
||||||
|
let list = res.data[0].list;
|
||||||
|
let productName = list.map((item: any) => { return { label: item.productName, value: item.productName } });
|
||||||
|
let carrierType = list.map((item: any) => { return { label: item.carrierType, value: item.carrierType } });
|
||||||
|
let carrierNumber = list.map((item: any) => { return { label: item.carrierNumber, value: item.carrierNumber } });
|
||||||
|
setSelectData({
|
||||||
|
productName: [{ label: '全部', value: '' }, ...productName],
|
||||||
|
carrierType: [{ label: '全部', value: '' }, ...carrierType],
|
||||||
|
carrierNumber: [{ label: '全部', value: '' }, ...carrierNumber],
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
message.error(res?.errorMsg);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const onFinish = (values: any) => {
|
useEffect(() => {
|
||||||
console.log('表单提交:', values);
|
getList();
|
||||||
|
}, [pageNumber]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getList1();
|
||||||
|
}, [pageNumber1]);
|
||||||
|
|
||||||
|
// 获取密钥体列表
|
||||||
|
const getList = () => {
|
||||||
|
let data = form.getFieldsValue()
|
||||||
|
let params = {
|
||||||
|
'secretImport.productName': data.productName,
|
||||||
|
'secretImport.productNum': data.productNum,
|
||||||
|
'secretImport.carrierType': data.carrierType,
|
||||||
|
'secretImport.carrierNumber': data.carrierNumber,
|
||||||
|
}
|
||||||
|
secretList({ pageNumber, pageSize, ...params }).then((res) => {
|
||||||
|
if (res?.result == "success") {
|
||||||
|
setTotal(res.data[0].total)
|
||||||
|
setTableData(res.data[0].list)
|
||||||
|
} else {
|
||||||
|
message.error(res?.errorMsg);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取密钥体邮箱任务列表
|
||||||
|
const getList1 = () => {
|
||||||
|
mailIssueList({ pageNumber: pageNumber1, pageSize: pageSize1 }).then((res) => {
|
||||||
|
if (res?.result == "success") {
|
||||||
|
setTotal1(res.data[0].total)
|
||||||
|
setTableData1(res.data[0].list)
|
||||||
|
} else {
|
||||||
|
message.error(res?.errorMsg);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const pageOnChange = (pageNumber: number) => {
|
||||||
|
setPageNumber(pageNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onShowSizeChange = (current: any, pageSize: any) => {
|
||||||
|
setpageSize(pageSize);
|
||||||
|
getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
const onFinish = () => {
|
||||||
|
pageNumber == 1 ? getList() : setPageNumber(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const sending = (type: number) => {
|
||||||
|
if (selectedRowKeys.length == 0) {
|
||||||
|
message.info('请勾选数据');
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let promises = selectedRowKeys.map(item => {
|
||||||
|
return secretUpdateStatus({ id: item, type }).then((res) => {
|
||||||
|
if (res?.result === "success") {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
message.error(res?.errorMsg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Promise.all(promises).then(results => {
|
||||||
|
let recordCount = results.reduce((acc: any, val) => acc + val, 0);
|
||||||
|
if (recordCount === selectedRowKeys.length) {
|
||||||
|
message.success('配发成功');
|
||||||
|
pageNumber1 == 1 ? getList1() : setPageNumber1(1);
|
||||||
|
setSelectedRowKeys([]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${styles.params_warp}`}>
|
<div className={`${styles.params_warp}`}>
|
||||||
<TabsComp
|
<TabsComp
|
||||||
dataSource={[{ id: 1, name: '密钥体导入' }]}
|
dataSource={[{ id: 1, name: '向邮箱配发密钥体' }]}
|
||||||
activeTab={activeTab}
|
activeTab={activeTab}
|
||||||
onChange={(e) => setActiveTab(e)} />
|
onChange={(e) => setActiveTab(e)} />
|
||||||
|
|
||||||
<Form form={form} layout={'inline'} onFinish={onFinish} className='mt20'>
|
<Form form={form} layout={'inline'} onFinish={onFinish} className='mt20'>
|
||||||
<Form.Item name="aaa" label="产品名称" style={formItemSty}>
|
<Form.Item name="productName" label="产品名称" style={formItemSty}>
|
||||||
<Select style={{ width: 260 }} onChange={(e) => { }} options={[{ label: '选项1', value: 1 }]} />
|
<Select style={{ width: 260 }} onChange={(e) => { }} options={selectData.productName} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="aaa" label="载体类型" style={formItemSty}>
|
<Form.Item name="carrierType" label="载体类型" style={formItemSty}>
|
||||||
<Select style={{ width: 260 }} onChange={(e) => { }} options={[{ label: '选项1', value: 1 }]} />
|
<Select style={{ width: 260 }} onChange={(e) => { }} options={selectData.carrierType} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="aaa" label="可下载数量" style={formItemSty}>
|
{/* <Form.Item name="aaa" label="可下载数量" style={formItemSty}>
|
||||||
|
<Input style={{ width: 260 }} />
|
||||||
|
</Form.Item> */}
|
||||||
|
<Form.Item name="productNum" label="产品编号" style={formItemSty}>
|
||||||
<Input style={{ width: 260 }} />
|
<Input style={{ width: 260 }} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="aaa" label="产品编号" style={formItemSty}>
|
<div className='flex_aiC'>
|
||||||
<Select style={{ width: 260 }} onChange={(e) => { }} options={[{ label: '选项1', value: 1 }]} />
|
<Form.Item name="carrierNumber" label="载体型号" style={{ marginBottom: 30 }}>
|
||||||
</Form.Item>
|
<Select style={{ width: 260 }} onChange={(e) => { }} options={selectData.carrierNumber} />
|
||||||
<Form.Item name="aaa" label="载体型号" style={formItemSty}>
|
|
||||||
<Select style={{ width: 260 }} onChange={(e) => { }} options={[{ label: '选项1', value: 1 }]} />
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="aaa" label=" 下载授权" style={formItemSty}>
|
<ButtonComp style={{ marginBottom: 30 }} text={'查询'} onClick={() => form.submit()} />
|
||||||
<Select style={{ width: 260 }} onChange={(e) => { }} options={[{ label: '选项1', value: 1 }]} />
|
</div>
|
||||||
|
{/* <Form.Item name="aaa" label=" 下载授权" style={formItemSty}>
|
||||||
|
<Select style={{ width: 260 }} onChange={(e) => { }} options={[
|
||||||
|
{ label: '已授权', value: '已授权' },
|
||||||
|
{ label: '未授权', value: '未授权' }
|
||||||
|
]} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="aaa" label="目的系统" style={formItemSty}>
|
<Form.Item name="systemName" label="目的系统" style={formItemSty}>
|
||||||
<Select style={{ width: 260 }} onChange={(e) => { }} options={[{ label: '选项1', value: 1 }]} />
|
<Select style={{ width: 260 }} onChange={(e) => { }} options={[]} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="aaa" label="配发数量" style={formItemSty}>
|
<Form.Item name="quantity" label="配发数量" style={formItemSty}>
|
||||||
<Select style={{ width: 260 }} onChange={(e) => { }} options={[{ label: '选项1', value: 1 }]} />
|
<Input style={{ width: 260 }} type='number' min={0} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="aaa" label=" 优先级" style={formItemSty}>
|
<Form.Item name="aaa" label=" 优先级" style={formItemSty}>
|
||||||
<Select style={{ width: 260 }} onChange={(e) => { }} options={[{ label: '选项1', value: 1 }]} />
|
<Select style={{ width: 260 }} onChange={(e) => { }} options={[
|
||||||
|
{ label: '普通', value: '普通' },
|
||||||
|
{ label: '特急', value: '特急' },
|
||||||
|
{ label: '紧急', value: '紧急' }
|
||||||
|
]} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item name="aaa" label="结束时间" style={formItemSty}>
|
<Form.Item name="aaa" label="结束时间" style={formItemSty}>
|
||||||
<DatePicker style={{ width: 260 }} />
|
<DatePicker style={{ width: 260 }} />
|
||||||
</Form.Item>
|
</Form.Item> */}
|
||||||
</Form>
|
</Form>
|
||||||
|
|
||||||
|
|
||||||
<div className='mb20 flex_aiC_jB'>
|
<div className='mb20 flex_aiC_jB'>
|
||||||
<div>密钥体邮箱任务列表</div>
|
<div>密钥体列表</div>
|
||||||
<ButtonComp type={'cancel'} text={'配发'} onClick={() => { }} />
|
<ButtonComp type={'cancel'} text={'配发'} onClick={() => sending(2)} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Table
|
<Table
|
||||||
scroll={tableData.length > 0 ? { y: 41 * 9 } : {}}
|
scroll={{ x: 800, y: 41 * 11 }}
|
||||||
pagination={false}
|
pagination={false}
|
||||||
bordered
|
bordered
|
||||||
columns={columns}
|
columns={columns}
|
||||||
dataSource={tableData}
|
dataSource={tableData}
|
||||||
rowKey={(record: any) => record?.id}
|
rowKey={(record: any) => record?.id}
|
||||||
rowClassName={rowClassName}
|
rowClassName={rowClassName}
|
||||||
|
rowSelection={{
|
||||||
|
selectedRowKeys,
|
||||||
|
onChange: (selectedKeys: any) => {
|
||||||
|
setSelectedRowKeys(selectedKeys);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{total > 0 && <div className='flex_aiC_jB mt20'>
|
||||||
|
<div>共 {total} 条</div>
|
||||||
|
<Pagination
|
||||||
|
current={pageNumber}
|
||||||
|
pageSize={pageSize}
|
||||||
|
total={total}
|
||||||
|
showQuickJumper
|
||||||
|
onChange={pageOnChange}
|
||||||
|
onShowSizeChange={onShowSizeChange}
|
||||||
|
/>
|
||||||
|
</div>}
|
||||||
|
|
||||||
|
<div className='mt30 mb20 flex_aiC_jB'>
|
||||||
|
<div>密钥体邮箱任务列表</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<Table
|
||||||
|
scroll={{ x: 800, y: 41 * 11 }}
|
||||||
|
pagination={false}
|
||||||
|
bordered
|
||||||
|
columns={columns1}
|
||||||
|
dataSource={tableData1}
|
||||||
|
rowKey={(record: any) => record?.id}
|
||||||
|
rowClassName={rowClassName}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{total1 > 0 && <div className='flex_aiC_jB mt20'>
|
||||||
|
<div>共 {total1} 条</div>
|
||||||
|
<Pagination
|
||||||
|
current={pageNumber1}
|
||||||
|
pageSize={pageSize1}
|
||||||
|
total={total1}
|
||||||
|
showQuickJumper
|
||||||
|
onChange={(pageNumber: number) => {
|
||||||
|
setPageNumber1(pageNumber);
|
||||||
|
}}
|
||||||
|
onShowSizeChange={(current: any, pageSize: any) => {
|
||||||
|
setpageSize1(pageSize);
|
||||||
|
getList1();
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
import { getRequest, postFormDataRequest, postRequest, uploadFile } from "@/utils/request";
|
||||||
|
|
||||||
|
// 密钥体格式导入
|
||||||
|
export async function secretFormatImport(formData: any) {
|
||||||
|
return uploadFile(`/xgd/secretBodyManger/secretFormatImport`, formData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密钥体格式列表
|
||||||
|
export async function secretFormatList(params: any) {
|
||||||
|
return getRequest(`/xgd/secretBodyManger/secretFormatList`, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改密钥体状态
|
||||||
|
// type: 1 删除 2还原 3清理
|
||||||
|
export async function secretUpdateSecret(data: any) {
|
||||||
|
return postFormDataRequest(`/xgd/secretBodyManger/updateSecret`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密钥体格式发布
|
||||||
|
export async function secretPublisher(data: any) {
|
||||||
|
return getRequest(`/xgd/secretBodyManger/secretPublisher`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密钥体导入
|
||||||
|
export async function secretBodyImport(formData: any) {
|
||||||
|
return uploadFile(`/xgd/secretBodyManger/secretBodyImport`, formData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密钥体接收单列表
|
||||||
|
export async function secretBodyList(params: any) {
|
||||||
|
return getRequest(`/xgd/secretBodyManger/secretBodyList`, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密钥体列表
|
||||||
|
export async function secretList(params: any) {
|
||||||
|
return getRequest(`/xgd/secretBodyManger/secretList`, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 密钥体申请
|
||||||
|
export async function addSecretAsk(data: any) {
|
||||||
|
return postRequest(`/xgd/secretBodyManger/addSecretAsk`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密钥体申请列表
|
||||||
|
export async function secretAskList(params: any) {
|
||||||
|
return getRequest(`/xgd/secretBodyManger/secretAskList`, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密钥体配发
|
||||||
|
// type: 1 向下级配发 2 向邮箱配发 3 向专用密码管理系统配发
|
||||||
|
export async function secretUpdateStatus(data: any) {
|
||||||
|
return postFormDataRequest(`/xgd/secretBodyManger/updateStatus`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密钥体配发-密钥体邮箱任务列表
|
||||||
|
export async function mailIssueList(params: any) {
|
||||||
|
return getRequest(`/xgd/secretBodyManger/mailIssueList`, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密钥体配发-向专用密码管理系统配发列表
|
||||||
|
export async function privateIssueList(params: any) {
|
||||||
|
return getRequest(`/xgd/secretBodyManger/privateIssueList`, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密钥体配发-向下级配发列表
|
||||||
|
export async function belowIssueList(params: any) {
|
||||||
|
return getRequest(`/xgd/secretBodyManger/belowIssueList`, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密钥体载体包封 - 明文载体包封
|
||||||
|
export async function keyBodyCarrierClearText(data: any) {
|
||||||
|
return postRequest(`/xgd/secretBodyManger/keyBodyCarrierClearText`, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 密钥体载体包封 - 密文载体包封
|
||||||
|
export async function keyBodyCarrierEncrypted(data: any) {
|
||||||
|
return postRequest(`/xgd/secretBodyManger/keyBodyCarrierEncrypted`, data);
|
||||||
|
}
|
Loading…
Reference in new issue