|
|
package cmd
|
|
|
|
|
|
import (
|
|
|
"github.com/go-resty/resty/v2"
|
|
|
"github.com/mizuki1412/go-core-kit/class/exception"
|
|
|
"github.com/mizuki1412/go-core-kit/init/initkit"
|
|
|
"github.com/mizuki1412/go-core-kit/library/commonkit"
|
|
|
"github.com/mizuki1412/go-core-kit/service/configkit"
|
|
|
"github.com/mizuki1412/go-core-kit/service/logkit"
|
|
|
"github.com/spf13/cast"
|
|
|
"github.com/spf13/cobra"
|
|
|
"github.com/tidwall/gjson"
|
|
|
"github.com/xuri/excelize/v2"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
func init() {
|
|
|
rootCmd.AddCommand(iom3Cmd)
|
|
|
defFlagsIOM3(iom3Cmd)
|
|
|
}
|
|
|
|
|
|
var iom3Cmd = &cobra.Command{
|
|
|
Use: "iom3",
|
|
|
Short: "Batch processing operations of the iom",
|
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
|
initkit.BindFlags(cmd)
|
|
|
res := readExcelWaitDel()
|
|
|
runIOM3(res)
|
|
|
},
|
|
|
}
|
|
|
|
|
|
func defFlagsIOM3(cmd *cobra.Command) {
|
|
|
cmd.Flags().String("token", "", "*Specify the token of IOM")
|
|
|
cmd.Flags().String("file", "", "*Specify the path of IOM file")
|
|
|
}
|
|
|
|
|
|
var client = resty.New().SetRetryCount(5).SetRetryWaitTime(20 * time.Second)
|
|
|
|
|
|
func runIOM3(data map[string][][]string) {
|
|
|
//先处理11级地址
|
|
|
data11 := data["11"]
|
|
|
for _, v := range data11 {
|
|
|
_ = commonkit.RecoverFuncWrapper(func() {
|
|
|
queryEqptsAndInvalid(v[3], v[0], v[1], v[2])
|
|
|
})
|
|
|
}
|
|
|
data10 := data["10"]
|
|
|
for _, v := range data10 {
|
|
|
_ = commonkit.RecoverFuncWrapper(func() {
|
|
|
queryEqptsAndInvalid2(v[3], v[0], v[1], v[2])
|
|
|
})
|
|
|
}
|
|
|
data9 := data["9"]
|
|
|
for _, v := range data9 {
|
|
|
_ = commonkit.RecoverFuncWrapper(func() {
|
|
|
queryEqptsAndInvalid2(v[3], v[0], v[1], v[2])
|
|
|
})
|
|
|
}
|
|
|
data8 := data["8"]
|
|
|
for _, v := range data8 {
|
|
|
_ = commonkit.RecoverFuncWrapper(func() {
|
|
|
queryEqptsAndInvalid2(v[3], v[0], v[1], v[2])
|
|
|
})
|
|
|
}
|
|
|
data7 := data["7"]
|
|
|
for _, v := range data7 {
|
|
|
_ = commonkit.RecoverFuncWrapper(func() {
|
|
|
queryEqptsAndInvalid2(v[3], v[0], v[1], v[2])
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func queryEqptsAndInvalid(districtId, standardAddrId, roadId, parentId string) {
|
|
|
//获取上一级地址
|
|
|
resp, err := client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetBody(map[string]interface{}{
|
|
|
"districtId": districtId,
|
|
|
"parentAddrId": parentId,
|
|
|
"regionId": "A",
|
|
|
"roadId": roadId,
|
|
|
}).Post("http://132.151.25.19:15609/prod-api/address/standard/list/tree")
|
|
|
if err != nil || resp.IsError() || gjson.Get(resp.String(), "code").Int() != 200 {
|
|
|
panic(exception.New("获取TreeThis失败"))
|
|
|
}
|
|
|
treeThis := gjson.Get(resp.String(), "data").Array()
|
|
|
for _, this := range treeThis {
|
|
|
if this.Get("standardAddrId").String() != standardAddrId {
|
|
|
continue
|
|
|
}
|
|
|
logkit.Info("开始处理:" + this.Get("detailName").String())
|
|
|
resp, err = client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetQueryParams(map[string]string{
|
|
|
"regionId": "A",
|
|
|
"districtId": districtId,
|
|
|
"standardAddrId": standardAddrId,
|
|
|
"roadId": roadId,
|
|
|
}).Get("http://132.151.25.19:15609/prod-api/resource/list/queryStandardAddress")
|
|
|
if err != nil || resp.IsError() {
|
|
|
panic(exception.New("获取地址详情失败"))
|
|
|
}
|
|
|
//判断用户是否为0,设备是否有关联
|
|
|
userCount := gjson.Get(resp.String(), "0.userCount").String()
|
|
|
eqptCount := gjson.Get(resp.String(), "0.eqptCount").String()
|
|
|
if userCount == "0" {
|
|
|
if eqptCount != "0" {
|
|
|
//用户为0,并且有设备关联,取消关联后删除
|
|
|
resp, err = client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetQueryParams(map[string]string{
|
|
|
"regionId": "A",
|
|
|
"standardAddrId": standardAddrId,
|
|
|
}).Get("http://132.151.25.19:15609/prod-api/resource/list/queryEqpts")
|
|
|
if err != nil || resp.IsError() {
|
|
|
panic(exception.New("获取设备详情失败"))
|
|
|
}
|
|
|
nodeID := gjson.Get(resp.String(), "0.eqptNodeId").Int()
|
|
|
//取消关联
|
|
|
resp, err = client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetBody(map[string]interface{}{
|
|
|
"eqptNodeIds": []int64{nodeID},
|
|
|
"standardAddrId": standardAddrId,
|
|
|
"oldAddrId": standardAddrId,
|
|
|
"regionId": "A",
|
|
|
}).Post("http://132.151.25.19:15609/prod-api/resource/list/updateEqptStandAddress")
|
|
|
logkit.Info("已取消关联:" + gjson.Get(this.String(), "detailName").String())
|
|
|
m := this.Map()
|
|
|
resultMap := make(map[string]interface{})
|
|
|
for k, v := range m {
|
|
|
resultMap[k] = v.Value()
|
|
|
}
|
|
|
//resp, err = client.R().
|
|
|
// SetHeaders(map[string]string{
|
|
|
// "Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
// "Content-Type": "application/json;charset=UTF-8",
|
|
|
// "Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
// "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
// }).
|
|
|
// SetBody(resultMap).Post("http://132.151.25.19:15609/prod-api/address/standard/confirm/invalid")
|
|
|
//if err != nil || resp.IsError() || gjson.Get(resp.String(), "code").Int() != 200 {
|
|
|
// panic(exception.New("有用户,无法删除:" + gjson.Get(this.String(), "detailName").String()))
|
|
|
//}
|
|
|
resp, err = client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetBody(resultMap).Put("http://132.151.25.19:15609/prod-api/address/standard/invalid")
|
|
|
if err != nil || resp.IsError() || gjson.Get(resp.String(), "code").Int() != 200 {
|
|
|
panic(exception.New("Invalid失败"))
|
|
|
}
|
|
|
logkit.Info("已删除:" + gjson.Get(this.String(), "detailName").String())
|
|
|
} else {
|
|
|
//用户为0,并且没有设备关联,直接删除
|
|
|
m := this.Map()
|
|
|
resultMap := make(map[string]interface{})
|
|
|
for k, v := range m {
|
|
|
resultMap[k] = v.Value()
|
|
|
}
|
|
|
//resp, err = client.R().
|
|
|
// SetHeaders(map[string]string{
|
|
|
// "Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
// "Content-Type": "application/json;charset=UTF-8",
|
|
|
// "Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
// "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
// }).
|
|
|
// SetBody(resultMap).Post("http://132.151.25.19:15609/prod-api/address/standard/confirm/invalid")
|
|
|
//if err != nil || resp.IsError() || gjson.Get(resp.String(), "code").Int() != 200 {
|
|
|
// panic(exception.New("有用户,无法删除:" + gjson.Get(this.String(), "detailName").String()))
|
|
|
//}
|
|
|
resp, err = client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetBody(resultMap).Put("http://132.151.25.19:15609/prod-api/address/standard/invalid")
|
|
|
if err != nil || resp.IsError() || gjson.Get(resp.String(), "code").Int() != 200 {
|
|
|
panic(exception.New("Invalid失败"))
|
|
|
}
|
|
|
logkit.Info("已删除:" + gjson.Get(this.String(), "detailName").String())
|
|
|
}
|
|
|
} else {
|
|
|
logkit.Info("@@@存在用户@@@" + gjson.Get(this.String(), "detailName").String())
|
|
|
}
|
|
|
break
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func queryEqptsAndInvalid2(districtId, standardAddrId, roadId, parentId string) {
|
|
|
//获取上一级地址
|
|
|
resp, err := client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetBody(map[string]interface{}{
|
|
|
"districtId": districtId,
|
|
|
"parentAddrId": parentId,
|
|
|
"regionId": "A",
|
|
|
"roadId": roadId,
|
|
|
}).Post("http://132.151.25.19:15609/prod-api/address/standard/list/tree")
|
|
|
if err != nil || resp.IsError() || gjson.Get(resp.String(), "code").Int() != 200 {
|
|
|
panic(exception.New("获取TreeThis失败"))
|
|
|
}
|
|
|
treeThis := gjson.Get(resp.String(), "data").Array()
|
|
|
for _, this := range treeThis {
|
|
|
if this.Get("standardAddrId").String() != standardAddrId {
|
|
|
continue
|
|
|
}
|
|
|
logkit.Info("开始处理:" + this.Get("detailName").String())
|
|
|
resp, err = client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetQueryParams(map[string]string{
|
|
|
"regionId": "A",
|
|
|
"districtId": districtId,
|
|
|
"standardAddrId": standardAddrId,
|
|
|
"roadId": roadId,
|
|
|
}).Get("http://132.151.25.19:15609/prod-api/resource/list/queryStandardAddress")
|
|
|
if err != nil || resp.IsError() {
|
|
|
panic(exception.New("获取地址详情失败"))
|
|
|
}
|
|
|
//判断用户是否为0,设备是否有关联
|
|
|
userCount := gjson.Get(resp.String(), "0.userCount").String()
|
|
|
eqptCount := gjson.Get(resp.String(), "0.eqptCount").String()
|
|
|
if userCount == "0" {
|
|
|
if eqptCount != "0" {
|
|
|
//用户为0,并且有设备关联,取消关联后删除
|
|
|
resp, err = client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetQueryParams(map[string]string{
|
|
|
"regionId": "A",
|
|
|
"standardAddrId": standardAddrId,
|
|
|
}).Get("http://132.151.25.19:15609/prod-api/resource/list/queryEqpts")
|
|
|
if err != nil || resp.IsError() {
|
|
|
panic(exception.New("获取设备详情失败"))
|
|
|
}
|
|
|
nodeID := gjson.Get(resp.String(), "0.eqptNodeId").Int()
|
|
|
//取消关联
|
|
|
resp, err = client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetBody(map[string]interface{}{
|
|
|
"eqptNodeIds": []int64{nodeID},
|
|
|
"standardAddrId": standardAddrId,
|
|
|
"oldAddrId": standardAddrId,
|
|
|
"regionId": "A",
|
|
|
}).Post("http://132.151.25.19:15609/prod-api/resource/list/updateEqptStandAddress")
|
|
|
logkit.Info("已取消关联:" + gjson.Get(this.String(), "detailName").String())
|
|
|
m := this.Map()
|
|
|
resultMap := make(map[string]interface{})
|
|
|
for k, v := range m {
|
|
|
resultMap[k] = v.Value()
|
|
|
}
|
|
|
resp, err = client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetBody(resultMap).Post("http://132.151.25.19:15609/prod-api/address/standard/confirm/invalid")
|
|
|
if err != nil || resp.IsError() || gjson.Get(resp.String(), "code").Int() != 200 {
|
|
|
panic(exception.New("有用户,无法删除:" + gjson.Get(this.String(), "detailName").String()))
|
|
|
}
|
|
|
resp, err = client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetBody(resultMap).Put("http://132.151.25.19:15609/prod-api/address/standard/invalid")
|
|
|
if err != nil || resp.IsError() || gjson.Get(resp.String(), "code").Int() != 200 {
|
|
|
panic(exception.New("Invalid失败"))
|
|
|
}
|
|
|
logkit.Info("已删除:" + gjson.Get(this.String(), "detailName").String())
|
|
|
} else {
|
|
|
//用户为0,并且没有设备关联,直接删除
|
|
|
m := this.Map()
|
|
|
resultMap := make(map[string]interface{})
|
|
|
for k, v := range m {
|
|
|
resultMap[k] = v.Value()
|
|
|
}
|
|
|
resp, err = client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetBody(resultMap).Post("http://132.151.25.19:15609/prod-api/address/standard/confirm/invalid")
|
|
|
if err != nil || resp.IsError() || gjson.Get(resp.String(), "code").Int() != 200 {
|
|
|
panic(exception.New("有用户,无法删除:" + gjson.Get(this.String(), "detailName").String()))
|
|
|
}
|
|
|
resp, err = client.R().
|
|
|
SetHeaders(map[string]string{
|
|
|
"Authorization": "HaoXian " + cast.ToString(configkit.Get("token", "")),
|
|
|
"Content-Type": "application/json;charset=UTF-8",
|
|
|
"Cookie": "Admin-Expires-In=720; Admin-Token=" + cast.ToString(configkit.Get("token", "")),
|
|
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
|
|
|
}).
|
|
|
SetBody(resultMap).Put("http://132.151.25.19:15609/prod-api/address/standard/invalid")
|
|
|
if err != nil || resp.IsError() || gjson.Get(resp.String(), "code").Int() != 200 {
|
|
|
panic(exception.New("Invalid失败"))
|
|
|
}
|
|
|
logkit.Info("已删除:" + gjson.Get(this.String(), "detailName").String())
|
|
|
}
|
|
|
} else {
|
|
|
logkit.Info("@@@存在用户@@@" + gjson.Get(this.String(), "detailName").String())
|
|
|
}
|
|
|
break
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func readExcelWaitDel() map[string][][]string {
|
|
|
// 打开 Excel 文件
|
|
|
f, err := excelize.OpenFile(configkit.GetString("file", "/Users/leo/Downloads/标准地址0112J待删除.xlsx"))
|
|
|
if err != nil {
|
|
|
logkit.Fatal(err)
|
|
|
}
|
|
|
defer func() {
|
|
|
// 关闭文件
|
|
|
if err := f.Close(); err != nil {
|
|
|
logkit.Fatal(err)
|
|
|
}
|
|
|
}()
|
|
|
|
|
|
var result [][]string
|
|
|
m := make(map[string][][]string)
|
|
|
|
|
|
// 获取 Excel 表的行
|
|
|
rows, err := f.GetRows("标准地址")
|
|
|
if err != nil {
|
|
|
logkit.Fatal(err)
|
|
|
}
|
|
|
|
|
|
// 遍历每一行,从第二行开始
|
|
|
for i, row := range rows {
|
|
|
if i == 0 {
|
|
|
// 跳过标题行
|
|
|
continue
|
|
|
}
|
|
|
if len(row) >= 14 { // 确保至少有 4 列
|
|
|
currentRow := []string{row[0], row[3], row[5], row[14]} //0标准地址id 3地址层级 5上级地址id 14区县编码
|
|
|
result = append(result, currentRow)
|
|
|
m[row[3]] = append(m[row[3]], currentRow)
|
|
|
}
|
|
|
}
|
|
|
return m
|
|
|
}
|